如何将此方法转换为更快地使用 LockBits 并且它将比较 3 个或更多图像?
Posted
技术标签:
【中文标题】如何将此方法转换为更快地使用 LockBits 并且它将比较 3 个或更多图像?【英文标题】:How can convert this method ot use LockBits to be faster and that it will compare 3 images or more? 【发布时间】:2014-11-28 17:23:38 【问题描述】:该方法获取两个图像。一种是来自资源的始终相同的图像。 第二个是下载的图像,可能与资源中的图像相同或不同。 然后方法返回tre或false。
//*** This function compare images region specific area ( in this case the "radar close" text area ) ***\\
public bool ImageComparison(Bitmap Image1, Bitmap Image2, Rectangle Rect, double tol)
//Logger.Write("Rect >>>> " + Rect.ToString());
double color_distance;
int x;
int y;
bool different = false;
textbox3 = Rect.ToString();
//if pictures are not of same size, return that they are different
if (Image1.Width != Image2.Width || Image1.Height != Image2.Height)
Logger.Write("Image1 Width >>>> " + Image1.Width.ToString());
Logger.Write("Image2 Width >>>> " + Image2.Width.ToString());
Logger.Write("Image1 Height >>>> " + Image1.Height.ToString());
Logger.Write("Image2 Height >>>> " + Image2.Height.ToString());
Logger.Write("Returned False images were different size");
MessageBox.Show("Images are different Size");
textbox1 = "";
textbox2 = "";
textbox3 = "";
return false;
//Iterate over the Rect
for (x = Rect.X; x < Rect.X + Rect.Width; ++x)
for (y = Rect.Y; y < Rect.Y + Rect.Height; ++y)
//check, if x and y are inside the picture
if (x >= 0 && x < Image1.Width && y >= 0 && y < Image1.Height &&
x < Image2.Width && y < Image2.Height)
Color c = Image1.GetPixel(x, y);
textbox1 = c.ToString();
Color c2 = Image2.GetPixel(x, y);
textbox2 = c2.ToString();
double Dr = c.R - c2.R;
double Dg = c.G - c2.G;
double Db = c.B - c2.B;
color_distance = Math.Sqrt(Dr * Dr + Dg * Dg + Db * Db);
if (color_distance > tol)
different = true;
break;
else
throw new Exception(" Hello!! your region is way off!!!.. major bug!");
if (different)
break;
//Logger.Write("differenet bool is now >>>> " + different.ToString());
return !different;
问题是我正在使用 GetPixel 和 SetPixel,它在某些下载的图像上可能太慢了。所以我想把它改成LockBits。 第二件事是我想改变方法,所以现在它会得到 3 张图片,不仅 2 张而且第三张图片也将来自资源。
这就是我在form1中使用方法的方式:
if (ImagesComparion1.ImageComparison(File1, file2, image_scan_text_rect, 50) == true)
File1.Dispose();
Properties.Resources.RadarImageClose.Dispose();
label18.Text = "The Radar Is Not Active Now";
label18.Visible = true;
else
File1.Dispose();
Properties.Resources.RadarImageClose.Dispose();
label18.Text = "The Radar Is Active Now";
label18.Visible = true;
而file2是资源中的图片:
file2 = Properties.Resources.RadarImageClose;
而File1是下载的图片:
File1 = new Bitmap(Properties.Resources.RadarImageClose);
现在我想改变制作这个东西的方法:
使用 LockBits 代替 GetPixel 和 SetPixel。
获取3张图片,进行两次对比处理:
首先将第一个资源图像file2与File1进行比较,然后在将同样是资源图像的file3与File1进行比较的方法中进行另一个比较过程。
我将方法顶部更改为:
public bool ImageComparison(Bitmap Image1, Bitmap Image2, Bitmap Image3, Bitmap Image4, Rectangle Rect, double tol)
Image1 Image 3 和 Image4 都是从资源中获取资源图片。 Image2 是下载的图片。
我需要使用 LockBits 并首先将 Image1 与 Image2 进行比较,然后将 Image3 与 Image2 进行比较,然后将 Image4 与 Image2 进行比较。
如果其中一个比较结果为真,则该方法返回真,而不进行其余比较,如果所有比较均返回结果为假,则该方法返回假。
这是我做的一个测试,我拿了 3 个图片框并放在左边和中间的图像中,里面的文字都有不同的文字,但都意味着雷达接近。在右边我有一个打开的雷达图像。我在同一区域的所有它们上画了一个红色矩形,它们都在同一区域。
【问题讨论】:
【参考方案1】:使用此功能比较两个图像:
private bool ImageComparison(Bitmap Image1, Bitmap Image2, Rectangle Rect, double tol)
int x, y, p, stride1, stride2;
int bytes, bytesPerPixel;
byte[] rgbValues1;
byte[] rgbValues2;
double Dr, Dg, Db, color_distance;
IntPtr ptr;
Rectangle rect;
BitmapData bitmap_Data;
if ( (Image1.Width != Image2.Width) || (Image1.Height != Image2.Height) )
MessageBox.Show("Images are different Size");
return false;
if (Rect.X < 0 || Rect.Y < 0 || ((Rect.X + Rect.Width) > Image1.Width) || ((Rect.Y + Rect.Height) > Image1.Height))
MessageBox.Show("Hello!! your region is way off!!!.. major bug!");
return false;
rect = new Rectangle(0, 0, Image1.Width, Image1.Height);
//Lock bitmap to copy its color information fast
bitmap_Data = Image1.LockBits(rect, ImageLockMode.ReadWrite, Image1.PixelFormat);
ptr = bitmap_Data.Scan0;
stride1 = bitmap_Data.Stride;
bytes = bitmap_Data.Stride * Image1.Height;
rgbValues1 = new byte[bytes];
//copy color information to rgbValues array
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues1, 0, bytes);
//we are done copying so unlock bitmap. We dont need it anymore
Image1.UnlockBits(bitmap_Data);
rect = new Rectangle(0, 0, Image2.Width, Image2.Height);
//Lock bitmap to copy its color information fast
bitmap_Data = Image2.LockBits(rect, ImageLockMode.ReadWrite, Image2.PixelFormat);
ptr = bitmap_Data.Scan0;
stride2 = bitmap_Data.Stride;
bytes = bitmap_Data.Stride * Image2.Height;
rgbValues2 = new byte[bytes];
//copy color information to rgbValues array
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues2, 0, bytes);
//we are done copying so unlock bitmap. We dont need it anymore
Image2.UnlockBits(bitmap_Data);
if (stride1 != stride2) //different pixel format
MessageBox.Show("Different pixel format");
return false;
bytesPerPixel = Image.GetPixelFormatSize(Image1.PixelFormat) / 8;
//scan images pixel per pixel
for (y = 0; y < Image1.Height; y++)
for (x = 0; x < Image1.Width; x++)
p = y * stride1 + x * bytesPerPixel;
Dr = (double)(rgbValues1[p + 2] - rgbValues2[p + 2]);
Dg = (double)(rgbValues1[p + 1] - rgbValues2[p + 1]);
Db = (double)(rgbValues1[p] - rgbValues2[p]);
color_distance = Math.Sqrt(Dr * Dr + Dg * Dg + Db * Db);
if (color_distance > tol)
return false;
return true;
如果您想比较多个,请将它们插入到 列表中:
List<Bitmap> bitmapListToCompare = new List<Bitmap>();
bitmapListToCompare.Add(....);
bitmapListToCompare.Add(....);
....
然后:
int i;
bool bl;
Bitmap bitmapToCompareWith = new Bitmap(...); //your bitmap to use as reference
//for your comparisons
for (i = 0; i < bitmapListToCompare.Count; i++)
bl = ImageComparison(bitmapToCompareWith, bitmapListToCompare[i], ...., ....);
if (bl == false)
MessageBox.Show("Image " + i.ToString() + " was different!");
break;
【讨论】:
比较有问题。现在图像已下载,资源中的图像完全相同。但是该方法返回 false 并显示“不同的像素格式”并且还显示“雷达现在处于活动状态”,而它假设返回 true 并且雷达现在不应该处于活动状态。这是为了比较两个下载的图片和资源。 @JamesAharon ...资源中的完全相同。你怎么知道?在您看来它可能看起来相同,但正如消息中所说,它们具有不同的格式,例如,一种可能是 24 位,另一种可能是其他格式。 你可以在这里看到ims.gov.il/IMS/tazpiot/RainRadar.htm雷达这是我正在下载的图像并将其与资源中的图像进行比较,它们是相同的,矩形应该告诉它是相同的并返回true并且雷达很近。 @JamesAharon 他们的文件大小一样吗? γηράσκω δ' 在我使用的旧方法中,当链接中的雷达与此图像和内部文本一起使用时,它工作正常,我确实将它与它显示的资源进行了比较,当有在没有此文本的链接图像中,它显示雷达处于打开状态。它在旧方法中起作用,也许扫描或比较不够好,但是当雷达打开和关闭并且它起作用时,我看到它确实起作用了。以上是关于如何将此方法转换为更快地使用 LockBits 并且它将比较 3 个或更多图像?的主要内容,如果未能解决你的问题,请参考以下文章