markus / ImageComparer / Markus.ImageCompare / ImageCompareBase.cs @ 2a2e72c2
이력 | 보기 | 이력해설 | 다운로드 (10.8 KB)
1 | 24c5e56c | taeseongkim | using OpenCvSharp; |
---|---|---|---|
2 | 38d69491 | taeseongkim | using OpenCvSharp.Extensions; |
3 | 24c5e56c | taeseongkim | using System; |
4 | using System.Collections.Generic; |
||
5 | using System.Drawing; |
||
6 | using System.Drawing.Imaging; |
||
7 | using System.IO; |
||
8 | using System.Linq; |
||
9 | using System.Net; |
||
10 | using System.Runtime.InteropServices; |
||
11 | using System.Text; |
||
12 | 38d69491 | taeseongkim | using System.Threading; |
13 | 24c5e56c | taeseongkim | using System.Threading.Tasks; |
14 | 38d69491 | taeseongkim | using static System.Net.Mime.MediaTypeNames; |
15 | 24c5e56c | taeseongkim | using Point = System.Drawing.Point; |
16 | using Size = System.Drawing.Size; |
||
17 | |||
18 | namespace Markus.Image |
||
19 | { |
||
20 | public class ImageCompareBase : IDisposable |
||
21 | { |
||
22 | Mat OriginalImageData = null; |
||
23 | Mat TargatImageData = null; |
||
24 | |||
25 | double contoursLongCount = 0; |
||
26 | double ComparisonCount = 0; |
||
27 | public CompareProgress Progress = new CompareProgress(); |
||
28 | |||
29 | private void SetStatus(string message,double percentage,CompareStatus status) |
||
30 | { |
||
31 | System.Diagnostics.Debug.WriteLine(percentage); |
||
32 | |||
33 | Progress.Message = message; |
||
34 | Progress.Percentage = percentage; |
||
35 | Progress.Status = status; |
||
36 | } |
||
37 | |||
38 | /// <summary> |
||
39 | /// Originalbitmap에서 TargatBitmap과 비교하여 틀린 부분의 데이터를 Emgu.CV.TDepth형식으로 반환한다. |
||
40 | /// </summary> |
||
41 | /// <param name="Originalbitmap">원본 이미지</param> |
||
42 | /// <param name="TargatBitmap">비교대상 이미지</param> |
||
43 | /// <returns>Emgu.CV.TDepth형식의 byte[,,]</returns> |
||
44 | protected Mat MathchesImageData(System.Drawing.Bitmap Originalbitmap, System.Drawing.Bitmap TargatBitmap) |
||
45 | { |
||
46 | Mat result = new Mat(); |
||
47 | |||
48 | try |
||
49 | { |
||
50 | SetStatus("Image Load", 0, CompareStatus.Loading); |
||
51 | |||
52 | 38d69491 | taeseongkim | //Originalbitmap = To24Bpp(Originalbitmap, Originalbitmap.Size); |
53 | //TargatBitmap = To24Bpp(TargatBitmap, Originalbitmap.Size); |
||
54 | |||
55 | 24c5e56c | taeseongkim | Originalbitmap = ChangeBitmapFormatAndSize(Originalbitmap, Originalbitmap.Size, PixelFormat.Format24bppRgb); |
56 | TargatBitmap = ChangeBitmapFormatAndSize(TargatBitmap, Originalbitmap.Size, PixelFormat.Format24bppRgb); |
||
57 | |||
58 | // 원본이미지의 크키와 Format24bppRgb로 타켓 이미지를 변경 |
||
59 | // 크기가 틀린 경우 비교시 바이트배열 오류 발생 |
||
60 | 38d69491 | taeseongkim | |
61 | 24c5e56c | taeseongkim | OriginalImageData = OpenCvSharp.Extensions.BitmapConverter.ToMat(Originalbitmap); |
62 | TargatImageData = OpenCvSharp.Extensions.BitmapConverter.ToMat(TargatBitmap); |
||
63 | 38d69491 | taeseongkim | var grayOriginal = new OpenCvSharp.Mat(); |
64 | var grayTargat = new OpenCvSharp.Mat(); |
||
65 | 24c5e56c | taeseongkim | |
66 | if (OriginalImageData.Size() != TargatImageData.Size()) |
||
67 | { |
||
68 | Cv2.Resize(TargatImageData, TargatImageData, OriginalImageData.Size()); |
||
69 | } |
||
70 | 38d69491 | taeseongkim | |
71 | Cv2.CvtColor(OriginalImageData, grayOriginal, ColorConversionCodes.BGR2GRAY); |
||
72 | Cv2.CvtColor(TargatImageData, grayTargat, ColorConversionCodes.BGR2GRAY); |
||
73 | //Cv2.ImShow("grayOriginal", grayOriginal); |
||
74 | //Cv2.ImShow("grayTargat", grayTargat); |
||
75 | 24c5e56c | taeseongkim | |
76 | 38d69491 | taeseongkim | Mat outputData = new Mat(grayTargat.Size(), MatType.CV_8UC1); |
77 | 24c5e56c | taeseongkim | |
78 | 38d69491 | taeseongkim | Cv2.Absdiff(grayOriginal, grayTargat, outputData); |
79 | 24c5e56c | taeseongkim | |
80 | // 틀린부분을 반환 |
||
81 | Cv2.BitwiseNot(outputData, result); |
||
82 | 38d69491 | taeseongkim | //Cv2.ImShow("result", result); |
83 | 24c5e56c | taeseongkim | } |
84 | catch (Exception ex) |
||
85 | { |
||
86 | throw ex; |
||
87 | } |
||
88 | finally |
||
89 | { |
||
90 | } |
||
91 | |||
92 | return result; |
||
93 | } |
||
94 | |||
95 | 38d69491 | taeseongkim | public System.Drawing.Bitmap ChangeBitmapFormatAndSize(System.Drawing.Bitmap bitmap, Size newSize, PixelFormat pixelFormat) |
96 | 24c5e56c | taeseongkim | { |
97 | 38d69491 | taeseongkim | Bitmap result; |
98 | |||
99 | result = new Bitmap(newSize.Width, newSize.Height, pixelFormat); |
||
100 | Graphics g = Graphics.FromImage(result); |
||
101 | g.DrawImage(bitmap, new Rectangle(0, 0, newSize.Width, newSize.Height), 0, 0, newSize.Width, newSize.Height, GraphicsUnit.Pixel); |
||
102 | //g.DrawImage(bitmap, 0, 0, newSize.Width, newSize.Height); |
||
103 | g.Save(); |
||
104 | g.Dispose(); |
||
105 | 24c5e56c | taeseongkim | |
106 | return result; |
||
107 | } |
||
108 | |||
109 | /// <summary> |
||
110 | /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환 |
||
111 | /// </summary> |
||
112 | /// <param name="data"></param> |
||
113 | /// <param name="block"></param> |
||
114 | /// <returns></returns> |
||
115 | protected List<System.Windows.Rect> GetMatchPixels(Mat data, Size block) |
||
116 | { |
||
117 | SetStatus("Detection", 0, CompareStatus.Detection); |
||
118 | |||
119 | int width = data.Cols; |
||
120 | int height = data.Rows; |
||
121 | |||
122 | List<System.Windows.Rect> results = new List<System.Windows.Rect>(); |
||
123 | |||
124 | System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); |
||
125 | stopwatch.Start(); |
||
126 | |||
127 | Mat outputMat = new Mat(data.Size(), MatType.CV_8UC1); |
||
128 | |||
129 | HierarchyIndex[] hierarchy; |
||
130 | OpenCvSharp.Point[][] contours; |
||
131 | |||
132 | OpenCvSharp.Point testpoint = new OpenCvSharp.Point(); |
||
133 | |||
134 | 38d69491 | taeseongkim | Cv2.Threshold(data, data, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu); |
135 | 24c5e56c | taeseongkim | |
136 | Cv2.FindContours(data, out contours, out hierarchy,RetrievalModes.List,ContourApproximationModes.ApproxNone, testpoint); |
||
137 | |||
138 | SetStatus("Comparison", 0, CompareStatus.Comparison); |
||
139 | contoursLongCount = contours.Sum(x => x.Count()); |
||
140 | 38d69491 | taeseongkim | |
141 | 24c5e56c | taeseongkim | var rects = contours.AsParallel() |
142 | .Select(points => GetRectList(points, block)) |
||
143 | .SelectMany(x => x); |
||
144 | |||
145 | results.AddRange(rects); |
||
146 | 38d69491 | taeseongkim | |
147 | System.Diagnostics.Debug.WriteLine(new TimeSpan(stopwatch.ElapsedTicks)); |
||
148 | |||
149 | 24c5e56c | taeseongkim | return results; |
150 | } |
||
151 | 38d69491 | taeseongkim | private List<System.Windows.Rect> GetRectList(OpenCvSharp.Point[] points, Size block) |
152 | { |
||
153 | List<System.Windows.Rect> result = new List<System.Windows.Rect>(); |
||
154 | |||
155 | Parallel.ForEach(points, point => |
||
156 | { |
||
157 | var rect = new System.Windows.Rect |
||
158 | { |
||
159 | X = point.X - block.Width / 2, |
||
160 | Y = point.Y - block.Height / 2, |
||
161 | Width = block.Width, |
||
162 | Height = block.Height |
||
163 | }; |
||
164 | |||
165 | lock (result) |
||
166 | { |
||
167 | if (!result.Any(r => r.IntersectsWith(rect))) |
||
168 | { |
||
169 | result.Add(rect); |
||
170 | } |
||
171 | } |
||
172 | |||
173 | //ComparisonCount++; |
||
174 | |||
175 | //Interlocked.Increment(ref ComparisonCount); |
||
176 | |||
177 | //SetStatus("Comparison", ComparisonCount / contoursLongCount * 100, CompareStatus.Comparison); |
||
178 | }); |
||
179 | |||
180 | return result; |
||
181 | } |
||
182 | 24c5e56c | taeseongkim | |
183 | 38d69491 | taeseongkim | private List<System.Windows.Rect> GetRectList_old(OpenCvSharp.Point[] points,Size block) |
184 | 24c5e56c | taeseongkim | { |
185 | List<System.Windows.Rect> result = new List<System.Windows.Rect>(); |
||
186 | |||
187 | for (int i = 0; i < points.Count(); i++) |
||
188 | { |
||
189 | var rect = new System.Windows.Rect |
||
190 | { |
||
191 | X = points[i].X - block.Width / 2, |
||
192 | Y = points[i].Y - block.Height / 2, |
||
193 | Width = block.Width, |
||
194 | Height = block.Height |
||
195 | }; |
||
196 | |||
197 | if (result.Count(r => r.IntersectsWith(rect)) == 0) |
||
198 | { |
||
199 | result.Add(rect); |
||
200 | } |
||
201 | |||
202 | ComparisonCount++; |
||
203 | |||
204 | 38d69491 | taeseongkim | //SetStatus("Comparison", ComparisonCount/contoursLongCount*100, CompareStatus.Comparison); |
205 | 24c5e56c | taeseongkim | } |
206 | |||
207 | return result; |
||
208 | } |
||
209 | |||
210 | /// <summary> |
||
211 | /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환 |
||
212 | /// </summary> |
||
213 | /// <param name="data"></param> |
||
214 | /// <param name="block"></param> |
||
215 | /// <returns></returns> |
||
216 | protected async Task<List<System.Windows.Rect>> GetMatchPixelsAsnc(Mat data, Size block) |
||
217 | { |
||
218 | return await Task.Factory.StartNew<List<System.Windows.Rect>>(() => |
||
219 | { |
||
220 | return GetMatchPixels(data, block); |
||
221 | }); |
||
222 | } |
||
223 | |||
224 | protected Bitmap LoadPicture(string url) |
||
225 | { |
||
226 | HttpWebRequest wreq; |
||
227 | HttpWebResponse wresp; |
||
228 | Stream mystream; |
||
229 | Bitmap bmp; |
||
230 | |||
231 | bmp = null; |
||
232 | mystream = null; |
||
233 | wresp = null; |
||
234 | try |
||
235 | { |
||
236 | wreq = (HttpWebRequest)WebRequest.Create(url); |
||
237 | wreq.AllowWriteStreamBuffering = true; |
||
238 | |||
239 | wresp = (HttpWebResponse)wreq.GetResponse(); |
||
240 | |||
241 | if ((mystream = wresp.GetResponseStream()) != null) |
||
242 | bmp = new Bitmap(mystream); |
||
243 | } |
||
244 | finally |
||
245 | { |
||
246 | if (mystream != null) |
||
247 | { |
||
248 | mystream.Close(); |
||
249 | mystream.Dispose(); |
||
250 | } |
||
251 | |||
252 | if (wresp != null) |
||
253 | { |
||
254 | wresp.Close(); |
||
255 | wresp.Dispose(); |
||
256 | } |
||
257 | } |
||
258 | return (bmp); |
||
259 | } |
||
260 | |||
261 | #region IDisposable Support |
||
262 | |||
263 | private bool disposedValue = false; |
||
264 | |||
265 | // 중복 호출을 검색하려면 |
||
266 | protected virtual void Dispose(bool disposing) |
||
267 | { |
||
268 | if (!disposedValue) |
||
269 | { |
||
270 | if (disposing) |
||
271 | { |
||
272 | // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다. |
||
273 | } |
||
274 | // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다. |
||
275 | // TODO: 큰 필드를 null로 설정합니다. |
||
276 | disposedValue = true; |
||
277 | } |
||
278 | } |
||
279 | |||
280 | // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다. |
||
281 | // |
||
282 | //~DisposeClass() |
||
283 | // { |
||
284 | // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요. |
||
285 | // Dispose(false); // |
||
286 | // } |
||
287 | |||
288 | // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다. |
||
289 | public void Dispose() |
||
290 | { |
||
291 | // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요. |
||
292 | Dispose(true); |
||
293 | |||
294 | |||
295 | if (OriginalImageData != null) |
||
296 | { |
||
297 | OriginalImageData.Dispose(); |
||
298 | } |
||
299 | |||
300 | if (TargatImageData != null) |
||
301 | { |
||
302 | TargatImageData.Dispose(); |
||
303 | } |
||
304 | |||
305 | // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다. |
||
306 | // GC.SuppressFinalize(this); |
||
307 | GC.Collect(); |
||
308 | GC.SuppressFinalize(this); |
||
309 | GC.Collect(); |
||
310 | } |
||
311 | #endregion |
||
312 | } |
||
313 | } |