internal class Picture
{
///
/// 查找图片,不能镂空
///
///
/// 如果为empty,则默认查找整个图像
/// 图片匹配度,默认90%
/// 容错,单个色值范围内视为正确0~255
/// 是否查找所有相似的图片
/// 返回查找到的图片的中心点坐标
public List<System.Drawing.Point> FindPicture(string subPic, System.Drawing.Rectangle searchRect, double matchRate = 0.9, byte errorRange = 0, bool isFindAll = false)
{
List<System.Drawing.Point> ListPoint = new List<System.Drawing.Point>();
var subBitmap = new Bitmap(subPic);
//创建Bitmap位图类(尺寸与分辨率相同)
Bitmap parBitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
//从一个继承自Image类的对象中创建Graphics对象
Graphics g = Graphics.FromImage(parBitmap);
//截取屏幕并复制到(g)myimage里
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height));
//保存截图
//parBitmap.Save(System.Environment.CurrentDirectory + @"\temp\test.bmp");
int subWidth = subBitmap.Width;
int subHeight = subBitmap.Height;
int parWidth = parBitmap.Width;
int parHeight = parBitmap.Height;
if (searchRect.IsEmpty)
{
searchRect = new System.Drawing.Rectangle(0, 0, parBitmap.Width, parBitmap.Height);
}
var searchLeftTop = searchRect.Location;
var searchSize = searchRect.Size;
System.Drawing.Color startPixelColor = subBitmap.GetPixel(0, 0);
var subData = subBitmap.LockBits(new System.Drawing.Rectangle(0, 0, subBitmap.Width, subBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var parData = parBitmap.LockBits(new System.Drawing.Rectangle(0, 0, parBitmap.Width, parBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var byteArrarySub = new byte[subData.Stride * subData.Height];
var byteArraryPar = new byte[parData.Stride * parData.Height];
Marshal.Copy(subData.Scan0, byteArrarySub, 0, subData.Stride * subData.Height);
Marshal.Copy(parData.Scan0, byteArraryPar, 0, parData.Stride * parData.Height);
var iMax = searchLeftTop.Y + searchSize.Height - subData.Height;//行
var jMax = searchLeftTop.X + searchSize.Width - subData.Width;//列
int smallOffsetX = 0, smallOffsetY = 0;
int smallStartX = 0, smallStartY = 0;
int pointX = -1; int pointY = -1;
for (int i = searchLeftTop.Y; i < iMax; i++)
{
for (int j = searchLeftTop.X; j < jMax; j++)
{
//大图x,y坐标处的颜色值
int x = j, y = i;
int parIndex = i * parWidth * 4 + j * 4;
var colorBig = System.Drawing.Color.FromArgb(byteArraryPar[parIndex + 3], byteArraryPar[parIndex + 2], byteArraryPar[parIndex + 1], byteArraryPar[parIndex]);
;
if (ColorAEqualColorB(colorBig, startPixelColor, errorRange))
{
smallStartX = x - smallOffsetX;//待找的图X坐标
smallStartY = y - smallOffsetY;//待找的图Y坐标
int sum = 0;//所有需要比对的有效点
int matchNum = 0;//成功匹配的点
for (int m = 0; m < subHeight; m++)
{
for (int n = 0; n < subWidth; n++)
{
int x1 = n, y1 = m;
int subIndex = m * subWidth * 4 + n * 4;
var color = System.Drawing.Color.FromArgb(byteArrarySub[subIndex + 3], byteArrarySub[subIndex + 2], byteArrarySub[subIndex + 1], byteArrarySub[subIndex]);
sum++;
int x2 = smallStartX + x1, y2 = smallStartY + y1;
int parReleativeIndex = y2 * parWidth * 4 + x2 * 4;//比对大图对应的像素点的颜色
var colorPixel = System.Drawing.Color.FromArgb(byteArraryPar[parReleativeIndex + 3], byteArraryPar[parReleativeIndex + 2], byteArraryPar[parReleativeIndex + 1], byteArraryPar[parReleativeIndex]);
if (ColorAEqualColorB(colorPixel, color, errorRange))
{
matchNum++;
}
}
}
if ((double)matchNum / sum >= matchRate)
{
Console.WriteLine((double)matchNum / sum);
pointX = smallStartX + (int)(subWidth / 2.0);
pointY = smallStartY + (int)(subHeight / 2.0);
var point = new System.Drawing.Point(pointX, pointY);
if (!ListContainsPoint(ListPoint, point, 10))
{
ListPoint.Add(point);
}
if (!isFindAll)
{
goto FIND_END;
}
}
}
//小图x1,y1坐标处的颜色值
}
}
FIND_END:
subBitmap.UnlockBits(subData);
parBitmap.UnlockBits(parData);
subBitmap.Dispose();
parBitmap.Dispose();
GC.Collect();
return ListPoint;
}
bool ColorAEqualColorB(System.Drawing.Color colorA, System.Drawing.Color colorB, byte errorRange = 10)
{
return colorA.A <= colorB.A + errorRange && colorA.A >= colorB.A - errorRange &&
colorA.R <= colorB.R + errorRange && colorA.R >= colorB.R - errorRange &&
colorA.G <= colorB.G + errorRange && colorA.G >= colorB.G - errorRange &&
colorA.B <= colorB.B + errorRange && colorA.B >= colorB.B - errorRange;
}
bool ListContainsPoint(List<System.Drawing.Point> listPoint, System.Drawing.Point point, double errorRange = 10)
{
bool isExist = false;
foreach (var item in listPoint)
{
if (item.X <= point.X + errorRange && item.X >= point.X - errorRange && item.Y <= point.Y + errorRange && item.Y >= point.Y - errorRange)
{
isExist = true;
}
}
return isExist;
}
}
}
前台操作,自行加延迟或锁定键盘鼠标。
Picture picture = new Picture();
List<System.Drawing.Point> points = new List<System.Drawing.Point>();
points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", Rectangle.Empty);
Picture picture = new Picture();
List<System.Drawing.Point> points = new List<System.Drawing.Point>();
Rectangle rectangle = new Rectangle(50, 50, 300, 300);
points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", rectangle);
do
{
points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", rectangle);
Thread.Sleep(1000);
} while (points.Count == 0);
//查找10次,找不到跳出循环
int i = 0;
do
{
points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", rectangle);
i++;
Thread.Sleep(1000);
} while (points.Count == 0 && i < 10);
鼠标点击相关代码见此处。
if (points.Count > 0)
{
//移动鼠标到坐标点
MouseHelper.SetCursorPos(points[0].X, points[0].Y);
//鼠标左键单击
MouseHelper.mouse_event(MouseHelper.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
MouseHelper.mouse_event(MouseHelper.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}