您的位置:首页 > 其它

基于harris角点检测的矩形检测

2018-03-27 09:51 232 查看
角点检测原理 https://blog.csdn.net/woxincd/article/details/60754658
参考文献     https://wenku.baidu.com/view/6041b397ff00bed5b8f31d22.html
我实现的算法尚有缺陷,必须基于角点,而且对于image效果很差。
源码:float getDistance(Point pointO, Point pointA)
{
float distance;
distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
distance = sqrtf(distance);

return distance;
}

int main()
{
Mat src1 = imread("i.png");
// blur(src1, src1, Size(3, 3));
Mat src;
cvtColor(src1, src, CV_BGR2GRAY);
Mat srcCanny;
Canny(src, srcCanny, 10, 30);
cv::imshow("srcCanny", srcCanny);
Mat cornerStrength;
cornerHarris(src, cornerStrength, 2, 3, 0.04);

//threshold(cornerStrength, harrisCorner, 0.00001, 255, THRESH_BINARY);

Mat dilated;
Mat localMax;
dilate(cornerStrength, dilated, Mat());

compare(cornerStrength, dilated, localMax, CMP_EQ);
double maxStrength;
minMaxLoc(cornerStrength, NULL, &maxStrength);
double holdValue = 0.8*maxStrength; // 0.5参数可调
Mat cornerTh, cornerMap;
threshold(cornerStrength, cornerTh, holdValue, 255, THRESH_BINARY);
cornerTh.convertTo(cornerMap, CV_8U);
bitwise_and(cornerMap, localMax, cornerMap); //相与,既满足大于阈值,又满足是极大值。
vector<Point> points;
for (int i = 0; i < cornerMap.rows; i++)
for (int j = 0; j < cornerMap.cols; j++)
{
if (cornerMap.at<uchar>(i, j))
points.push_back(Point(j, i));

}
cout << points.size() << endl;
Mat saveAngle(Size(points.size(), points.size()), CV_32FC1, Scalar::all(0)), saveDistance(Size(points.size(), points.size()), CV_32FC1, Scalar::all(0));
for (int i = 0; i < points.size(); i++)
for (int j = i + 1; j < points.size(); j++)
{
float angleValue = atanf((points[i].y - points[j].y) / (points[i].x - points[j].x+1));//加1防止分母为0,经验不足
float distanceValue = getDistance(points[i], points[j]);
saveAngle.at<float>(i, j) = angleValue;
saveDistance.at<float>(i, j) = distanceValue;
}
vector<vector<Point> > matchPoints;
for (int i = 0; i < saveAngle.rows; i++)
for (int j = i + 1; j < saveAngle.cols; j++)
{
float angleValue = saveAngle.at<float>(i, j);
float distanceValue = saveDistance.at<float>(i, j);
for (int k = i; k < saveAngle.rows; k++)
for (int l = k + 1; l < saveAngle.cols; l++)
{
if (l == j) continue;
float angleValue_ = saveAngle.at<float>(k, l);
float distanceValue_ = saveDistance.at<float>(k, l);
float theta = fabsf( angleValue-angleValue_ );
float roita = fabsf(distanceValue - distanceValue_);
if (theta < 5 && roita < 10) //参数可调
{
vector<Point> pointsGroup;
pointsGroup.push_back(points[i]);
pointsGroup.push_back(points[j]);
pointsGroup.push_back(points[k]);
pointsGroup.push_back(points[l]);
matchPoints.push_back(pointsGroup);
}
}
}
cout << matchPoints.size() << endl;
vector<float> angleAverage;
for (int i = 0; i < matchPoints.size(); i++)
{
float angleM = atanf((matchPoints[i][0].y - matchPoints[i][1].y) / (matchPoints[i][0].x - matchPoints[i][1].x + 1));
float angleN = atanf((matchPoints[i][2].y - matchPoints[i][3].y) / (matchPoints[i][2].x - matchPoints[i][3].x + 1));
float a = 0.5*(angleM + angleN);
angleAverage.push_back(a);
}
vector<vector<Point> > matchPoints_;
for (int i = 0; i < angleAverage.size(); i++)
for (int j = i + 1; j < angleAverage.size(); j++)
{
if (fabs(fabs(angleAverage[i] - angleAverage[j]) - 0.5*CV_PI)<(5*CV_PI/180))
{
bool j1 = matchPoints[i][0] == matchPoints[j][0];
bool j2 = matchPoints[i][0] == matchPoints[j][1];
bool j3 = matchPoints[i][0] == matchPoints[j][2];
bool j4 = matchPoints[i][0] == matchPoints[j][3];
bool j5 = matchPoints[i][1] == matchPoints[j][0];
bool j6 = matchPoints[i][1] == matchPoints[j][1];
bool j7 = matchPoints[i][1] == matchPoints[j][2];
bool j8 = matchPoints[i][1] == matchPoints[j][3];
bool j9 = matchPoints[i][2] == matchPoints[j][0];
bool j10 = matchPoints[i][2] == matchPoints[j][1];
bool j11 = matchPoints[i][2] == matchPoints[j][2];
bool j12 = matchPoints[i][2] == matchPoints[j][3];
bool j13 = matchPoints[i][3] == matchPoints[j][0];
bool j14 = matchPoints[i][3] == matchPoints[j][1];
bool j15 = matchPoints[i][3] == matchPoints[j][2];
bool j16 = matchPoints[i][3] == matchPoints[j][3];
if ((j1||j2||j3||j4)&&(j5||j6||j7||j8)&&(j9||j10||j11||j12)&&(j13||j14||j15||j16))
{
matchPoints_.push_back(matchPoints[i]);
}
}
}
cout << matchPoints_.size() << endl;

Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
dilate(srcCanny, srcCanny, element);
cv::imshow("dilated", srcCanny);

vector<vector<Point> > points_dst;
for (int i = 0; i < matchPoints_.size(); i++)
{
Vec4f line;
vector<Point> fitPoints1, fitPoints2;
cv::Point point0;
int count1 = 0;
int count2 = 0;
for (int j = 0; j < 4; j = j + 2)
{
vector<Point> ps;
ps.push_back(matchPoints_[i][j]);
ps.push_back(matchPoints_[i][j+1]);
fitLine(ps, line, cv::DIST_L2, 0, 1e-2, 1e-2);
point0.x = line[2];
point0.y = line[3];
double k = line[1] / (line[0] + 0.0000001); //加个极小量
if (k > 1000) //是竖直线 x不变 y变
{
for (int c = fminf(matchPoints_[i][j].y, matchPoints_[i][j + 1].y); c < fmaxf(matchPoints_[i][j].y, matchPoints_[i][j + 1].y); c++)
{
Point ss(matchPoints_[i][j].x, c);
if (j==0)
fitPoints1.push_back(ss);
if (j==2)
fitPoints2.push_back(ss);
}
}
else{
Point p1;
for (int c = fminf(matchPoints_[i][j].x, matchPoints_[i][j + 1].x); c < fmaxf(matchPoints_[i][j].x, matchPoints_[i][j + 1].x); c++)
{
p1.x = c;
p1.y = k * (c - point0.x) + point0.y;
if (j==0)
fitPoints1.push_back(p1);
if (j == 2)
fitPoints2.push_back(p1);
}
}
}
for (int l = 0; l < fitPoints1.size();l++)
{
if (srcCanny.at<uchar>(fitPoints1[l]))
count1 += 1;
}
for (int q = 0; q < fitPoints2.size(); q++)
{
if (srcCanny.at<uchar>(fitPoints2[q]))
count2 += 1;
}
bool w1 = fabs(count1 - getDistance(matchPoints_[i][0], matchPoints_[i][1])) < 10;
bool w2 = fabs(count2 - getDistance(matchPoints_[i][2], matchPoints_[i][3])) < 10;
if (w1&&w2)
points_dst.push_back(matchPoints_[i]);
}

cout << points_dst.size() << endl;

for (int i = 0; i < points_dst.size(); i++)
for (int j = 0; j < 4; j = j + 2)
{
line(src1, points_dst[i][j], points_dst[i][j + 1], Scalar(0, 0, 255), 4, LINE_AA);
/* int counts = points_dst.size(); //points_dst中有重复的内容,暂时不知道如何消除重复内容
String s = "There are" + to_string(counts) + "rectangles";
putText(src1,s, Point(5, 50), cv::FONT_HERSHEY_COMPLEX, 2, Scalar(0, 0, 255), 2, LINE_AA);
*/
putText(src1, String("red line marked Rect"), Point(5, 30), cv::FONT_HERSHEY_COMPLEX, 2, Scalar(0, 0, 255), 2);
}
if (points_dst.size() == 0)
{
putText(src1, String("cnmlgb,there is no Rect"), Point(5, 30), cv::FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
}

cv::imshow("dst", src1);

cv::waitKey(0);
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: