C C++最全13- OpenCV:霍夫检测:直线、圆检测_opencv 霍夫检测,【架构师必备】

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

(1)Hough Line Transform用来做直线检测

(2)前提条件 – 边缘检测已经完成 (cv::Canny,输入的是8位的图像可以是单通道或多通道,输出的是8位单通道的灰度图像,再通过threshold转化为二值化图像)

(3)平面空间到极坐标空间转换

极坐标也就是霍夫空间的坐标。

2、霍夫直线变换的例子

(1)对于任意一条直线上的所有点来说

(2)变换到极坐标中,从[0~360]空间,可以得到r的大小

(3)属于同一条直线上点在极坐标空(r, theta)必然在一个点上有最强的信号出现,根据此反算到平面坐标中就可以得到直线上各点的像素坐标。从而得到直线

(4)从平面坐标变换到霍夫空间(极坐标)

3、相关API学习(代码例子)

(1)标准的霍夫变换 cv::HoughLines从平面坐标转换到霍夫空间,最终输出是极坐标空间;表示形式为:

cv::HoughLines(

InputArray src, // 输入图像,必须8-bit的灰度图像

OutputArray lines, // 输出的极坐标来表示直线

double rho, // 生成极坐标时候的像素扫描步长

double theta, //生成极坐标时候的角度步长,一般取值CV_PI/180

int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线

double srn=0;// 是否应用多尺度的霍夫变换,如果不是设置0表示经典霍夫变换

double stn=0;//是否应用多尺度的霍夫变换,如果不是设置0表示经典霍夫变换

double min_theta=0; // 表示角度扫描范围 0 ~180之间, 默认即可

double max_theta=CV_PI

) // 一般情况是有经验的开发者使用,需要自己反变换到平面空间(少用)

(2)霍夫变换直线概率 cv::HoughLinesP最终输出是直线的两个点**(常用)**

cv::HoughLinesP(

InputArray src, // 输入图像,必须8-bit的灰度图像

OutputArray lines, // 输出的极坐标来表示直线

double rho, // 生成极坐标时候的像素扫描步长

double theta, //生成极坐标时候的角度步长,一般取值

CV_PI/180 int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线

double minLineLength=0;// 最小直线长度

double maxLineGap=0;// 最大间隔

)

(3)检测结果

(4)代码演示:

#include<opencv2\opencv.hpp>
#include<iostream>
#include <math.h>

using namespace cv;
using namespace std;

// Hough Line霍夫直线检测
int main(int argc, char** argv) {
	Mat src, src_gray, dst;
	src = imread("line.jpg");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_TITLE[] = "input image";
	char OUTPUT_TITLE[] = "hough-line-detection";
	namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_TITLE, src);

	// extract edge
	Canny(src, src_gray, 150, 200);
	cvtColor(src_gray, dst, CV_GRAY2BGR);
	imshow("edge image", src_gray);

	vector<Vec2f> lines;
	HoughLines(src_gray, lines, 1, CV_PI / 180, 150, 0, 0);
	for (size_t i = 0; i < lines.size(); i++) {
		float rho = lines[i][0]; // 极坐标中的r长度
		float theta = lines[i][1]; // 极坐标中的角度
		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, Scalar(0, 0, 255), 1, CV_AA);
	}

	/*
	vector<Vec4f> plines;
	HoughLinesP(src_gray, plines, 1, CV_PI / 180.0, 10, 0, 10);
	Scalar color = Scalar(0, 0, 255);
	for (size_t i = 0; i < plines.size(); i++) {
		Vec4f hline = plines[i];
		line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
	}*/
	imshow(OUTPUT_TITLE, dst);

	waitKey(0);
	return 0;
}

效果展示:

三、霍夫变换—圆检测
1、霍夫圆检测原理

(1)从平面坐标到极坐标转换三个参数

(2)假设平面坐标的任意一个圆上的点,转换到极坐标中:                         处有最大值,霍夫变换正是利用这个原理实现圆的检测。

2、相关API学习(代码例子)

(1)cv::HoughCircles

因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波

基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:

1)检测边缘,发现可能的圆心

2)基于第一步的基础上从候选圆心开始计算最佳半径大小

HoughCircles(

InputArray image, // 输入图像 ,必须是8位的单通道灰度图像

OutputArray circles, // 输出结果,发现的圆信息

Int method, // 方法 - HOUGH_GRADIENT

Double dp, // dp = 1;

Double mindist, // 10 最短距离-可以分辨是两个圆的,否则认为是同心圆- src_gray.rows/8 Double param1, // canny edge detection low threshold

Double param2, // 中心点累加器阈值 – 候选圆心

Int minradius, // 最小半径 Int maxradius//最大半径

)

(2)代码演示:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("circle.jpg");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}
	char INPUT_TITLE[] = "input image";
	char OUTPUT_TITLE[] = "hough circle demo";
	namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_TITLE, src);

	// 中值滤波
	Mat moutput;


![img](https://img-blog.csdnimg.cn/img_convert/0fbf9fa90abb1f2a220c999605da4934.png)
![img](https://img-blog.csdnimg.cn/img_convert/09513fbd0f23d866615dcd475d27967c.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

tput;


[外链图片转存中...(img-vJJbA8FF-1715680465502)]
[外链图片转存中...(img-KMGxDGTy-1715680465502)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenCV中的霍夫变换可以用来检测直线。下面分别介绍一下如何使用霍夫变换检测直线。 1. 检测直线 首先,需要将图像转换为灰度图像,并进行边缘检测。然后,使用cv2.HoughLines函数进行霍夫变换检测直线,该函数的参数包括输入图像、霍夫变换类型、直线的距离和角度分辨率、阈值等。具体代码如下: ``` import cv2 import numpy as np # 读取图像并转换为灰度图像 img = cv2.imread('test.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 霍夫变换检测直线 lines = cv2.HoughLines(edges, 1, np.pi/180, 200) # 绘制直线 for line in lines: rho, theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a*rho y0 = b*rho x1 = int(x0 + 1000*(-b)) y1 = int(y0 + 1000*a) x2 = int(x0 - 1000*(-b)) y2 = int(y0 - 1000*a) cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) # 显示图像 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 2. 检测 同样地,需要将图像转换为灰度图像,并进行边缘检测。然后,使用cv2.HoughCircles函数进行霍夫变换检测,该函数的参数包括输入图像、霍夫变换类型、心和半径的最小值和最大值等。具体代码如下: ``` import cv2 import numpy as np # 读取图像并转换为灰度图像 img = cv2.imread('test.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 霍夫变换检测 circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0) # 绘制 if circles is not None: circles = np.round(circles[0, :]).astype("int") for (x, y, r) in circles: cv2.circle(img, (x, y), r, (0, 255, 0), 2) # 显示图像 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 以上就是使用霍夫变换检测直线的方法,希望能对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值