-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathImageSearch.cs
More file actions
194 lines (145 loc) · 6 KB
/
ImageSearch.cs
File metadata and controls
194 lines (145 loc) · 6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using OpenCV.Net;
using System.Diagnostics;
namespace OpenCVImageSearch
{
class ImageSearch
{
public static Methods MatchingMethod = Methods.CorrelationCoefficientNormed;
public static MatchPoint Find(Bitmap small, Bitmap big, bool returnCenter = true)
{
MatchPoint result;
using (Mat sm = BitmapToMat(small))
using (Mat bm = BitmapToMat(big))
using (Mat Mresult = Match(sm, bm))
{
double minVal, maxVal, MatchVal;
OpenCV.Net.Point minLoc, maxLoc, MatchLoc;
CV.MinMaxLoc(Mresult, out minVal, out maxVal, out minLoc, out maxLoc);
//For SquareDifference and SquareDifferenceNormed, the best matches are lower values.
//For all the other methods, the higher the better
MatchVal = (MatchingMethod == Methods.SquareDifference || MatchingMethod == Methods.SquareDifferenceNormed) ? minVal : maxVal;
MatchLoc = (MatchingMethod == Methods.SquareDifference || MatchingMethod == Methods.SquareDifferenceNormed) ? minLoc : maxLoc;
if (returnCenter)
{
MatchLoc.X += small.Width / 2;
MatchLoc.Y += small.Height / 2;
}
result = new MatchPoint(MatchLoc, MatchVal);
}
return result;
}
/// <summary>
/// Finds all matches of small bmp in the big bmp
/// </summary>
/// <param name="small">Small image that will be searched</param>
/// <param name="big">Big image that small image will be searched in</param>
/// <param name="MaxValue">max number of matches</param>
/// <param name="punctuality">Must be ranged 0.00~1.00</param>
/// <param name="returnCenter">middle of small bmp</param>
/// <returns>List of MatchPoint based on found positions</returns>
public static List<MatchPoint> FindAll(Bitmap small, Bitmap big, int MaxValue, double punctuality, bool returnCenter = true)
{
var result = new List<MatchPoint>();
double minVal, maxVal, MatchVal;
OpenCV.Net.Point minLoc, maxLoc, MatchLoc;
//For SquareDifference and SquareDifferenceNormed, the best matches are lower values.
//For all the other methods, the higher the better
bool boolMin = (MatchingMethod == Methods.SquareDifference || MatchingMethod == Methods.SquareDifferenceNormed);
using (Mat sm = BitmapToMat(small))
using (Mat bm = BitmapToMat(big))
using (Mat Mresult = Match(sm, bm))
{
while (MaxValue > 0)
{
CV.MinMaxLoc(Mresult, out minVal, out maxVal, out minLoc, out maxLoc);
MatchVal = boolMin ? minVal : maxVal;
bool pass = (MatchVal >= punctuality);
if (boolMin) pass = (MatchVal <= punctuality);
if (pass)
{
MatchLoc = boolMin ? minLoc : maxLoc;
// Fill results array with hi or lo vals, so we don't match this same location
CV.FloodFill(Mresult, MatchLoc, new Scalar(Convert.ToDouble(boolMin)), new Scalar(0.1), new Scalar(1.0));
if (returnCenter)
{
MatchLoc.X += small.Width / 2;
MatchLoc.Y += small.Height / 2;
}
result.Add(new MatchPoint(MatchLoc, MatchVal));
}
else
{
break;
}
MaxValue--;
}
}
return result;
}
private static Mat Match(Mat small, Mat big)
{
int rows = big.Rows - small.Rows + 1;
int cols = big.Cols - small.Cols + 1;
Mat result = new Mat(rows, cols, Depth.F32, 1);//CV_32FC1
CV.MatchTemplate(big, small, result, (TemplateMatchingMethod)MatchingMethod);
// NamedWindow wnd = new NamedWindow("Debug");
//wnd.ShowImage(result);
// CV.WaitKey();
//CV.Threshold(result, result, 0.90d, 1.00d, ThresholdTypes.ToZero);
// wnd.ShowImage(result);
//CV.WaitKey();
return result;
}
private static Mat BitmapToMat(Bitmap bitmap)
{
BitmapData bmData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
var tmp = new IplImage(new OpenCV.Net.Size(bitmap.Width, bitmap.Height), IplDepth.U8, 3, bmData.Scan0);
bitmap.UnlockBits(bmData);
return tmp.GetMat();
}
}
public enum Methods //copied from TemplateMatchingMethod
{
SquareDifference = 0,
SquareDifferenceNormed = 1,
CrossCorrelation = 2,
CrossCorrelationNormed = 3,
CorrelationCoefficient = 4,
CorrelationCoefficientNormed = 5,
}
public class MatchPoint
{
public int X;
public int Y;
public double Punctuality;
public MatchPoint() : this(0, 0, 0.0) { }
public MatchPoint(int x, int y, double val)
{
X = x;
Y = y;
Punctuality = val;
}
public MatchPoint(OpenCV.Net.Point pt, double val)
{
X = pt.X;
Y = pt.Y;
Punctuality = val;
}
public System.Drawing.Point ToPoint()
{
return new System.Drawing.Point(X, Y);
}
public OpenCV.Net.Point ToCVPoint()
{
return new OpenCV.Net.Point(X, Y);
}
}
}