• C#_查找图片(按键精灵找图)


    一、class

        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;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127

    二、代码

      前台操作,自行加延迟或锁定键盘鼠标。

    1、全屏找图

                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);
    
    • 1
    • 2
    • 3

    2、区域找图

                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);
    
    • 1
    • 2
    • 3
    • 4

    3、循环找图

                do
                {
                    points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", rectangle);
                    Thread.Sleep(1000);
                } while (points.Count == 0);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4、循环找图,避免死循环

                //查找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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5、找图后鼠标点击

      鼠标点击相关代码见此处。

                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);
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    JavaScript 对象
    【探索Linux】P.39(传输层 —— TCP的三次 “握手” 和四次 “挥手” )
    [附源码]计算机毕业设计基于springboot框架的食品安全监督平台的设计与实现
    去除pdf/word的水印艺术字
    智慧城市建设的原则及规划目标
    Vue3 set up 的使用
    你们github 官网的代码 npm i 运行报错怎么解决啊
    详细总结SoC、DSP、MCU、GPU和FPGA等基础概念
    【神印王座】龙皓晨竟然上了头版头条!内容违背,新闻真实性原则
    cudann官网上不见了,找不到了安装CUDA和CUDANN时,发现CUDANN不见了,官网甚至找不到一丝它的信息,公告也没有
  • 原文地址:https://blog.csdn.net/qq_26244423/article/details/134421223