A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

内容来自OpenCV-Python Tutorials 自己翻译整理

目标:
理解概念
在图片中检测直线
学习函数cv2.HoughLines(),cv2.HoughLinesP()

原理:
霍夫变换在检测各种形状的技术中十分流行,如果能用数学表达式写出图形的公式,就可以使用霍夫变换来进行检测。

待检测的物体可以存在一些破坏和变型。

直线的表达式为<span class="MathJax" id="MathJax-Element-714-Frame" tabindex="0" data-mathml="y=mx+c" role="presentation" style="box-sizing: border-box; outline: 0px; display: inline; line-height: normal; text-align: left; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; word-break: break-all; position: relative;">y=mx+cy=mx+c或者用极坐标表示为,<span class="MathJax" id="MathJax-Element-715-Frame" tabindex="0" data-mathml="ρ=xcosθ+ysinθ" role="presentation" style="box-sizing: border-box; outline: 0px; display: inline; line-height: normal; text-align: left; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; word-break: break-all; position: relative;">ρ=xcosθ+ysinθρ=xcosθ+ysinθ

ρ表示从原点到直线的垂直距离,θ表示直线的垂线与横轴顺时针方向的夹角。

直线在原点下方,ρ是正值,角度小于180。直线在原点上方经过,角度不是大于180度,而是小于180度,但是ρ值取负值。垂直的时候角度为0,水平的时候角度为90度。

霍夫变换是如何实现的?
每条直线都可以用(ρ,θ)表示。
首先创建一个2D数组或者累加器(用来存储两个参数),初始化数组为0。行表示ρ,列表示θ。数组的大小决定了结果是否准确。如果要精度为1度,那么需要180列。
ρ值最大为图片对角线的距离。如果精度要求达到像素级别,那么行数应该等于图像对角线的长度。

如果有一个100×100的水平直线在图像中央(在第50行的位置)。取直线上第一个点(x,y),将点带入方程,遍历θ值从0到180.求出对应的ρ值,这样得到敌对(ρ,θ),如果该值再创建的2D数组(累加器)中的对应位置上也存在,那个该位置加1。所以累加器中位置(50,90)=1。(一个点可能在多条直线当中,所以一个点可能对应多个值加1)。取直线第二个点,重复上述过程。更新累加器中的值。此时(50,90)的值为2。对直线上每个点都按照这种方式操作,最后(50,90)的值肯定最大。这就说明有一条直线。

(注意上面能选取到直线上的点的原因是因为选取的图像边缘信息点)

opencv中的霍夫变换
使用函数cv2.HoughLines(),返回(ρ,θ),ρ的单位是像素,θ是弧度。
输入参数:第一个参数是二值化图像,进行霍夫变换之前要进行二值化或者canny边缘检测。第二第三个参数代表ρ和θ的精度。第四个参数是阈值,只有当累加器中的值高于阈值时才被当成是直线。

import cv2

import numpy as np

img = cv2.imread('18.jpg')

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

edges = cv2.Canny(gray,50,150,apertureSize = 3)

lines = cv2.HoughLines(edges,1,np.pi/180,200)

for rho,theta in lines[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))

    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)

cv2.imwrite('houghlines3.jpg',img)

概率霍夫变换

上面的过程可以看到一条直线需要两个参数,这需要大量计算。概率检测是一种优化,它不是对每一个点都检测,而是在图像中随机选取点集合进行运算,检测直线足够用,但是要降低阈值。

函数为 cv2.HoughLinesP()

参数为minLineLength表示直线长度的阈值,少于此长度的会被忽略。MaxLineGap两天直线的间隔,小于此值会被当成一条直线。

返回值为直线的起点和终点。


5 个回复

倒序浏览
奈斯,优秀
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马