OpenCV—直线检测与圆检测

直线检测

直线检测可以通过OpenCV的HoughLines和HoughLinesP函数来完成,它们仅有的差别是:第一个函数使用标准的Hough变换,第二个函数使用概率Hough变换,即只通过分析点的子集并估计这些点都属于一条直线的概率,这在计算速度上更快。

函数原型:HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None)

参数设置:

  • image:必须是二值图像,推荐使用canny边缘检测的结果图像;
  • rho:线段以像素为单位的距离精度,double类型的,推荐用1.0;
  • theta:线段以弧度为单位的角度精度,推荐用numpy.pi/180;
  • threshold:累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。根据情况推荐先用100试试;
  • lines:这个参数的意义未知,发现不同的lines对结果没影响,但是不要忽略了它的存在;
  • minLineLength:线段以像素为单位的最小长度,根据应用场景设置;
  • maxLineGap:同一方向上两条线段判定为一条线段的最大允许间隔(断裂),超过了设定值,则把两条线段当成一条线段,值越大,允许线段上的断裂越大,越有可能检出潜在的直线段

 

import cv2 as cv
import numpy as np


def hons_line_demo(img):
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    edge = cv.Canny(gray, 50, 150)
    lines = cv.HoughLines(edge, 1, np.pi/180, 200)
    for line in lines:
        rho , theta = line[0]
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a + rho
        y0 = b + rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000 * (a))
        x2 = int(x0 - 1000 * (-b))
        y2 = int(y0 - 1000 * (a))
        cv.line(img,(x1, y1), (x2, y2),(0, 0, 255), 2)
    cv.imshow("line img", img)


def hon_line_demo(img):
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    edge = cv.Canny(gray, 50, 150)
    lines = cv.HoughLinesP(edge, 1, np.pi/180, 100 ,minLineLength=50, maxLineGap=10)
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv.line(img, (x1, y1), (x2, y2), (0, 0 ,255), 2)
    cv.imshow("hone_line", img)


src = cv.imread("./../img/8.png") # 读取图像
cv.namedWindow("input img", cv.WINDOW_AUTOSIZE)
cv.imshow("input img", src) # 显示图像
hons_line_demo(src)
hon_line_demo(src)

cv.waitKey(0)
cv.destroyAllWindows()

 

 园检测

霍夫圆变换只能检测一些简单情形下的圆形,并且检测不出椭圆

首先对原图进行canny边缘检测,然后用findContours查找轮廓,遍历轮廓上的每一个点,可以得到轮廓上距离最远的两个点,他们的中点可以假定为圆心,这两点间距离可假定为直径,如果轮廓上每个点到这个中点距离在这个半径附近波动,则认为是一个圆(这里最好归一化处理,因为直径大的波动范围,和直径小的波动范围肯定不能用一个阈值)


HoughCircles函数实现了圆形检测,它使用的算法是改进的霍夫变换,该算法把霍夫变换分为两个阶段,从而减小了霍夫空间的维数。第一阶段用于检测圆心,第二阶段从圆心推导出圆半径。

霍夫变换具体步骤:
第一阶段:检测圆心
1.1、对输入图像边缘检测;
1.2、计算图形的梯度,并确定圆周线,其中圆周的梯度就是它的法线;
1.3、在二维霍夫空间内绘出所有图形的梯度直线,坐标点累加和的值越大,则该点上直线相交的次数越多,该点越有可能是圆心;
1.4、在霍夫空间的4邻域内进行非最大值抑制;
1.5、设定一个阈值,霍夫空间内累加和大于该阈值的点就对应于圆心。
第二阶段:检测圆半径
2.1、计算某一个圆心到所有圆周线的距离,这些距离中就有该圆心所对应的圆的半径的值,这些半径值当然是相等的,并且这些圆半径的数量要远远大于其他距离值相等的数量;
2.2、设定两个阈值:最大半径和最小半径。保留距离在这两个半径之间的值,这意味着我们检测的圆不能太大,也不能太小;
2.3、对保留下来的距离进行排序;
2.4、找到距离相同的那些值,并计算相同值的数量;
2.5、设定一个阈值,只有相同值的数量大于该阈值,就认为该值是该圆心对应的圆半径;
2.6、对每一个圆心,完成上面的2.1~2.5步骤,得到所有的圆半径。

def HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None): 

 

image为输入图像,要求是灰度图像

method为使用霍夫变换圆检测的算法,Opencv2.4.9只实现了2-1霍夫变换,它的参数是CV_HOUGH_GRADIENT

dp为第一阶段所使用的霍夫空间的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半,以此类推

minDist为圆心之间的最小距离,如果检测到的两个圆心之间距离小于该值,则认为它们是同一个圆心

circles为输出圆向量,每个向量包括三个浮点型的元素——圆心横坐标,圆心纵坐标和圆半径

param1为边缘检测时使用Canny算子的高阈值

param2为步骤1.5和步骤2.5中所共有的阈值

minRadius和maxRadius为所检测到的圆半径的最小值和最大值

 

执行步骤:

1、执行均值偏移滤波,消除噪声

2、转成灰度图

3、canny边缘检测

4、执行霍夫圆检测

5、绘制出检测到的圆

def check_circular_demo(img):
    # 均值偏移滤波
    dst = cv.pyrMeanShiftFiltering(img, 10, 100)
    # 转成灰度图
    gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
    # 执行霍夫圆检测
    circular = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0)
    '''
       HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None)
       image: 输入图像
       method: 检测方法 
       minDist: 检测到圆心之间的最小距离 img.rows/8
       circles: 返回结果 (x,y,r)
       param1: canny边缘函数的高阈值
       param2: 圆心检测阈值
       minRadius: 能检测到的最小圆半径
       maxRadius: 能检测到的最大圆半径
    '''
    circular = np.uint16(np.around(circular))
    for i in circular[0, :]:
        cv.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)
        cv.circle(img, (i[0], i[1]), 2, (255, 0, 0), 2)
    cv.imshow("circular", img)

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值