프로젝트

일반

사용자정보

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

markus / ImageComparer / Markus.ImageComparer / ImageComparerBase.cs @ 606884bf

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

1 6b6e937c taeseongkim
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
            Parallel.ForEach(heightRange, (y) =>
165
            {
166
                Parallel.ForEach(widthRange, (x) =>
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
            System.Diagnostics.Debug.WriteLine("1 - " + new TimeSpan(stopwatch.ElapsedTicks));
178
            return results;
179
        }
180
181
        /// <summary>
182
        /// Image<TColor, TDepth>의 틀린 부분을 Rect로 반환
183
        /// </summary>
184
        /// <param name="data"></param>
185
        /// <param name="block"></param>
186
        /// <returns></returns>
187
        protected async Task<List<System.Windows.Rect>> GetMatchPixelsAsnc(byte[,,] data, Size block)
188
        {
189
            return await Task.Factory.StartNew<List<System.Windows.Rect>>(() =>
190
            {
191
                return GetMatchPixels(data, block);
192
            });
193
        }
194
195
        protected Bitmap LoadPicture(string url)
196
        {
197
            HttpWebRequest wreq;
198
            HttpWebResponse wresp;
199
            Stream mystream;
200
            Bitmap bmp;
201
202
            bmp = null;
203
            mystream = null;
204
            wresp = null;
205
            try
206
            {
207
                wreq = (HttpWebRequest)WebRequest.Create(url);
208
                wreq.AllowWriteStreamBuffering = true;
209
210
                wresp = (HttpWebResponse)wreq.GetResponse();
211
212
                if ((mystream = wresp.GetResponseStream()) != null)
213
                    bmp = new Bitmap(mystream);
214
            }
215
            finally
216
            {
217
                if (mystream != null)
218
                {
219
                    mystream.Close();
220
                    mystream.Dispose();
221
                }
222
223
                if (wresp != null)
224
                {
225
                    wresp.Close();
226
                    wresp.Dispose();
227
                }
228
            }
229
            return (bmp);
230
        }
231
232
        #region  IDisposable Support 
233
234
        private bool disposedValue = false;
235
236
        // 중복 호출을 검색하려면 
237
        protected virtual void Dispose(bool disposing)
238
        {
239
            if (!disposedValue)
240
            {
241
                if (disposing)
242
                {
243
                    // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다. 
244
                }
245
                // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다. 
246
                // TODO: 큰 필드를 null로 설정합니다. 
247
                disposedValue = true;
248
            }
249
        }
250
251
        // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
252
        // 
253
        //~DisposeClass()
254
       // {
255
            // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요. 
256
            // Dispose(false); // 
257
       // } 
258
259
        // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다. 
260
        public void Dispose()
261
        {
262
            // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요. 
263
            Dispose(true);
264
265
266
            if (OriginalImageData != null)
267
            {
268
                OriginalImageData.Dispose();
269
            }
270
271
            if (TargatImageData != null)
272
            {
273
                TargatImageData.Dispose();
274
            }
275
276
            // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다. 
277
            //  GC.SuppressFinalize(this);
278
            GC.Collect();
279
            GC.SuppressFinalize(this);
280
            GC.Collect();
281
        } 
282
        #endregion
283
    }
284
}
클립보드 이미지 추가 (최대 크기: 500 MB)