博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenCV-Python:霍夫变换
阅读量:7111 次
发布时间:2019-06-28

本文共 2570 字,大约阅读时间需要 8 分钟。

霍夫变换常用来在图像中提取直线和圆等几何形状。如下图:

我们下面来看看如何使用霍夫变换来检测直线。一条直线可以用数学表达式 y = mx + 或者 ρ = xcosθ + y sinθ表示(极坐标)

简单说明一下:

ρ 是从原点到直线的垂直距离,θ是直线的垂线与横轴顺时针方向的夹角,如下图所示:

首先创建一个2D数组(累加器),初始化累加器,所有的值都为0。行表示 ρ,列表示 θ。这个数组的大小决定了最后结果的准确性。如果你希望角度精确到1°,你就需要180列。对于 ρ,最大值为图片对角线距离。

想象一下我们有一个大小为100x100的直线位于图像中央。取直线上的第一个点,我们知道此处的(x,y)值,把x和y带入公式:ρ = xcosθ + y sinθ,然后遍历 θ 的取值0, 1, 2, 3,...,180.分别求出对应的 ρ 值,这样我们就得到了一系列(ρ,θ)的数值对,如果这个数值对在累加器中也存在相应的位置,就在这个位置上加 1。由于同一条直线上的点必然会有同样的(ρ,θ)。所以现在累加器中的(50,90)=1。现在取直线上的第二个点。重复上边的过程。更新累加器中的值。现在累加器中(50,90)的值为 2。你每次做的就是更新累加器中的值。对直线上的每个点都执行上边的操作,每次操作完成之后,累加器中的值就加 1,但其他地方有时会加 1, 有时不会。按照这种方式下去,到最后累加器中(50,90)的值肯定是最大的。如果你搜索累加器中的最大值,并找到其位置(50,90),这就说明图像中有一条直线,这条直线到原点的距离为 50,它的垂线与横轴的夹角为 90 度。

OpenCV中首先计算(r,θ) 累加数,累加数超过一定值后就认为在同一直线上(有一个阈值)。

霍夫直线变换

import cv2import numpy as np# 1.加载图片,转为二值图img = cv2.imread('shapes.jpg')drawing = np.zeros(img.shape[:], dtype=np.uint8)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)edges = cv2.Canny(gray, 50, 150)# 2.霍夫直线变换lines = cv2.HoughLines(edges, 0.8, np.pi / 180, 90)

函数中:

  • 参数1:要检测的二值图(一般是阈值分割或边缘检测后的图)
  • 参数2:距离 ρ 的精度,值越大,考虑越多的线
  • 参数3:角度 θ 的精度,值越小,考虑越多的线
  • 参数4:累加数阈值,值越小,考虑越多的线
# 3.将检测的线画出来(注意是极坐标噢)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))    cv2.line(drawing, (x1, y1), (x2, y2), (0, 0, 255))

统计概率霍夫直线变换

前面的方法又称为标准霍夫变换,它会计算图像中的每一个点,计算量比较大,另外它得到的是整一条线,并不知道原图中直线的端点。所以提出了概率霍夫直线变换(Probabilistic Hough Transform),是一种改进的霍夫变换:

drawing = np.zeros(img.shape[:], dtype=np.uint8)# 统计概率霍夫线变换lines = cv2.HoughLinesP(edges, 0.8, np.pi / 180, 90, minLineLength=50, maxLineGap=10) # 将检测的线画出来for line in lines:    x1, y1, x2, y2 = line[0]    cv2.line(drawing, (x1, y1), (x2, y2), (0, 255, 0), 1, lineType = cv2.LINE_AA)cv2.imwrite('houghlines4.jpg', drawing)

参数:

  • minLineLength:最短长度阈值,比这个长度短的线会被排除
  • maxLineGap:同一直线两点之间的最大距离

cv2.LINE_AA:抗锯齿线型

霍夫圆变换

霍夫圆变换跟直线变换类似,只不过线是用(r,θ),圆是用(x_center,y_center,r)来表示,从二维变成了三维,数据量变大了很多;所以一般使用霍夫梯度法去减少计算量

drawing = np.zeros(img.shape[:], dtype=np.uint8)# 霍夫圆变换circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 20, param2=30)circles = np.int0(np.around(circles))# 将检测的圆画出来for i in circles[0, :]:    cv2.circle(drawing, (i[0], i[1]), i[2], (0, 255, 0), 2)  # 画出外圆    cv2.circle(drawing, (i[0], i[1]), 2, (0, 0, 255), 3)  # 画出圆心cv2.imwrite('HoughCircles.jpg', drawing)
  • 参数2:变换方法,一般使用霍夫梯度法,详情:
  • 参数3 dp=1:表示霍夫梯度法中累加器图像的分辨率与原图一致
  • 参数4:两个不同圆圆心的最短距离
  • 参数5:param2跟霍夫直线变换中的累加数阈值一样

 

转载于:https://www.cnblogs.com/gezhuangzhuang/p/10737499.html

你可能感兴趣的文章
第四次作业
查看>>
PPPoA、PPPoE
查看>>
JVM-详解
查看>>
四中copy数组方法的效率比较
查看>>
解决tmux在非root下无法正常运行的问题
查看>>
校色、调色
查看>>
Linux-VIM使用总结
查看>>
iptables/netfilter详解中文手册
查看>>
网络部署Xenserver6.5
查看>>
php pdo连接报错Connection failed: SQLST
查看>>
Struts2中处理请求的流程
查看>>
asp.net web api [FromBody]参数
查看>>
phpcms 2008 修改编辑器工具栏问题
查看>>
seconds_behind_master问题分析一则
查看>>
linux清理内存
查看>>
如何自己动手实现 KVO
查看>>
硬盘整数分区 C语言源码
查看>>
【马哥linux学员学习笔记】MySQL多实例详解
查看>>
数据库连接池操作步骤及遇到的相应问题
查看>>
谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词
查看>>