프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / ImageComparer / Markus.ImageComparer / ImageCompareBase.cs @ 16231f58

이력 | 보기 | 이력해설 | 다운로드 (11.3 KB)

1
using OpenCvSharp;
2
using System;
3
using System.Collections.Generic;
4
using System.Drawing;
5
using System.Drawing.Imaging;
6
using System.IO;
7
using System.Linq;
8
using System.Net;
9
using System.Runtime.InteropServices;
10
using System.Text;
11
using System.Threading.Tasks;
12
using Point = System.Drawing.Point;
13
using Size = System.Drawing.Size;
14

    
15
namespace Markus.Image
16
{
17
    public class ImageCompareBase : IDisposable
18
    {
19
        Mat OriginalImageData = null;
20
        Mat TargatImageData = null;
21

    
22
        double contoursLongCount = 0;
23
        double ComparisonCount = 0;
24
        public CompareProgress Progress = new CompareProgress();
25

    
26
        private void SetStatus(string message,double percentage,CompareStatus status)
27
        {
28
            System.Diagnostics.Debug.WriteLine(percentage);
29

    
30
            Progress.Message = message;
31
            Progress.Percentage = percentage;
32
            Progress.Status = status;
33
        }
34

    
35
        /// <summary>
36
        /// Originalbitmap에서 TargatBitmap과 비교하여 틀린 부분의 데이터를 Emgu.CV.TDepth형식으로 반환한다.
37
        /// </summary>
38
        /// <param name="Originalbitmap">원본 이미지</param>
39
        /// <param name="TargatBitmap">비교대상 이미지</param>
40
        /// <returns>Emgu.CV.TDepth형식의 byte[,,]</returns>
41
        protected Mat MathchesImageData(System.Drawing.Bitmap Originalbitmap, System.Drawing.Bitmap TargatBitmap)
42
        {
43
            Mat result = new Mat();
44

    
45
            try
46
            {
47
                SetStatus("Image Load", 0, CompareStatus.Loading);
48

    
49
                Originalbitmap = ChangeBitmapFormatAndSize(Originalbitmap, Originalbitmap.Size, PixelFormat.Format24bppRgb);
50
                TargatBitmap = ChangeBitmapFormatAndSize(TargatBitmap, Originalbitmap.Size, PixelFormat.Format24bppRgb);
51

    
52
                // 원본이미지의 크키와 Format24bppRgb로 타켓 이미지를 변경
53
                // 크기가 틀린 경우 비교시 바이트배열 오류 발생
54
                OriginalImageData = OpenCvSharp.Extensions.BitmapConverter.ToMat(Originalbitmap);
55
                TargatImageData = OpenCvSharp.Extensions.BitmapConverter.ToMat(TargatBitmap);
56

    
57
                if (OriginalImageData.Size() != TargatImageData.Size())
58
                {
59
                    Cv2.Resize(TargatImageData, TargatImageData, OriginalImageData.Size());
60
                }
61
                
62
                Cv2.CvtColor(OriginalImageData, OriginalImageData, ColorConversionCodes.BGR2GRAY);
63
                Cv2.CvtColor(TargatImageData, TargatImageData, ColorConversionCodes.BGR2GRAY);
64

    
65
                //Cv2.EqualizeHist(OriginalImageData, OriginalImageData);
66
                //Cv2.EqualizeHist(TargatImageData, TargatImageData);
67

    
68
                //Cv2.GaussianBlur(OriginalImageData, OriginalImageData, new OpenCvSharp.Size(5, 5), 0);
69
                //Cv2.GaussianBlur(TargatImageData, TargatImageData, new OpenCvSharp.Size(5, 5), 0);
70
                // Canny 엣지 검출 적용
71

    
72
                Mat outputData = new Mat(TargatImageData.Size(), MatType.CV_8UC1);
73
                Cv2.Absdiff(OriginalImageData, TargatImageData, outputData);
74

    
75
                // 틀린부분을 반환
76
                Cv2.BitwiseNot(outputData, result);
77
            }
78
            catch (Exception ex)
79
            {
80
                throw ex;
81
            }
82
            finally
83
            {
84
            }
85
            
86
            return result;
87
        }
88

    
89
        protected System.Drawing.Bitmap ChangeBitmapFormatAndSize(System.Drawing.Bitmap bitmap, Size newSize, PixelFormat pixelFormat)
90
        {
91
            Bitmap result = bitmap;
92

    
93
            if (pixelFormat != bitmap.PixelFormat)
94
            {
95
                Point originPoint = new Point(0, 0);
96
                Rectangle rect = new Rectangle(originPoint, bitmap.Size);
97
                result = bitmap.Clone(rect, pixelFormat);
98
            }
99

    
100
            if (bitmap.Size != newSize)
101
            {
102
                result = new Bitmap(newSize.Width, newSize.Height);
103

    
104
                using (Graphics g = Graphics.FromImage(result))
105
                {
106
                    g.DrawImage(bitmap, 0, 0, newSize.Width, newSize.Height);
107
                    g.Dispose();
108
                }
109
            }
110

    
111
            return result;
112
        }
113

    
114
        /// <summary>
115
        /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환
116
        /// </summary>
117
        /// <param name="data"></param>
118
        /// <param name="block"></param>
119
        /// <returns></returns>
120
        protected List<System.Windows.Rect> GetMatchPixels(Mat data, Size block)
121
        {
122
            SetStatus("Detection", 0, CompareStatus.Detection);
123

    
124
            int width = data.Cols;
125
            int height = data.Rows;
126

    
127
            List<System.Windows.Rect> results = new List<System.Windows.Rect>();
128

    
129
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
130
            stopwatch.Start();
131

    
132
            Mat outputMat = new Mat(data.Size(), MatType.CV_8UC1);
133

    
134
            HierarchyIndex[] hierarchy;
135
            OpenCvSharp.Point[][] contours;
136

    
137
            OpenCvSharp.Point testpoint = new OpenCvSharp.Point();
138
           
139
            Cv2.Threshold(data, data, 0, 30,ThresholdTypes.BinaryInv);
140

    
141
            Cv2.FindContours(data, out contours, out hierarchy,RetrievalModes.List,ContourApproximationModes.ApproxNone, testpoint);
142

    
143
            SetStatus("Comparison", 0, CompareStatus.Comparison);
144
            contoursLongCount = contours.Sum(x => x.Count());
145

    
146
            var rects = contours.AsParallel()
147
                                .Select(points => GetRectList(points, block))
148
                                .SelectMany(x => x);
149

    
150
            results.AddRange(rects);
151
             
152
            return results;
153
        }
154

    
155
        protected System.Drawing.Bitmap GetContoursImage(Mat data,Size resultSize,Color RectColor)
156
        {
157
            System.Drawing.Bitmap result = null;
158

    
159
            try
160
            {
161
                OpenCvSharp.Mat transparentImage = new OpenCvSharp.Mat(new OpenCvSharp.Size(resultSize.Width, resultSize.Height), OpenCvSharp.MatType.CV_8UC4, new OpenCvSharp.Scalar(0, 0, 0, 0));
162

    
163
                // 컨투어를 찾기 위한 변수 선언
164
                OpenCvSharp.HierarchyIndex[] hierarchy;
165
                OpenCvSharp.Point[][] contours;
166
                OpenCvSharp.Point testpoint = new OpenCvSharp.Point();
167

    
168
                OpenCvSharp.Cv2.Threshold(data, data, 50, 255, OpenCvSharp.ThresholdTypes.BinaryInv);
169
                // 이진화된 이미지에서 컨투어 찾기
170
                OpenCvSharp.Cv2.FindContours(data, out contours, out hierarchy, OpenCvSharp.RetrievalModes.List, OpenCvSharp.ContourApproximationModes.ApproxNone, testpoint);
171

    
172

    
173
                // OpenCvSharp.Scalar(B,G,R,A)
174
                // 컨투어 그리기
175
                OpenCvSharp.Cv2.DrawContours(transparentImage, contours, -1, new OpenCvSharp.Scalar(RectColor.B, RectColor.G, RectColor.R, RectColor.A), 10);
176

    
177
                // Mat을 Bitmap으로 변환
178
                result = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(transparentImage);
179
            }
180
            catch (Exception ex)
181
            {
182
                throw new Exception("GetContoursImage Error.",ex);
183
            }
184
            finally
185
            {
186

    
187
            }
188

    
189
            return result;
190
        }
191

    
192
        private List<System.Windows.Rect> GetRectList(OpenCvSharp.Point[] points,Size block)
193
        {
194
            List<System.Windows.Rect> result = new List<System.Windows.Rect>();
195

    
196
            for (int i = 0; i < points.Count(); i++)
197
            {
198
                var rect = new System.Windows.Rect
199
                {
200
                    X = points[i].X - block.Width / 2,
201
                    Y = points[i].Y - block.Height / 2,
202
                    Width = block.Width,
203
                    Height = block.Height
204
                };
205

    
206
                if (result.Count(r => r.IntersectsWith(rect)) == 0)
207
                {
208
                    result.Add(rect);
209
                }
210

    
211
                ComparisonCount++;
212

    
213
                SetStatus("Comparison", ComparisonCount/contoursLongCount*100, CompareStatus.Comparison);
214
            }
215

    
216
            return result;
217
        }
218

    
219
        /// <summary>
220
        /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환
221
        /// </summary>
222
        /// <param name="data"></param>
223
        /// <param name="block"></param>
224
        /// <returns></returns>
225
        protected async Task<List<System.Windows.Rect>> GetMatchPixelsAsnc(Mat data, Size block)
226
        {
227
            return await Task.Factory.StartNew<List<System.Windows.Rect>>(() =>
228
            {
229
                return GetMatchPixels(data, block);
230
            });
231
        }
232

    
233
        protected Bitmap LoadPicture(string url)
234
        {
235
            HttpWebRequest wreq;
236
            HttpWebResponse wresp;
237
            Stream mystream;
238
            Bitmap bmp;
239

    
240
            bmp = null;
241
            mystream = null;
242
            wresp = null;
243
            try
244
            {
245
                wreq = (HttpWebRequest)WebRequest.Create(url);
246
                wreq.AllowWriteStreamBuffering = true;
247

    
248
                wresp = (HttpWebResponse)wreq.GetResponse();
249

    
250
                if ((mystream = wresp.GetResponseStream()) != null)
251
                    bmp = new Bitmap(mystream);
252
            }
253
            finally
254
            {
255
                if (mystream != null)
256
                {
257
                    mystream.Close();
258
                    mystream.Dispose();
259
                }
260

    
261
                if (wresp != null)
262
                {
263
                    wresp.Close();
264
                    wresp.Dispose();
265
                }
266
            }
267
            return (bmp);
268
        }
269

    
270
        #region  IDisposable Support 
271

    
272
        private bool disposedValue = false;
273

    
274
        // 중복 호출을 검색하려면 
275
        protected virtual void Dispose(bool disposing)
276
        {
277
            if (!disposedValue)
278
            {
279
                if (disposing)
280
                {
281
                    // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다. 
282
                }
283
                // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다. 
284
                // TODO: 큰 필드를 null로 설정합니다. 
285
                disposedValue = true;
286
            }
287
        }
288

    
289
        // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
290
        // 
291
        //~DisposeClass()
292
       // {
293
            // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요. 
294
            // Dispose(false); // 
295
       // } 
296

    
297
        // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다. 
298
        public void Dispose()
299
        {
300
            // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요. 
301
            Dispose(true);
302

    
303

    
304
            if (OriginalImageData != null)
305
            {
306
                OriginalImageData.Dispose();
307
            }
308

    
309
            if (TargatImageData != null)
310
            {
311
                TargatImageData.Dispose();
312
            }
313

    
314
            // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다. 
315
            //  GC.SuppressFinalize(this);
316
            GC.Collect();
317
            GC.SuppressFinalize(this);
318
            GC.Collect();
319
        } 
320
        #endregion
321
    }
322
}
클립보드 이미지 추가 (최대 크기: 500 MB)