码迷,mamicode.com
首页 > Windows程序 > 详细

C# 之屏幕找图

时间:2015-09-15 18:21:54      阅读:325      评论:0      收藏:0      [点我收藏+]

标签:

  • 引言

    最近,由于工作上的某些原因,又要写类似于外挂的程序,又要用到一个屏幕找图功能,很多程序(eg:按键精灵)都提供了类似的功能,其实在这之前,我也查找过很多类似的C#方法,因为之前有一个试过没有用得起,所以最后就放弃了,知道现在都是使用的自己写的一个,相对来说,除了效率比较慢,没有太大的问题。不过就是由于效率不高,后面又想了其他的一些解决办法。

  • 基础+贴代码。

    因为是一些图片处理和操作,所以必不可少的会用到C# GDI+的一些基本知识,对于这个网上应该也有很多,大家可以拿来学习和参考。

    再者,其实细细想一下,其实应该很简单,为什么呢,因为就是一个一个像素的比较,比较颜色差异,没有差异就通过,有差异,就继续查找,知道找到必须要,且完全匹配就OK。

    于是乎有了下面的代码。1.0

  // 基础代码和调用代码 (注释基本,略,后面又没有添加,多多包涵)

技术分享
 1 public class ImageManager
 2     {
 3         public static Point Compare(Bitmap bigImage, Bitmap smallImage)
 4         {
 5             for (int i = 0; i < bigImage.Width; i++)
 6             {
 7                 for (int j = 0; j < bigImage.Height; j++)
 8                 {
 9                     Color c1 = bigImage.GetPixel(i, j);
10                     Color c2 = smallImage.GetPixel(0, 0);
11 
12                     // 颜色相等,且没有超出边界
13                     if (Compare(c1, c2) && bigImage.Width >= (i + smallImage.Width) && bigImage.Height >= (j + smallImage.Height))
14                     {
15                         bool iscontinue = false;
16                         for (int x = 0; x < smallImage.Width; x++)
17                         {
18                             for (int y = 0; y < smallImage.Height; y++)
19                             {
20                                 Color c3 = smallImage.GetPixel(x, y);
21                                 Color c4 = bigImage.GetPixel(i + x, j + y);
22                                 if (!Compare(c3, c4))
23                                 {
24                                     iscontinue = true;
25                                     break;
26                                 }
27                             }
28 
29                             if (iscontinue)
30                             {
31                                 break;
32                             }
33                         }
34 
35                         if (!iscontinue)
36                         {
37                             return new Point(i, j);
38                         }
39                     }
40                 }
41             }
42 
43             return new Point(-1, -1);
44         }
45 
46         private static bool Compare(Color c1, Color c2)
47         {
48             if (c1.A == c2.A && c1.R == c2.R && c1.B == c2.B && c1.G == c2.G)
49             {
50                 return true;
51             }
52 
53             return false;
54         }
55     }
C# ImageManager 1.0
技术分享
 1     /// <summary>
 2         /// 得到指定图片顶点
 3         /// </summary>
 4         /// <param name="picName">图片名称</param>
 5         private Point GetPicturePoint(string picName)
 6         {
 7             Bitmap image = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
 8             Graphics imgGraphics = Graphics.FromImage(image);
 9 
10             //设置截屏区域 
11             imgGraphics.CopyFromScreen(0, 0, 0, 0, new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height));
12 
13             // 然后从截屏图片中查找指定图片
14             string taskImagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "image", picName);
15             Image img = Image.FromFile(taskImagePath);
16 
17             var result = ImageManager.Compare(CloseImg(image), CloseImg(img));
18 
19             return result;
20         }
21 
22         private Bitmap CloneImg(Image img)
23         {
24             using (MemoryStream mostream = new MemoryStream())
25             {
26                 Bitmap bmp = new Bitmap(img);
27                 bmp.Save(mostream, System.Drawing.Imaging.ImageFormat.Jpeg);//将图像以指定的格式存入缓存内存流
28                 byte[] bt = new byte[mostream.Length];
29                 mostream.Position = 0;//设置流的初始位置
30                 mostream.Read(bt, 0, Convert.ToInt32(bt.Length));
31 
32                 return bmp;
33             }
34         }
ImageManager 调用方法

  

    由于效率不敢恭维,没办法,又想其他的法子吧,于是乎想到了多线程。。

  • 多线程处理,效率没啥子提升感觉。

    由于代码的处理方式,造成了,循环太多,处理的比较的次数很多,运算量大。。

    多线程怎么处理呢,于是想到了,把整个屏幕分成很多块小图片,这样,用小图片和要查找的图片进行比较然后得到最后的结果。但是问题来了,如果,图片正好在中间怎么办。于是就把小图片,朵切割一点,多切割,需要查找的图片的宽度和高度。

    于是写成了代码,如下:

技术分享
  1 public class ImageManager
  2     {
  3         private static List<Point> result = new List<Point>();
  4 
  5         public static event Action<int, Image> DoPic;
  6 
  7         private static int width = 0;
  8 
  9         private static int height = 0;
 10 
 11         /// <summary>
 12         /// 多线程找图
 13         /// </summary>
 14         /// <param name="bigImage"></param>
 15         /// <param name="smallImage"></param>
 16         /// <returns></returns>
 17         public static Point ThreadCompare(Bitmap bigImage, Bitmap smallImage)
 18         {
 19             result = new List<Point>();
 20             // 先拆分大图成为16个小图片,每个小图片都需要加上smallImage的长宽组成一个新图片
 21             // 需要16个线程来完成。
 22             width = (int)Math.Ceiling(bigImage.Width / 4.0);
 23             height = (int)Math.Ceiling(bigImage.Height / 4.0);
 24             int maxWidth = width + smallImage.Width;
 25             int maxHeight = height + smallImage.Height;
 26             int index = 0;
 27             for (int i = 0; i < 4; i++)
 28             {
 29                 for (int j = 0; j < 4; j++)
 30                 {
 31                     Bitmap bitMap = null;
 32                     if (i == 3 && j == 3)
 33                     {
 34                         bitMap = new Bitmap(width, height);
 35                     }
 36                     else if (j == 3)
 37                     {
 38                         bitMap = new Bitmap(maxWidth, height);
 39                     }
 40                     else if (i == 3)
 41                     {
 42                         bitMap = new Bitmap(width, maxWidth);
 43                     }
 44                     else
 45                     {
 46                         bitMap = new Bitmap(maxWidth, maxHeight);
 47                     }
 48 
 49                     Graphics resultG = Graphics.FromImage(bitMap);
 50                     resultG.DrawImage(bigImage, new Rectangle(0, 0, bitMap.Width, bitMap.Height), new Rectangle(i * width, j * height, bitMap.Width, bitMap.Height), GraphicsUnit.Pixel);
 51                     resultG.Dispose();
 52 
 53                     if (DoPic != null)
 54                     {
 55                         DoPic(index, CloneImg(bitMap));
 56                     }
 57 
 58                     ThreadPool.QueueUserWorkItem(new WaitCallback(CompareThread), new object[] { bitMap, CloneImg(smallImage), i, j });
 59                     index++;
 60                 }
 61             }
 62 
 63             while (result.Count != 16)
 64             {
 65                 Thread.Sleep(50);
 66             }
 67 
 68             var point = new Point(-1, -1);
 69             if (result.Exists(p => p.X >= 0))
 70             {
 71                 point = result.Find(a => a.X >= 0);
 72             }
 73 
 74             return point;
 75         }
 76 
 77         public static Point Compare(Bitmap bigImage, Bitmap smallImage)
 78         {
 79             for (int i = 0; i < bigImage.Width; i++)
 80             {
 81                 for (int j = 0; j < bigImage.Height; j++)
 82                 {
 83                     Color c1 = bigImage.GetPixel(i, j);
 84                     Color c2 = smallImage.GetPixel(0, 0);
 85 
 86                     // 颜色相等,且没有超出边界
 87                     if (Compare(c1, c2) && bigImage.Width >= (i + smallImage.Width) && bigImage.Height >= (j + smallImage.Height))
 88                     {
 89                         bool iscontinue = false;
 90                         for (int x = 0; x < smallImage.Width; x++)
 91                         {
 92                             for (int y = 0; y < smallImage.Height; y++)
 93                             {
 94                                 Color c3 = smallImage.GetPixel(x, y);
 95                                 Color c4 = bigImage.GetPixel(i + x, j + y);
 96                                 if (!Compare(c3, c4))
 97                                 {
 98                                     iscontinue = true;
 99                                     break;
100                                 }
101                             }
102 
103                             if (iscontinue)
104                             {
105                                 break;
106                             }
107                         }
108 
109                         if (!iscontinue)
110                         {
111                             return new Point(i, j);
112                         }
113                     }
114                 }
115             }
116 
117             return new Point(-1, -1);
118         }
119 
120         private static void CompareThread(object obj)
121         {
122             object[] objs = obj as object[];
123             Bitmap bigImage = objs[0] as Bitmap;
124             Bitmap smallImage = objs[1] as Bitmap;
125             int indexI = Convert.ToInt32(objs[2]);
126             int indexJ = Convert.ToInt32(objs[3]);
127             bool isbreak = false;
128             Point p = new Point(-1, -1);
129             for (int i = 0; i < bigImage.Width; i++)
130             {
131                 for (int j = 0; j < bigImage.Height; j++)
132                 {
133                     Color c1 = bigImage.GetPixel(i, j);
134                     Color c2 = smallImage.GetPixel(0, 0);
135 
136                     // 颜色相等,且没有超出边界
137                     if (Compare(c1, c2) && bigImage.Width >= (i + smallImage.Width) && bigImage.Height >= (j + smallImage.Height))
138                     {
139                         bool iscontinue = false;
140                         for (int x = 0; x < smallImage.Width; x++)
141                         {
142                             for (int y = 0; y < smallImage.Height; y++)
143                             {
144                                 Color c3 = smallImage.GetPixel(x, y);
145                                 Color c4 = bigImage.GetPixel(i + x, j + y);
146                                 if (!Compare(c3, c4))
147                                 {
148                                     iscontinue = true;
149                                     break;
150                                 }
151                             }
152 
153                             if (iscontinue)
154                             {
155                                 break;
156                             }
157                         }
158 
159                         if (!iscontinue)
160                         {
161                             isbreak = true;
162                             p = new Point(i + indexI * width, j + indexJ * height);
163                             break;
164                         }
165                     }
166                 }
167 
168                 if (isbreak)
169                 {
170                     break;
171                 }
172             }
173 
174             result.Add(p);
175         }
176 
177         private static bool Compare(Color c1, Color c2)
178         {
179             if (c1.A == c2.A && c1.R == c2.R && c1.B == c2.B && c1.G == c2.G)
180             {
181                 return true;
182             }
183 
184             return false;
185         }
186 
187         private static Bitmap CloneImg(Image img)
188         {
189             using (MemoryStream mostream = new MemoryStream())
190             {
191                 Bitmap bmp = new Bitmap(img);
192                 bmp.Save(mostream, System.Drawing.Imaging.ImageFormat.Jpeg);//将图像以指定的格式存入缓存内存流
193                 byte[] bt = new byte[mostream.Length];
194                 mostream.Position = 0;//设置留的初始位置
195                 mostream.Read(bt, 0, Convert.ToInt32(bt.Length));
196 
197                 return bmp;
198             }
199         }
200     }
ImageManager 2.0

    终于支持多线程了,然后测试了一下,效率略有增加,不过没有太大的感觉。但是用别人的工具,感觉特别快,因为软件上面写的50,60毫秒,我就想啊,到底是哪里拖慢了速度呢。。。当然,没有想到。所以这里就抛砖引玉了。。。

  • 总结

    博客园的编辑器,每次我都感觉自己不会用,别人写的文章,编辑出来效果杠杠的,为什么我这个不行呢,感觉有点坑。

    最后,欢迎拍砖。

    谢谢支持。

 

C# 之屏幕找图

标签:

原文地址:http://www.cnblogs.com/Supperlitt/p/4810891.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!