1.检测直线的霍夫变换原理
2.检测直线函数HoughLines()
检测直线流程:
Step1:将参数空间的坐标轴离散化。
Step2:将图像中每个非0像素通过映射关系求取在参数空间通过的方格
Step3:统计参数空间内每个方格出现的次数,选取次数大于某一值的方格作为表示直线的方格
Step4:将参数空间中表示直线的方格的参数作为图像中直线的参数
void cv::HoughLines ( InputArray image
OutputArray lines,
double rho,
double theta,
int threshold.
double srn = 0,
double stn =0,
double min_theta = 0,
double max_theta = CV_PI
)
参数说明:
- image:输入的二值图像,通常是经过边缘检测后的图像。
- lines:输出参数,包含检测到的直线的向量。
- rho:极径参数ρ的精确度,以像素为单位。
- theta:角度参数θ的精确度,以弧度为单位。
- threshold:参数空间中投票阈值,用于确定检测到的直线。
- srn、stn、min_theta、max_theta:这些参数是可选的,用于进一步细化直线检测的精度和范围。
示例代码:
void drawLine(Mat &img,//要标记直线的图像 vector<Vec2f> lines,//检测的直线数据 double rows,//原图像的行数(高) double cols,//原图像的列数(宽) Scalar scalar,//绘制直线的颜色 int n//绘制直线的线宽 ){ Point pt1,pt2; for(size_t i=0;i<lines.size();i++){ float rho=lines[i][0];//直线距离坐标原点的距离 float theta=lines[i][1];//直线过坐标原点垂线 double a=cos(theta);//夹角的余弦值 double b=sin(theta);//夹角的正弦值 double x0=a*rho,y0=b*rho;//直线与坐标原点的垂线的交点 double length=max(rows,cols);//图像高宽的最大值 //计算直线上的一点 pt1.x= cvRound(x0+length*(-b)); pt1.y= cvRound(y0+length*(a)); //计算直线上的另一点 pt2.x= cvRound(x0-length*(-b)); pt2.y= cvRound(y0-length*(a)); //两点绘制一条直线 line(img,pt1,pt2,scalar,n); } } //霍夫直线检测 void Hough_linear_detection(Mat image){ Mat gray; cvtColor(image,gray,COLOR_BGR2GRAY); Mat edge; //检测边缘图像,并二值化 Canny(gray,edge,80,180,3, false); //用不同的累加器进行检测直线 vector<Vec2f> lines1,lines2; HoughLines(edge, lines1,1,CV_PI/180,50,0,0); HoughLines(edge, lines2,1,CV_PI/180,150,0,0); //在原图像中绘制直线 Mat img1,img2; image.copyTo(img1); image.copyTo(img2); drawLine(img1,lines1,edge.rows,edge.cols,Scalar(255),2); drawLine(img2,lines2,edge.rows,edge.cols,Scalar(255),2); //显示图像 imwrite("/sdcard/DCIM/edge.png",edge); imwrite("/sdcard/DCIM/img1.png",img1); imwrite("/sdcard/DCIM/img2.png",img2); }
Canny算子边缘检测后图片 :
用累加器为50进行检测直线:
用累加器为150进行检测直线:
3.检测直线函数 HoughLinesP()
void cv::HoughLinesP ( InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength =0,
double maxLineGap = 0
)
- image:待检测直线的原图像,必须是CV_8C的单通道二值图像
- lines:霍夫变换检测到的直线输出量,每一条直线都由4个参数进行描述,分别是直线两个端点的坐标
- rho:以像素为单位的距离分辨率。
- theta: 以弧度为单位的角度分辨率
- threshold:累加器的阈值
- minLineLength: 直线的最小长度,当检测直线的长度小于该数值时将会被剔除
- maxLineGap:允许将同一行两个点连接起来的最大距离。
示例代码:
//霍夫直线检测 void Hough_linearP_detection(Mat image){ Mat gray; cvtColor(image,gray,COLOR_BGR2GRAY); Mat edge; //检测边缘图像,并二值化 Canny(gray,edge,80,180,3, false); //利用渐进概率式霍夫变换提取直线 vector<Vec4i> linesP1,linesP2; HoughLinesP(edge, linesP1,1,CV_PI/180,150,30,10);//两个点连接最大距离10 HoughLinesP(edge, linesP2,1,CV_PI/180,150,30,30);//两个点连接最大距离30 //绘制两个点连接最大距离10直线检测结果 Mat img1; image.copyTo(img1); for(size_t i=0;i<linesP1.size();i++){ line(img1,Point(linesP1[i][0],linesP1[i][1]), Point(linesP1[i][2],linesP1[i][3]),Scalar(255),3); } //绘制两个点连接最大距离30直线检测结果 Mat img2; image.copyTo(img2); for(size_t i=0;i<linesP2.size();i++){ line(img2,Point(linesP2[i][0],linesP2[i][1]), Point(linesP2[i][2],linesP2[i][3]),Scalar(255),3); } //显示图像 imwrite("/sdcard/DCIM/img10.png",img1); imwrite("/sdcard/DCIM/img20.png",img2); }
绘制两个点连接最大距离10直线检测结果:
绘制两个点连接最大距离30直线检测结果: