opencv之霍夫变换直线检测

霍夫变换检测

霍夫变换之直线检测

  • 霍夫变换直线检测
  • 前提条件-边缘检测已经完成
  • 平面空间到极坐标空间的转换(空间域向霍夫域的转换)

x = ρ c o s θ x=ρcos\theta x=ρcosθ

y = ρ s i n θ y=ρsin\theta y=ρsinθ

ρ 2 = x 2 + y 2 ρ^2=x^2+y^2 ρ2=x2+y2

t a n θ = y / x ( x ≠ 0 ) tan\theta=y/x(x≠0) tanθ=y/x(x=0)

检测原理
两点确定一条直线,通过一点可以确定无数条直线,极坐标直线公式 ρ = x c o s θ + y s i n θ ρ=xcos\theta+ysin\theta ρ=xcosθ+ysinθ
每个点通过角度取不同的值,都能在横坐标为角度值,纵坐标为ρ值的坐标系内确定一条曲线,只要角度值的精细度足够。ρ代表直线到原点的距离。对每个像素采取这样的操作,将会得出很多这样的曲线,这些曲线的交点证明,这些点所在的那个角度所通过的直线到原点距离相等,则证明这些点就在同一条直线上。从运算的复杂程度来看opencv不可能采取那样精细的角度范围。但大致原理基本如此。

  • 对于任意一条直线上的所有点来说
  • 变换到极坐标,从[0~360]空间,可以得到r的大小
  • 属于同一条直线点在极坐标(r,theta)必然在一个点上有最强的信号出现,根据此反算到平面坐标中可以得到直线上各点的像素坐标。从而得到直线
    参考链接:
    https://blog.csdn.net/u013263891/article/details/82867251
    https://blog.csdn.net/fengjiexyb/article/details/78075888
    https://blog.csdn.net/weixin_40196271/article/details/83346442

相关API

  • 标准的霍夫变换cv::HoughLines从平面坐标转换到霍夫空间,最终输出是(角度,极轴)表示极坐标空间
  • 霍夫变换直线概率cv::HoughLinesP最终输出是直线的两个点(x0,y0,x1,y1)

函数API(不常用)
void 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 )
函数参数

  • 第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。
  • 第二个参数,InputArray类型的lines,经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量表示,其中,是离坐标原点((0,0)(也就是图像的左上角)的距离。 是弧度线条旋转角度(0~垂直线,π/2~水平线)
  • 第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。PS:Latex中/rho就表示 。
  • 第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
  • 第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
  • 第六个参数,double类型的srn,有默认值0。对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离。粗略的累加器进步尺寸直接是第三个参数rho,而精确的累加器进步尺寸为rho/srn
  • 第七个参数,double类型的stn,有默认值0,对于多尺度霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离。且如果srnstn同时为0,就表示使用经典的霍夫变换。否则,这两个参数应该都为正数。
  • 第八个参数,double类型的 min_theta,对于标准和多尺度Hough变换,检查线条的最小角度。必须介于0和max_theta之间。
  • 第九个参数,double类型的 max_theta, 对于标准和多尺度Hough变换,检查线条的最大角度。必须介于min_thetaCV_PI之间.

函数API(常用)
void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )

参数介绍

  • 第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。
  • 第二个参数,InputArray类型的lines,经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)(x_2, y_2) 是是每个检测到的线段的结束点。
  • 第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。
  • 第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
  • 第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
  • 第六个参数,double类型的minLineLength,有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。
  • 第七个参数,double类型的maxLineGap,有默认值0,允许将同一行点与点之间连接起来的最大的距离。

代码演示

#include <iostream>  
#include <fstream>
#include <opencv2/opencv.hpp>
#include <math.h>

cv::Mat src; 
cv::Mat gray_src;
int cur_val=240;
int max_val=255;
void canny_demo(int ,void *);
int main(void)
{
    string pic = string(Pic_Path) + string(Pic_Name);
    cout << pic << endl;
	
    src = cv::imread(pic.c_str());
    cv::namedWindow("原始图片",cv::WINDOW_AUTOSIZE);
    cv::imshow("原始图片",src);
    
    cv::cvtColor(src,gray_src,cv::COLOR_BGR2GRAY);
    
    cv::namedWindow("边缘检测",cv::WINDOW_AUTOSIZE);
    cv::createTrackbar("边缘阈值调整","边缘检测",&cur_val,max_val, canny_demo);
    canny_demo(0,0);
    
    cv::waitKey(0);
    cv::destroyAllWindows();

}
void canny_demo(int ,void *)
{
    cv::Mat canny_dst;
    
    //边缘检测 使用动态的边缘检测范围 检测尺寸为3 使用非精确的近似算法
    cv::Canny(gray_src,canny_dst,cur_val,cur_val*2,3,false);
    cv::imshow("边缘检测",canny_dst);
 
    vector<cv::Vec4f> plines;   //定义直线向量容器  可以理解为数组 存储所有的直线概率点集合
    
    //直线检测 直线概率点 一个像素点为检测的步进检测步长 一度的检测角度 低于10个的直线点集合过滤 
    cv::HoughLinesP(canny_dst,plines,1,CV_PI/180.0,60,100,20);
    
    cv::Mat dst = cv::Mat(canny_dst.size(),src.type());
    //定义颜色
    cv::Scalar color = cv::Scalar(39,0,235);
    for(int i=0;i<plines.size();i++)
    {
        //定义一个二维向量点元素 临时存储每个二维向量点
        cv::Vec4f hline = plines[i];
        //划线 定义线宽 去锯齿
        cv::line(dst,cv::Point(hline[0],hline[1]),cv::Point(hline[2],hline[3]),color,2,cv::LINE_AA);
    }
    if(dst.empty())
    {
        cout << "图片为空 退出" << cur_val<< endl;
        return ;
    }
    cv::medianBlur(dst,dst,3);
    //cv::namedWindow("直线检测",cv::WINDOW_AUTOSIZE);
    //cv::imshow("直线检测",dst);
    cv::Mat cacul;
    cv::addWeighted(src,0.8,dst,1,0,cacul);
    cv::namedWindow("检测叠加",cv::WINDOW_AUTOSIZE);
    cv::imshow("检测叠加",cacul);
f
}

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值