霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换的结果。
霍夫变换运用两个坐标空间之间的变换将一个空间中具有相同形状的曲线或直线映射到另一个坐标空间中的一个点上形成峰值。
霍夫线变换是一种来寻找直线的方法,在使用霍夫变换之前,首先对图像进行边缘检测的处理。霍夫线变换的直接输入只能是边缘二值图像。
Opencv中的霍夫线变换
极坐标表示: y=(−cosθsinθ)x+rsinθ y = ( − c o s θ s i n θ ) x + r s i n θ
可以简化为: r=xcosθ+ysinθ r = x c o s θ + y s i n θ
对于点 (x0,y0) ( x 0 , y 0 ) 可以简化为
一般来说,一条直线能够通过在平面 θ−r θ − r 寻找交于一点的曲线数量来检测。越多的曲线交于一点意味着这个交点表示的直线由更多的点组成
如果交一点的曲线数量超过阈值,那么可以认为这个交点所代表的参数对 (θ,r) ( θ , r ) 在原图像中为一条直线
void HoughLines(InputArray image, OutputArray lines,double rho, double theta,int threshold,double srn = 0, double stn = 0)
#include
#include
using namespace std;
using namespace cv;
//mian()函数
int main()
{
//载入原始图
Mat srcImage = imread("1.jpg");
Mat midImage, dstImage;
//canny检测边缘转化为灰度图
Canny(srcImage, midImage, 50, 200, 3);
cvtColor(midImage, dstImage, CV_GRAY2BGR);
//进行霍夫变换
vector lines;
HoughLines(midImage, lines, 1, CV_PI / 180, 150, 0, 0);
//一次在图中绘制出每条线段
for (size_t i = 0; i < lines.size(); i++)
{
float rho = lines[i][0];
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(dstImage, pt1, pt2, Scalar(55, 100, 195), 1, LINE_AA);
}
//显示效果图
imshow("【原始图】", srcImage);
//边缘检测之后的图
imshow("【边缘检测后的图】", midImage);
//显示效果图
imshow("【效果图】", dstImage);
waitKey(0);
return 0;
}
此函数在HoughLines的基础上,在末尾加了一个代表Probabilistic概率的P,表示采用累计概率霍夫变换PPHT来找出二值图像中的直线
void HoughLinesP(InputArray image, OutputArray lines,double rho,double theta, int threshold, double minLineLength =0 , double maxLineGap = 0)
#include
#include
using namespace std;
using namespace cv;
//mian()函数
int main()
{
//载入原始图
Mat srcImage = imread("1.jpg");
Mat midImage, dstImage;
//canny检测边缘转化为灰度图
Canny(srcImage, midImage, 50, 200, 3);
cvtColor(midImage, dstImage, CV_GRAY2BGR);
//进行霍夫变换
vector lines;
HoughLinesP(midImage, lines, 1, CV_PI / 180, 80, 50, 10);
//一次在图中绘制出每条线段
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i l = lines[i];
line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(186, 88, 255), 1, LINE_AA);
}
//显示效果图
imshow("【原始图】", srcImage);
//边缘检测之后的图
imshow("【边缘检测后的图】", midImage);
//显示效果图
imshow("【效果图】", dstImage);
waitKey(0);
return 0;
}
只要点对应的二维极径角空间被三维的圆心点 x,y x , y 和半径 r r 空间取代。表示一个圆 C:(xcenter,ycenter,r) C : ( x c e n t e r , y c e n t e r , r )
不需要源图是二值的
void HoughCircles(InputArray image,OutputArray circles,int method, int dp,int minDist,double param1 = 100,double param2 = 100,int minRadius = 0,int maxRadius = 0)
#include
#include
using namespace std;
using namespace cv;
//mian()函数
int main()
{
//载入原始图
Mat srcImage = imread("1.jpg");
Mat midImage, dstImage;
//转化为灰度图并平滑
cvtColor(srcImage, midImage, CV_BGR2GRAY);
GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);
//进行霍夫圆变换
vector circles;
HoughCircles(midImage, circles, HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);
//一次在图中绘制出每条线段
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(dstImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);
circle(dstImage, center, radius, Scalar(155, 50, 255), 3, 8, 0);
}
//显示效果图
imshow("【原始图】", srcImage);
//显示效果图
imshow("【效果图】", srcImage);
waitKey(0);
return 0;
}
#include
#include
#include
using namespace std;
using namespace cv;
//原始图,中间图和效果图
Mat g_srcImage, g_dstImage, g_midImage;
vector g_lines;
int g_nthreshold = 100;
//全局函数声明
static void on_HoughLines(int, void *);
//main()函数
int main()
{
//改变console字体颜色
system("color 3F");
//载入原始图
g_srcImage = imread("1.jpg");
//显示原始图
imshow("【原始图】", g_srcImage);
//创建滚动条
namedWindow("【效果图】", 1);
createTrackbar("值:", "【效果图】", &g_nthreshold, 200, on_HoughLines);
//进行边缘检测和转化为灰度图
Canny(g_srcImage, g_midImage, 50, 200, 3);
cvtColor(g_midImage, g_dstImage, COLOR_GRAY2BGR);
//调用回调函数
on_HoughLines(g_nthreshold, 0);
HoughLinesP(g_midImage, g_lines, 1, CV_PI / 180, 80, 50, 10);
//显示效果图
imshow("【效果图】", g_dstImage);
waitKey(0);
return 0;
}
static void on_HoughLines(int, void *)
{
//定义局部变量
Mat dstImage = g_dstImage.clone();
Mat midImage = g_midImage.clone();
//调用HoughLinesP函数
vector mylines;
HoughLinesP(midImage, mylines, 1, CV_PI / 180, g_nthreshold + 1, 50, 10);
//循环遍历绘制每一个线段
for (size_t i = 0; i < mylines.size(); i++)
{
Vec4i l = mylines[i];
line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(23, 180, 55), 1, LINE_AA);
}
//显示图像
imshow("【效果图】",dstImage);
}