一.霍夫直线变换介绍
Hough Line Transform用来做直线检测
前提条件 – 边缘检测已经完成
平面空间到极坐标空间转换
Hough Line Transform用来做直线检测
前提条件 – 边缘检测已经完成
平面空间到极坐标空间转换
二.相关API
标准的霍夫变换 cv::HoughLines从平面坐标转换到霍夫空间,最终输出是 (Θ,r) 表示极坐标空间
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
) // 一般情况是有经验的开发者使用,需要自己反变换到平面空间
霍夫变换直线概率 cv::HoughLinesP最终输出是直线的两个点(x0,y0,x1,y1)
cv::HoughLinesP(
InputArray src, // 输入图像,必须8-bit的灰度图像
OutputArray lines, // 输出的极坐标来表示直线
double rho, // 生成极坐标时候的像素扫描步长
double theta, //生成极坐标时候的角度步长,一般取值CV_PI/180
int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线
double minLineLength=0;// 最小直线长度
double maxLineGap=0;// 最大间隔
)
三.霍夫直线代码实现
/*
OpenCV 霍夫变换学习
Michael Jiang<sencom1997@outlook.com>
2019年7月26日14:34:37
*/
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
Mat src, dst, gray, hou,fin;
//读取图像
src = imread("D:/test18.png", IMREAD_COLOR);
//判断读取是否成功
if (src.empty()) {
printf("pic load failed!\n");
return -1;
}
imshow("src", src);
src.copyTo(fin);
//高斯模糊
GaussianBlur(src, dst, Size(3, 3), 0, 0, BORDER_DEFAULT);
//转灰度
cvtColor(dst, gray, COLOR_BGR2GRAY);
imshow("gray", gray);
//Canny边缘检测
Canny(gray, hou, 50, 70);
vector<Vec4f> lines;
//霍夫直线变换
HoughLinesP(hou,lines,1,CV_PI/180.0,10,50,20);
for (size_t i = 0; i < lines.size(); i++) {
Vec4f h = lines[i];
line(fin, Point(h[0], h[1]), Point(h[2], h[3]), Scalar(0, 0, 0), 3, LINE_AA);
}
imshow("fin", fin);
waitKey(0);
return 0;
}
直线全部被检测出来
四.霍夫圆变换
1.原理
从平面坐标到极坐标转换三个参数C(x0,y0,r)其中x0,y0是圆心
假设平面坐标的任意一个圆上的点,转换到极坐标中:C(x0,y0,r)处有最大值,霍夫变换正是利用这个原理实现圆的检测。
2.相关API
相关API cv::HoughCircles
因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波。
基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:
- 检测边缘,发现可能的圆心
- 基于第一步的基础上从候选圆心开始计算最佳半径大小
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//最大半径
)
3.代码实现
/*
OpenCV 霍夫变换学习
Michael Jiang<sencom1997@outlook.com>
2019年7月26日15:05:25
*/
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
Mat src, dst, gray, hou,fin;
//读取图像
src = imread("D:/test18.png", IMREAD_COLOR);
//判断读取是否成功
if (src.empty()) {
printf("pic load failed!\n");
return -1;
}
imshow("src", src);
src.copyTo(fin);
//高斯模糊
GaussianBlur(src, dst, Size(3, 3), 0, 0, BORDER_DEFAULT);
//转灰度
cvtColor(dst, gray, COLOR_BGR2GRAY);
imshow("gray", gray);
//Canny边缘检测
Canny(gray, hou, 50, 70);
vector<Vec4f> circles;
//霍夫圆变换
HoughCircles(hou, circles,HOUGH_GRADIENT,1,10,100,30,5,145);
for (size_t i = 0; i < circles.size(); i++) {
Vec4f h = circles[i];
circle(fin, Point(h[0], h[1]), h[2], Scalar(0, 0, 255), 3, LINE_AA);
circle(fin, Point(h[0], h[1]), 2, Scalar(0, 255, 0), 3, LINE_AA);
}
imshow("fin", fin);
waitKey(0);
return 0;
}