Hough变换是图像处理中从图像中识别几何形状的基本方法之一
原理看视频:
https://www.bilibili.com/video/BV16i4y1R7kf?spm_id_from=333.999.0.0
霍夫直线检测
- 标准的霍夫变换 cv::HoughLines从平面坐标转换到霍夫空间,最终输出是 表示极坐标空间
- 霍夫变换直线概率 cv::HoughLinesP最终输出是直线的两个点
霍夫线变换是一种用来寻找直线的方法. 在使用霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像
OpenCV支持三种不同的霍夫线变换,它们分别是:
标准霍夫变换(Standard Hough Transform,SHT),
多尺度霍夫变换(Multi-Scale Hough Transform,MSHT),
累计概率霍夫变换(Progressive Probabilistic Hough Transform ,PPHT)
在OpenCV中,我们可以用HoughLines函数来调用标准霍夫变换SHT和多尺度霍夫变换MSHT。
而HoughLinesP函数用于调用累计概率霍夫变换PPHT。累计概率霍夫变换执行效率很高,所有相比于HoughLines函数,我们更倾向于使用HoughLinesP函数
HoughLinesP寻找直线
10.jpg
#include<opencv2/opencv.hpp> #include<iostream> int main(int argc, char** argv) { cv::Mat src = cv::imread("D:/bb/tu/10.jpg"); if (!src.data) { printf("图像读取失败...\n"); return -1; } cv::imshow("src", src); cv::Mat canny, dst; Canny(src, canny, 50, 255); //获取边缘 imshow("canny", canny); cvtColor(canny, dst, cv::COLOR_GRAY2BGR);//将二值图转换为RGB图颜色空间 std::vector<cv::Vec4f> plines;//保存霍夫变换检测到的直线 HoughLinesP(canny, plines, 1, CV_PI / 180, 10, 0, 10);//霍夫变换---寻找直线 //提取边缘时,会造成有些点不连续,所以maxLineGap设大 /* 参数1:InputArray src 输入图像,必须8-bit的灰度边缘图像 参数2:输出的极坐标来表示直线,经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量, 每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是 每个检测到的线段的起点和结束点。 参数3:double rho 生成极坐标时的像素扫描步长,一般取值为1 参数4:double theta 生成极坐标时的角度步长,一般取值CV_PI/180,即表示一度 参数5:int threshold 阈值,只有获得足够交点的极坐标点才被看成是直线 参数6:double minLineLength=0 最小直线长度,有默认值0,表示最低线段的长度,比这个 设定参数短的线段就不能被显现出来 参数7:double maxLineGap=0 最大间隔,有默认值0,允许将同一行点与点之间连接起来的最大的距离 【间隔小于等于这个数,就认为是连续直线】 */ std::cerr << plines.size() << std::endl;//检测到的直线数量 cv::Scalar color = cv::Scalar(0, 0, 255);//设置颜色 for (size_t i = 0; i < plines.size(); i++) { cv::Vec4f hline = plines[i];//提取直线坐标 line(dst, cv::Point(hline[0], hline[1]), cv::Point(hline[2], hline[3]), color, 1, cv::LINE_AA);//绘制直线 } cv::imshow("检测到的直线", dst); cv::waitKey(0); return 0; }
HoughLines寻找直线
#include<opencv2/opencv.hpp> #include<iostream> int main(int argc, char** argv) { cv::Mat src = cv::imread("D:/bb/tu/10.jpg"); if (!src.data) { printf("图像读取失败...\n"); return -1; } cv::imshow("src", src); cv::Mat canny, dst; Canny(src, canny, 50, 255); //获取边缘 imshow("canny", canny); cvtColor(canny, dst, cv::COLOR_GRAY2BGR);//将二值图转换为RGB图颜色空间 std::vector<cv::Vec4f> plines;//保存霍夫变换检测到的直线 HoughLines(canny, plines, 1, CV_PI / 180, 10, 0, 0);//霍夫变换---寻找直线 /* 参数1:InputArray src 输入图像,必须8-bit的灰度边缘图像 参数2:OutputArray lines 输出的极坐标来表示直线,经过调用HoughLines函数后储存了霍 夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量(ρ,θ)表示,其 中,ρ是离坐标原点((0,0)(也就是图像的左上角)的距离。 θ是弧度线条旋转角度 (0~ 垂直线,π/2~水平线)。 参数3:double rho 生成极坐标时的像素扫描步长,一般取值为1,不要大于图像尺寸的一半 参数4:double theta 生成极坐标时的角度步长,一般取值CV_PI/180,即表示一度 参数5:int threshold 阈值,只有获得足够交点的极坐标点才被看成是直线,大于阈值的线段 才可以被确认为直线 参数6:double srn=0 是否应用多尺度的霍夫变换;设置0表示经典霍夫变换, 多尺度表示的是使用图像金字塔,即多尺度图上进行霍夫变换 参数7:stn,默认值为 0。也是多尺度霍夫线变换才会用到的参数。对于多尺度霍夫线变换, 平面 - 中 θ 轴的单位长度 = theta / stn。如果 srn、stn 同时为 0,就表示使用 经典霍夫变换,否则两个参数都应该为正数 */ std::cerr << plines.size() << std::endl;//检测到的直线数量 cv::Scalar color = cv::Scalar(0, 0, 255);//设置颜色 for (size_t i = 0; i < plines.size(); i++) { cv::Vec4f hline = plines[i];//提取直线坐标 line(dst, cv::Point(hline[0], hline[1]), cv::Point(hline[2], hline[3]), color, 1, cv::LINE_AA);//绘制直线 } cv::imshow("检测到的直线", dst); cv::waitKey(0); return 0; }
寻找圆
2.jpg
#include<opencv2/opencv.hpp>] #include<iostream> int main(int argc, char** argv) { cv::Mat src = cv::imread("D:/bb/tu/2.jpg"); if (!src.data) { printf("图像读取失败...\n"); return -1; } cv::imshow("src", src); cv::Mat gray_src, dst; medianBlur(src, dst, 5);//因为霍夫圆检测对噪声比较敏感,故须先做中值滤波 cvtColor(dst, gray_src, cv::COLOR_BGR2GRAY); imshow("gray", gray_src); std::vector<cv::Vec3f> circles;//用Vec3f:一个圆需要三个数:圆心x y 半径r HoughCircles(gray_src, circles, cv::HOUGH_GRADIENT, 1, 10, 150, 50, 50, 100);//寻找圆 /* 参数1:输入图像 ,必须是8位的单通道灰度图像 参数2:输出结果,发现的圆信息 参数3:目前opencv只有霍夫梯度法一种方法可用,该参数填HOUGH_GRADIENT即可 参数4:double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数 允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如 果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度 参数5:为霍夫变换检测到的圆的圆心之间的最小距离 参数6:它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT, 它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半 参数7:也是第三个参数method设置的检测方法的对应的参数,对当前唯一的方法霍夫梯度法HOUGH_GRADIENT, 它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能 通过检测的圆就更加接近完美的圆形了 参数8:表示圆半径的最小值 参数9:表示圆半径的最大值 */ std::cerr << circles.size() << std::endl;//找到的圆的数量 //画出圆和圆心 for (size_t i = 0; i < circles.size(); i++) { cv::Vec3f cc = circles[i]; std::cout << "=" << std::endl << cc << std::endl;//查看图像中圆的信息 circle(src, cv::Point(cc[0], cc[1]), cc[2], cv::Scalar(0, 0, 255), 2, cv::LINE_AA);//画圆 circle(src, cv::Point(cc[0], cc[1]), 2, cv::Scalar(255, 0, 0), 2, cv::LINE_AA);//标记出圆心(这里把圆的半径设为2,并把标记线的粗细设为2,刚好画出一个实心的圆心) } imshow("result", src); cv::waitKey(0); return 0; }