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

角点检测原理

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;


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值