霍夫变换
极坐标
直线检测
流程步骤:
- 将空域坐标中的点通过极坐标转换到极坐标空间(霍夫空间)上
- 在霍夫空间中相交的点所代表的直线,即为这些点所在的直线
- 再使用极坐标将这些霍夫在霍夫空间中投票选好的点逆变换回直角坐标中的直线
圆检测
流程步骤
- 先对图片进行中值滤波,因为霍夫圆检测对图片中的椒盐噪声比较敏感
- 进行canny边缘检测,先筛选出可能是边缘的点
- 利用参数方程将直角坐标系转换为极坐标系
- 假设每个像素点都是圆心(a,b)后,确定了(a,b)后变动θ和R画多个圆,而这些圆交于一点时那就是一个圆的圆心,而半径则有可能是多个(由那些点到此点的距离来决定)
API简介
直线检测
HoughLines(
InputArray src,//输入图像,必须是8-bit的灰度图
OutputArray lines,//输出图像,是极坐标形式的直线
double rho,//生成极坐标时候的像素扫描步长,以像素为单位的距离步长。
double theta,//生成极坐标时候的角度扫描步长,以弧度为单位的角度步长。
int threshold,//阈值,只有获得足够交点的极坐标才会被视为是一条有效的直线
double srn=0,//默认值为0,用于在多尺度霍夫变换中作为参数rho的除数,rho=rho/srn。
double stn=0,//默认值为0,用于在多尺度霍夫变换中作为参数theta的除数,theta=theta/stn。
double min_theta,//表示角度扫描范围0~180之间,默认即可
double max_theta = CV_PI//
)
//需要自己将他反变换回直角坐标系中
HoughLinesP
(
InputArray src,//输入图像,必须是8-bit的灰度图
OutputArray lines,//输出直线,是直角坐标形式的直线
double rho,//生成极坐标时候的像素扫描步长
double theta,//生成极坐标时候的角度扫描步长,通常取CV_PI/180
double minLineLength = 0,//最小直线长
double maxLineGap = 0,//最大间隔,即直线与直线之间的间隔
)
//直接返回直角坐标系中的直线
圆检测
HoughCircles(
InputArray src,//输入图像,必须是8-bit的灰度图
OutputArray lines,//输出结果,发现圆的信息
Int method,//方法 HOUGH_GRADENT 基于梯度的
Double dp,//dp = 1 ,DIP,即尺度
Double mindist,//两个圆弧相隔的最短距离,比这个距离小就认为是同一个圆,大于则认为是同心圆
Double param1,//canny的弱边缘阈值
Double param2,//中心点累加器的阈值,即有多数个像素在同一弧度上,才判断为圆,设定此值需要参考半径
Int minradiux,//最小半径
Int maxradiux,//最大半径
)
代码与实践
直线检测
#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
//src = imread("src.jpg");
Mat src = imread("1.PNG");
Mat edge_img;
if (!src.data)
{
cout << "cannot open image" << endl;
return -1;
}
Mat gray_src;
cvtColor(src, gray_src, COLOR_BGR2GRAY);
Canny(src, edge_img, 150, 250);
imshow("edge image", edge_img);
vector<Vec4f> plines;
//创建向量存储检测结果
HoughLinesP(edge_img, plines, 1, CV_PI/180.0, 10, 0, 5);
//检测直线
Scalar color = Scalar(0, 0, 255);
for (size_t i = 0; i < plines.size(); i++)
{
Vec4f hline = plines[i];
line(gray_src, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
}
imshow("OUTPUT", gray_src);
waitKey(0);
return 0;
}
#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
Mat src = imread("5.jpg");
//Mat src = imread("1.PNG");
Mat edge_img;
if (!src.data)
{
cout << "cannot open image" << endl;
return -1;
}
Mat moutput;
medianBlur(src, moutput,3);
cvtColor(moutput, moutput, COLOR_BGR2GRAY);
vector<Vec3f> pcircles;
//创建向量存储检测结果
HoughCircles(moutput, pcircles, HOUGH_GRADIENT, 1, 15, 30, 35, 15, 50);
//检测圆
Scalar color = Scalar(0, 255, 0);
for (size_t i = 0; i < pcircles.size(); i++)
{
Vec3f cc = pcircles[i];
circle(src, Point(cc[0], cc[1]), cc[2], color, 2);
circle(src, Point(cc[0], cc[1]), 2, color, 2);
}
imshow("OUTPUT", src);
waitKey(0);
return 0;
}