• C# 如何在一张大图片中快速找到另外一张图片(两种方式)?


      自己写了一种,速度不是很快,但是能够实现

           var findpic = new FindPic();
                var rec = findpic.FindPicture(@"C:\Users\zaranet\Desktop\xiao.png", @"C:\Users\zaranet\Desktop\da.png", 10);
                MessageBox.Show(rec[0].X +","+rec[0].Y);

    Find类,在这其中先删除了最外边界的高宽,最后注意循环足够rate则直接返回。

        class FindPic
        {
            #region 找图
            /// <summary>
            /// 查找图片,不能镂空
            /// </summary>
            /// <param name="subPic">要查找坐标的小图</param>
            /// <param name="parPic">在哪个大图里查找</param>
            /// <param name="errorRange">容错,单个色值范围内视为正确0~255</param>
            /// <param name="searchRect">如果为empty,则默认查找整个图像</param>
            /// <param name="matchRate">图片匹配度,默认90%</param>
            /// <param name="isFindAll">是否查找所有相似的图片</param>
            /// <returns>返回查找到的图片的中心点坐标</returns>
            public List<System.Drawing.Point> FindPicture(string subPic, string parPic, byte errorRange = 0, Rectangle searchRect = new System.Drawing.Rectangle(), double matchRate = 0.9, bool isFindAll = false)
            {
                List<System.Drawing.Point> ListPoint = new List<System.Drawing.Point>();
                var subBitmap = new Bitmap(subPic);
                var parBitmap = new Bitmap(parPic);
                int subWidth = subBitmap.Width;
                int subHeight = subBitmap.Height;
                int parWidth = parBitmap.Width;
                int parHeight = parBitmap.Height;
                if (searchRect.IsEmpty)
                {
                    searchRect = new 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 Rectangle(0, 0, subBitmap.Width, subBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                var parData = parBitmap.LockBits(new 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;
            }
            #endregion
            public 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;
            }
            public 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;
            }
        }

    最后项目实施发现速度不快,只能弃用,网上查询 发现有AForge实现方式。引用

    private void button3_Click(object sender, EventArgs e)
            {
                System.Drawing.Bitmap sourceImage = ConvertToFormat(System.Drawing.Image.FromFile(@"C:\Users\zaranet\Desktop\da.png"), PixelFormat.Format24bppRgb);
                System.Drawing.Bitmap template = ConvertToFormat(System.Drawing.Image.FromFile(@"C:\Users\zaranet\Desktop\xiao.png"), PixelFormat.Format24bppRgb); 
                // create template matching algorithm's instance
                // (set similarity threshold to 92.5%)
    
                ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0.921f);
                // find all matchings with specified above similarity
    
                TemplateMatch[] matchings = tm.ProcessImage(sourceImage, template);
                // highlight found matchings
    
                BitmapData data = sourceImage.LockBits(
                    new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
                    ImageLockMode.ReadWrite, sourceImage.PixelFormat);
                foreach (TemplateMatch m in matchings)
                {
    
                    Drawing.Rectangle(data, m.Rectangle, Color.White);
    
                    MessageBox.Show(m.Rectangle.Location.ToString());
                    // do something else with matching
                }
                sourceImage.UnlockBits(data);
            }
            public Bitmap ConvertToFormat(System.Drawing.Image image, PixelFormat format)
            {
                Bitmap copy = new Bitmap(image.Width, image.Height, format);
                using (Graphics gr = Graphics.FromImage(copy))
                {
                    gr.DrawImage(image, new Rectangle(0, 0, copy.Width, copy.Height));
                }
                return copy;
            }

    速度略快吧。

  • 相关阅读:
    MyBatis中文文档
    网络编程
    Django
    Django
    Django
    Django
    Django
    Django
    Django
    Django
  • 原文地址:https://www.cnblogs.com/ZaraNet/p/16847422.html
Copyright © 2020-2023  润新知