Hough变换

本文详细介绍了Hough变换在计算机视觉中的原理,展示了如何使用OpenCV库实现直线检测(Mathough、MathoughP、MathoughC)和关键点检测。通过实例演示了Hough变换在图像边缘(Canny)、二值阈值(otsu)和圆检测(HoughCircles)的应用。
摘要由CSDN通过智能技术生成

Hough变换

#include<opencv2/opencv.hpp>

/*
* 原理:
* 如果在笛卡儿空间内,有N个点能够连成一条直线y=k1x+b1,
那么在霍夫空间内就会有N条直线穿过对应的点(k1,b1)。
或者反过来说,如果在霍夫空间中,有越多的直线穿过点(k1,b1),
就说明在笛卡儿空间内有越多的点位于斜率为k1,截距为b1的直线y=k1x+b1上。
​ 一般来说,在极坐标系内的一条直线能够通过在霍夫坐标系内相交于一点的线的数量来评估。
在霍夫坐标系内,经过一个点的线越多,
说明其映射在极坐标系内的直线,是由越多的点所构成(穿过)的。
因此,霍夫变换选择直线的基本思路是:选择由尽可能多条线汇成的点。
*/

//检测直线一
cv::Mat hough(cv::Mat src, std::vector<cv::Vec2f> lines) {

	cv::HoughLines(src, lines, 1, CV_PI / 180, 300, 0, 0);
	cv::Mat dst;
	cv::cvtColor(src, dst, CV_GRAY2BGR);
	//画线
	for (size_t i = 0; i < lines.size(); i++) {
		float rho = lines[i][0], theta = lines[i][1];
		cv::Point pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a * rho, y0 = b * rho;
		pt1.x = cvRound(x0 + 1000 * (-b));
		pt1.y = cvRound(y0 + 1000 * (a));
		pt2.x = cvRound(x0 - 1000 * (-b));
		pt2.y = cvRound(y0 - 1000 * (a));
		line(dst, pt1, pt2, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
	}

	return dst;
}

//检测直线二
cv::Mat houghP(cv::Mat src, std::vector<cv::Vec4i> linesP) {
	cv::Mat dst;
	cv::cvtColor(src, dst, CV_GRAY2BGR);
	HoughLinesP(src, linesP, 1, CV_PI / 180, 50, 50, 10); // 运行实际检测
	// Draw the lines
	for (size_t i = 0; i < linesP.size(); i++)
	{
		cv::Vec4i l = linesP[i];
		line(dst, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), 
			cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
	}
	return dst;
}

cv::Mat houghC(cv::Mat src) {
	cv::Mat gray;
	cv::cvtColor(src, gray, CV_BGR2GRAY);
	cv::Mat thresh;
	cv::threshold(gray, thresh, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);

	std::vector<cv::Vec3f> circles;
	circles.reserve(src.cols * src.rows);
	cv::HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, 100, 220, 30, 150, 200);

	//在原图中画出圆心和圆
	for (size_t i = 0; i < circles.size(); i++)
	{
		//提取出圆心坐标
		cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
		//提取出圆半径
		int radius = cvRound(circles[i][2]);
		//圆心
		circle(src, center, 3, cv::Scalar(0, 255, 0), -1, 8, 0);
		//圆
		circle(src, center, radius, cv::Scalar(0, 0, 255), 1, 8, 0);
	}

	return src;
}

int main() {

	cv::Mat build = cv::imread("D:\\pic\\xian.jpg");
	cv::Mat moon = cv::imread("D:\\pic\\moon.jpg");

	cv::Mat build_gray, build_gray_canny, build_gray_thresh;
	cv::cvtColor(build, build_gray, CV_BGR2GRAY);

	cv::threshold(build_gray, build_gray_thresh, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
	cv::Canny(build, build_gray_canny, 50, 200, 3);

	std::vector<cv::Vec2f> lines;
	std::vector<cv::Vec4i> linesP;
	lines.resize(build.rows * build.cols);
	linesP.resize(build.rows * build.cols);

	//memset(lines.data(), 0, lines.size() * sizeof(cv::Vec2f));

	cv::Mat thresh_hough = hough(build_gray_thresh, lines);
	cv::Mat canny_hough = hough(build_gray_canny, lines);
	
	cv::Mat thresh_houghP = houghP(build_gray_thresh, linesP);
	cv::Mat canny_houghP = houghP(build_gray_canny, linesP);

	cv::Mat moon_houghC = houghC(moon);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值