eyemMatchShapes.cpp
5.8 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
#include "eyemMatchShapes.h"
shape_based_matching::~shape_based_matching(void) {}
int shape_based_matching::create_shape_model(cv::Mat tpTemplate, double maxContrast, double minContrast, double apertureSize, bool L2gradient)
{
int incn = tpTemplate.channels();
if (incn != 1) {
cv::cvtColor(tpTemplate, tpTemplate, cv::COLOR_BGR2GRAY);
}
//获取边缘
cv::Mat edges;
cv::Canny(tpTemplate, edges, minContrast, maxContrast, (int)apertureSize, L2gradient);
auto contours = std::vector<std::vector<cv::Point>>();
cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
//计算偏导
cv::Mat gx, gy;
cv::Sobel(tpTemplate, gx, CV_64F, 1, 0, 3);
cv::Sobel(tpTemplate, gy, CV_64F, 0, 1, 3);
//计算梯度以及方向
cv::Mat magnitude, direction;
cv::cartToPolar(gx, gy, magnitude, direction);
auto sum = cv::Point2d(0, 0);
for (int i = 0; i < contours.size(); i++)
{
for (int j = 0; j < contours[i].size(); j++)
{
auto cur = contours[i][j];
auto fdx = gx.ptr<double>(cur.y)[cur.x];
auto fdy = gy.ptr<double>(cur.y)[cur.x];
auto der = cv::Point2d(fdx, fdy);
auto mag = magnitude.ptr<double>(cur.y)[cur.x];
auto dir = direction.ptr<double>(cur.y)[cur.x];
results.push_back(PointInfo(cur, der, mag, dir));
sum.x += cur.x; sum.y += cur.y;
}
}
//模板尺寸
templSize = cv::Size(tpTemplate.cols, tpTemplate.rows);
//中心
auto Center = cv::Point2d(sum.x / results.size(), sum.y / results.size());
//更新位置
for (auto&item : results) {
item.update(Center);
}
return FUNC_OK;
}
double shape_based_matching::find_shape_model(cv::Mat tpImage, double minScore, double greediness, cv::Point& resultPoint)
{
int incn = tpImage.channels();
if (incn != 1) {
cv::cvtColor(tpImage, tpImage, cv::COLOR_BGR2GRAY);
}
//尺寸信息
const int X = tpImage.cols, Y = tpImage.rows;
//用于显示
cv::Mat showMat;
cv::cvtColor(tpImage, showMat, cv::COLOR_GRAY2BGR);
//计算偏导
cv::Mat gx, gy;
cv::Sobel(tpImage, gx, CV_64F, 1, 0, 3);
cv::Sobel(tpImage, gy, CV_64F, 0, 1, 3);
//计算梯度以及方向
cv::Mat magnitude, direction;
cv::cartToPolar(gx, gy, magnitude, direction);
cv::Mat scoreMap(cv::Size(tpImage.cols, tpImage.rows), CV_64FC1, cv::Scalar(0));
//基于ncc匹配
long noOfCordinates = static_cast<int>(results.size());
double normMinScore = minScore / noOfCordinates;
double normGreediness = (1 - greediness*minScore) / ((1.0 - greediness) / noOfCordinates);
double partialScore = .0, resultScore = .0;
for (int i = 0; i < tpImage.rows; i++) {
for (int j = 0; j < tpImage.cols; j++) {
double partialSum = .0;
for (int m = 0; m < noOfCordinates; m++)
{
auto item = results[m];
auto curX = (int)(j + item.Offset.x);
auto curY = (int)(i + item.Offset.y);
auto iTx = item.Derivative.x;
auto iTy = item.Derivative.y;
if (curX < 0 || curY < 0 || curY > tpImage.rows - 1 || curX > tpImage.cols - 1)
continue;
auto iSx = gx.ptr<double>(curY)[curX];
auto iSy = gy.ptr<double>(curY)[curX];
if ((iSx != 0 || iSy != 0) && (iTx != 0 || iTy != 0))
{
auto mag = magnitude.ptr<double>(curY)[curX];
auto matGradMag = (mag == 0) ? 0 : 1.0 / mag;
partialSum += ((iSx * iTx) + (iSy * iTy)) * (item.Magnitude * matGradMag);
auto sumOfCoords = m + 1;
partialScore = partialSum / sumOfCoords;
if (partialScore < MIN((minScore - 1) + normGreediness * sumOfCoords, normMinScore * sumOfCoords))
break;
}
}
scoreMap.ptr<double>(i)[j] = partialScore;
}
}
//归一化
cv::normalize(scoreMap, scoreMap, 1.0, 0, cv::NORM_MINMAX);
//计算结果非极大值抑制处理
std::vector<int> indices;
std::vector<cv::Rect> bboxes; std::vector<float> scoreIndex;
for (int y = 0; y < Y; y++)
{
for (int x = 0; x < X; x++)
{
if (scoreMap.ptr<double>(y)[x]>minScore) {
bboxes.push_back(cv::Rect(x - templSize.width / 2, y - templSize.height / 2, templSize.width, templSize.height));
scoreIndex.push_back((float)scoreMap.ptr<double>(y)[x]);
}
}
}
cv::dnn::NMSBoxes(bboxes, scoreIndex, (float)minScore, 0.25f, indices);
for (int i = 0; i < indices.size(); i++) {
resultPoint = (bboxes[indices[i]].tl() + bboxes[indices[i]].br()) / 2;
//画图显示
auto contours = std::vector<cv::Point>();
for (int i = 0; i < results.size(); i++)
{
contours.push_back(results[i].Offset + cv::Point2d(resultPoint));
}
draw_match_shapes(showMat, resultPoint, cv::Scalar(151, 243, 121), 1);
}
cv::imwrite("result.png", showMat);
return 0;
}
void shape_based_matching::draw_match_shapes(cv::Mat &showMat, cv::Point cog, cv::Scalar color, int linew)
{
//绘图显示
cv::circle(showMat, cog, 2, cv::Scalar(0, 0, 255), -1);
auto contours = std::vector<cv::Point>();
for (int i = 0; i < results.size(); i++)
{
contours.push_back(results[i].Offset + cv::Point2d(cog));
}
for (auto&point : contours) {
showMat.at<cv::Vec3b>(point) = cv::Vec3b((uchar)color[0], (uchar)color[1], (uchar)color[2]);
}
}
int eyemMakeShapeModel(EyemImage tpImage, double dContrast, double dMinContrast, int iApertureSize, bool bL2gradient)
{
CV_Assert(NULL != tpImage.vpImage);
cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
if (image.empty())
return FUNC_IMAGE_NOT_EXIST;
//创建模板
sbm.create_shape_model(image, dContrast, dMinContrast, iApertureSize, bL2gradient);
return FUNC_OK;
}
int eyemFindShapeModel(EyemImage tpImage, int iNumLevels, double dAngleStart, double dAngleExtent, double dAngleStep, double dMinContrast, double dContrast, double dGreediness, double dMinScore, bool bOptimization)
{
CV_Assert(NULL != tpImage.vpImage);
cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
if (image.empty())
return FUNC_IMAGE_NOT_EXIST;
//匹配模板
cv::Point result;
sbm.find_shape_model(image, dMinScore, dGreediness, result);
return FUNC_OK;
}