프로젝트

일반

사용자정보

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

markus / ImageComparer / Markus.ImageComparer / ImageComparerBase.cs @ 84605c0c

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

1
using Emgu.CV;
2
using Emgu.CV.Structure;
3
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.Text;
11
using System.Threading.Tasks;
12

    
13
namespace Markus.Image
14
{
15
    public class ImageComparerBase : IDisposable
16
    {
17
        Image<Bgr, Byte> OriginalImageData = null;
18
        Image<Bgr, Byte> TargatImageData = null;
19

    
20
        /// <summary>
21
        /// 이미지 비교에 사용되는 점수
22
        /// </summary>
23
        double gMatchScore = 0.9;
24

    
25
        /// <summary>
26
        /// 이미지의 크기와 포멧을 변경한다.
27
        /// </summary>
28
        /// <param name="bitmap"></param>
29
        /// <param name="newSize"></param>
30
        /// <param name="pixelFormat"></param>
31
        /// <returns></returns>
32
        protected System.Drawing.Bitmap ChangeBitmapFormatAndSize(System.Drawing.Bitmap bitmap, Size newSize, PixelFormat pixelFormat)
33
        {
34
            Bitmap result = bitmap;
35

    
36
            if (pixelFormat != bitmap.PixelFormat)
37
            {
38
                Point originPoint = new Point(0, 0);
39
                Rectangle rect = new Rectangle(originPoint, bitmap.Size);
40
                result = bitmap.Clone(rect, pixelFormat);
41
            }
42

    
43
            if (bitmap.Size != newSize)
44
            {
45
                result = new Bitmap(newSize.Width, newSize.Height);
46

    
47
                using (Graphics g = Graphics.FromImage(result))
48
                {
49
                    g.DrawImage(bitmap, 0, 0, newSize.Width, newSize.Height);
50
                    g.Dispose();
51
                }
52
            }
53

    
54
            return result;
55
        }
56

    
57
        /// <summary>
58
        /// Originalbitmap에서 TargatBitmap과 비교하여 틀린 부분의 데이터를 Emgu.CV.TDepth형식으로 반환한다.
59
        /// </summary>
60
        /// <param name="Originalbitmap">원본 이미지</param>
61
        /// <param name="TargatBitmap">비교대상 이미지</param>
62
        /// <returns>Emgu.CV.TDepth형식의 byte[,,]</returns>
63
        protected byte[,,] MathchesImageData(System.Drawing.Bitmap Originalbitmap, System.Drawing.Bitmap TargatBitmap)
64
        {
65
            byte[,,] result = null;
66

    
67
            try
68
            {
69
                // 원본이미지의 크키와 Format24bppRgb로 타켓 이미지를 변경
70
                // 크기가 틀린 경우 비교시 바이트배열 오류 발생
71
                // 이미지 포멧은 24bit이하로 emgu CV가 작동
72
                Originalbitmap = ChangeBitmapFormatAndSize(Originalbitmap, Originalbitmap.Size, PixelFormat.Format24bppRgb);
73
                TargatBitmap = ChangeBitmapFormatAndSize(TargatBitmap, Originalbitmap.Size, PixelFormat.Format24bppRgb);
74

    
75
                OriginalImageData = new Image<Bgr, Byte>(Originalbitmap);
76
                TargatImageData = new Image<Bgr, Byte>(TargatBitmap);
77

    
78
                //Computes absolute different between this image and the other image
79
                // 원본이미지와 타겟이미지를 처리
80
                var tmp = OriginalImageData.AbsDiff(TargatImageData);
81

    
82
                // 틀린부분을 반환
83
                var matches = tmp.Not();
84

    
85
                result = matches.Data;
86

    
87
                matches.Dispose();
88
                tmp.Dispose();
89
            }
90
            catch (Exception ex)
91
            {
92
                throw ex;
93
            }
94
            
95
            return result;
96
        }
97

    
98
        /// <summary>
99
        /// MathchesImageData의 틀린 부분을 Rect로 반환
100
        /// </summary>
101
        /// <param name="data"></param>
102
        /// <param name="currentX"></param>
103
        /// <param name="currentY"></param>
104
        /// <param name="ImageWidth"></param>
105
        /// <param name="ImageHeight"></param>
106
        /// <param name="block"></param>
107
        /// <returns></returns>
108
        protected System.Windows.Rect? DataMatchScore(byte[,,] data, int currentX, int currentY, int ImageWidth, int ImageHeight, Size block)
109
        {
110
            System.Windows.Rect? result = null;
111

    
112
            int x = currentX;
113
            int y = currentY;
114
            int width = ImageWidth;
115
            int height = ImageHeight;
116

    
117
            for (int i = 0; i < block.Width; i++)
118
            {
119
                int wi = x + i;
120
                if (wi >= width) break;
121

    
122
                for (int j = 0; j < block.Height; j++)
123
                {
124
                    int hj = y + j;
125
                    if (hj >= height) break;
126

    
127
                    double matchScore = data[wi, hj, 0];
128

    
129
                    if (matchScore < gMatchScore)
130
                    {
131
                        result = new System.Windows.Rect(y, x, block.Width, block.Height);
132
                        return result;
133
                    }
134
                }
135
            }
136

    
137
            return result;
138
        }
139

    
140
        /// <summary>
141
        /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환
142
        /// </summary>
143
        /// <param name="data"></param>
144
        /// <param name="block"></param>
145
        /// <returns></returns>
146
        protected List<System.Windows.Rect> GetMatchPixels(byte[,,] data, Size block)
147
        {
148
            int width = data.GetLength(0);
149
            int height = data.GetLength(1);
150

    
151
            List<System.Windows.Rect> results = new List<System.Windows.Rect>();
152

    
153
            var heightRange = from h in Enumerable.Range(1, height)
154
                              where h % block.Height == 0
155
                              select h;
156

    
157
            var widthRange = from w in Enumerable.Range(1, width)
158
                             where w % block.Width == 0
159
                             select w;
160

    
161
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
162
            stopwatch.Start();
163

    
164
            foreach (var y in heightRange)
165
            {
166
                foreach (var x in widthRange)
167
                {
168
                    var rect = DataMatchScore(data, x, y, width, height, block);
169

    
170
                    if (rect != null)
171
                    {
172
                        results.Add(rect.Value);
173
                    }
174
                }
175
            }
176

    
177
            //Parallel.ForEach(heightRange, (y) =>
178
            //{
179
            //    Parallel.ForEach(widthRange, (x) =>
180
            //    {
181
            //        var rect = DataMatchScore(data, x, y, width, height, block);
182

    
183
            //        if (rect != null)
184
            //        {
185
            //            results.Add(rect.Value);
186
            //        }
187
            //    });
188
            //});
189
            //Parallel.ForEach(heightRange, (y) =>
190
            //{
191
            //    Parallel.ForEach(widthRange, (x) =>
192
            //    {
193
            //        var rect = DataMatchScore(data, x, y, width, height, block);
194

    
195
            //        if (rect != null)
196
            //        {
197
            //            results.Add(rect.Value);
198
            //        }
199
            //    });
200
            //});
201

    
202
            System.Diagnostics.Debug.WriteLine("1 - " + new TimeSpan(stopwatch.ElapsedTicks));
203
            return results;
204
        }
205

    
206
        /// <summary>
207
        /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환
208
        /// </summary>
209
        /// <param name="data"></param>
210
        /// <param name="block"></param>
211
        /// <returns></returns>
212
        protected async Task<List<System.Windows.Rect>> GetMatchPixelsAsnc(byte[,,] data, Size block)
213
        {
214
            return await Task.Factory.StartNew<List<System.Windows.Rect>>(() =>
215
            {
216
                return GetMatchPixels(data, block);
217
            });
218
        }
219

    
220
        protected Bitmap LoadPicture(string url)
221
        {
222
            HttpWebRequest wreq;
223
            HttpWebResponse wresp;
224
            Stream mystream;
225
            Bitmap bmp;
226

    
227
            bmp = null;
228
            mystream = null;
229
            wresp = null;
230
            try
231
            {
232
                wreq = (HttpWebRequest)WebRequest.Create(url);
233
                wreq.AllowWriteStreamBuffering = true;
234

    
235
                wresp = (HttpWebResponse)wreq.GetResponse();
236

    
237
                if ((mystream = wresp.GetResponseStream()) != null)
238
                    bmp = new Bitmap(mystream);
239
            }
240
            finally
241
            {
242
                if (mystream != null)
243
                {
244
                    mystream.Close();
245
                    mystream.Dispose();
246
                }
247

    
248
                if (wresp != null)
249
                {
250
                    wresp.Close();
251
                    wresp.Dispose();
252
                }
253
            }
254
            return (bmp);
255
        }
256

    
257
        #region  IDisposable Support 
258

    
259
        private bool disposedValue = false;
260

    
261
        // 중복 호출을 검색하려면 
262
        protected virtual void Dispose(bool disposing)
263
        {
264
            if (!disposedValue)
265
            {
266
                if (disposing)
267
                {
268
                    // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다. 
269
                }
270
                // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다. 
271
                // TODO: 큰 필드를 null로 설정합니다. 
272
                disposedValue = true;
273
            }
274
        }
275

    
276
        // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
277
        // 
278
        //~DisposeClass()
279
       // {
280
            // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요. 
281
            // Dispose(false); // 
282
       // } 
283

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

    
290

    
291
            if (OriginalImageData != null)
292
            {
293
                OriginalImageData.Dispose();
294
            }
295

    
296
            if (TargatImageData != null)
297
            {
298
                TargatImageData.Dispose();
299
            }
300

    
301
            // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다. 
302
            //  GC.SuppressFinalize(this);
303
            GC.Collect();
304
            GC.SuppressFinalize(this);
305
            GC.Collect();
306
        } 
307
        #endregion
308
    }
309
}
클립보드 이미지 추가 (최대 크기: 500 MB)