zoukankan      html  css  js  c++  java
  • 十六 直线检测

    一、霍夫直线变换原理

    推文:Opencv学习笔记-----霍夫变换直线检测及原理理解

    推文:OpenCV-Python教程(9、使用霍夫变换检测直线)

    Hough变换是经典的检测直线的算法。其最初用来检测图像中的直线,同时也可以将其扩展,以用来检测图像中简单的结构。

    1、对于直角坐标系中的任意一点A(x0,y0),经过点A的直线满足Y0=k*X0+b.(k是斜率,b是截距)

    2、那么在X-Y平面过点A(x0,y0)的直线簇可以用Y0=k*X0+b表示,但对于垂直于X轴的直线斜率是无穷大的则无法表示。因此将直角坐标系转换到极坐标系就能解决该特殊情况。

    3、在极坐标系中表示直线的方程为ρ=xCosθ+ySinθ(ρ为原点到直线的距离),如图所示:

     

    4、原理过程

    • 如上图,假定在一个8*8的平面像素中有一条直线,并且从左上角(1,8)像素点开始分别计算θ为0°、45°、90°、135°、180°时的ρ;
    • 图中可以看出ρ分别为1、(9√2)/2、8、(7√2)/2、-1,并给这5个值分别记一票;
    • 同理计算像素点(3,6)点θ为0°、45°、90°、135°、180°时的ρ,再给计算出来的5个ρ值分别记一票;
    • 此时就会发现ρ = (9√2)/2的这个值已经记了两票了;
    • 以此类推,遍历完整个8*8的像素空间的时候ρ = (9√2)/2就记了5票, 别的ρ值的票数均小于5票;
    • 所以得到该直线在这个8*8的像素坐标中的极坐标方程为 (9√2)/2=x*Cos45°+y*Sin45°;
    • 到此该直线方程就求出来了。(PS:但实际中θ的取值不会跨度这么大,一般是PI/180)。

    二、霍夫直线检测的两种方法

    1.获取灰度图像
    2.canny边缘检测
    3.获取霍夫直线信息
    4.算出直线位置,画出每条直线

    1、HoughLines霍夫变换

    (1)HoughLines函数

    def HoughLines(image, rho, theta, threshold, lines=None, srn=None, stn=None, min_theta=None, max_theta=None): 

    cv2.HoughLines函数输出的是很多的[float, float]形式的数组,其中每个值表示检测到的线(ρ , θ)中浮点点值的参数。

    cv.HoughLines(edges,1,np.pi/180,200)

    第一个参数image:是canny边缘检测后的图像

    第二个参数rho和第三个参数theta:对应直线搜索的步长。在本例中,函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线。

    最后一个参数threshold:是经过某一点曲线的数量的阈值,超过这个阈值,就表示这个交点所代表的参数对(rho, theta)在原图像中为一条直线

    (3)代码实现

     1 import cv2 as cv
     2 import numpy as np
     3 
     4 def houghlines(image):
     5     gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
     6     #用canny边缘检测,下阈值是50,上阈值是150,算子大小只能是1,3,5,7
     7     edges = cv.Canny(gray,150,250,apertureSize=3)
     8     # 函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线
     9     #lines.shape = (113,1,2)
    10     lines = cv.HoughLines(edges,1,np.pi/180,150)        #通过更改canny的上下阈值和houghlines的阈值来调整!!
    11     for line in lines:
    12         rho,theta = line[0]   #因为lines的第二维只有一个,所以得用0
    13         a = np.cos(theta)
    14         b = np.sin(theta)
    15         x0 = rho * a
    16         y0 = rho * b
    17         x_max = int(x0 + 1000*(-b))
    18         y_max = int(y0 + 1000*(a))
    19         x_min = int(x0 - 1000*(-b))
    20         y_min = int(y0 - 1000*(a))
    21         #在image上画线,起点(x_max,y_max),终点(x_min,y_min),颜色(0,0,255),线条宽度1
    22         cv.line(image,(x_max,y_max),(x_min,y_min),(0,0,255),1)
    23     cv.imshow('imageline',image)
    24 src = cv.imread('road.jpg')
    25 cv.namedWindow('input image',cv.WINDOW_NORMAL)
    26 cv.imshow('input image',src)
    27 houghlines(src)
    28 cv.waitKey(0)
    29 cv.destroyAllWindows()

    2、HoughLinesP概率霍夫变换(是加强版)使用简单,效果更好,检测图像中分段的直线(而不是贯穿整个图像的直线)

    (1)HoughLinesP函数

     HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None): 

    cv.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=50,maxLineGap=10)

    第一个参数是需要处理的原图像,该图像必须为cannay边缘检测后的图像;


    第二和第三参数:步长为1的半径和步长为π/180的角来搜索所有可能的直线

    第四个参数是阈值,概念同霍夫变换

    第五个参数:minLineLength-线的最短长度,比这个线短的都会被忽略。

    第六个参数:maxLineGap-两条线之间的最大间隔,如果小于此值,这两条线就会被看成一条线。

    (3)代码实现

     1 import cv2 as cv
     2 import numpy as np
     3 
     4 def houghlinesp(image):
     5     gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
     6     edges = cv.Canny(gray,50,150,apertureSize=3)
     7     lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=300,maxLineGap=10)
     8     for line in lines:
     9         print(type(line))
    10         x1,y1,x2,y2 = line[0]
    11         cv.line(image,(x1,y1),(x2,y2),(0,0,255),2)
    12     cv.imshow('line_demo',image)
    13 img = cv.imread('road.jpg')
    14 cv.namedWindow('input image',cv.WINDOW_FREERATIO)
    15 cv.imshow('input image',img)
    16 houghlinesp(img)
    17 cv.waitKey(0)
    18 cv.destroyAllWindows()

  • 相关阅读:
    感光板制作问答
    游戏外挂技术分析(转)
    div 显示和隐藏
    c# 构造sql语句
    Iframe自动适应高度
    .net web图表类
    通讯录从Database导出vCard格式
    winform通过HttpWebRequest(post方式)上传文件和传递参数
    c# CSV读入DataSet
    模拟器显示屏上方的信号和电池图标不显示设置
  • 原文地址:https://www.cnblogs.com/pacino12134/p/9879635.html
Copyright © 2011-2022 走看看