一、霍夫变换

本文主要介绍霍夫变换检测直线和圆的原理。

霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。主要用来从图像中分离出具有某种相同特征的集合图像(如,直线,圆等)。最基本的霍夫变换是从黑白图像中检测直线(线段)。

1、直线检测

1.1 直线的表示方式

对于平面中的一条直线,在笛卡尔坐标系中,常见的有两点式,点斜式表示方式。然而在Hough变换中,考虑的是另外一种表示方式:使用( r , θ r,\theta r,θ) 来 表 示 一 条 直 线 。 其 中 , r 为 该 直 线 到 原 点 的 距 离 , 来表示一条直线。其中,r为该直线到原点的距离, 线r线\theta$为该直线的垂线与x轴的夹角。如图下所示:

在这里插入图片描述$

也就是霍夫变换中表示一条直线的参数变成了(r, θ \theta θ)。

2.如何判断多个点是否在同一直线上

当我们的对象变成点时,我们知道一个点可以发射出无数条直线,根据霍夫变换的直线表达形式,假设这个点为i,则通过这个点的直线我们用( r i , θ i r_i,\theta_i ri,θi)表示。再假设一个点为j,则通过点j的一系列直线我们用( r j , θ j r_j,\theta_j rj,θj)表示。我们知道两点决定一条直线,所以这两个点的直线必定有 r i = r j , θ i = θ j r_i=r_j,\theta_i= \theta_j ri=rj,θi=θj的时候。
那如果是三个点呢,假设第三个点是k,则通过k点的一系列直线为( r k , θ k r_k,\theta_k rk,θk),如果三点在一条直线上,那必定有某个 r i = r j = r k = r , θ i = θ j = θ k = θ r_i=r_j=r_k = r,\theta_i = \theta_j= \theta_k = \theta ri=rj=rk=r,θi=θj=θk=θ
在霍夫变换检测直线时我们需要找到这样一样直线,如何找到这条直线呢?

3.如何检测出直线

使用hough变换来检测直线的思想就是:为每一个点假设n个方向的直线,通常n=180,此时检测的直线的角度精度为1°,分别计算这n条直线的 ( r , θ ) (r,\theta) r,θ坐标,得到n个坐标点。如果要判断的点共有N个,最终得到的 ( r , θ ) (r,\theta) r,θ坐标有N * n个。有关这N * n个(r,theta)坐标,其中 θ \theta θ是离散的角度,共有180个取值。
最重要的地方来了,如果多个点在一条直线上,那么必有这多个点在theta=某个值theta_i时,这多个点的r近似相等于 r i r_i ri。也就是说这多个点都在直线 ( r i , θ i ) (r_i,\theta_i) ri,θi上。
下面拿个例子说明:
如果空间中有3个点,如何判断这三个点在不在一个直线上,如果在,这条直线的位置为:

这个例子中,对于每个点均求过该点的6条直线的(r, θ \theta θ)坐标,共求了3 * 6个(r, θ \theta θ)坐标。可以发现在 θ \theta θ=60时,三个点的r都近似为80.7,由此可判定这三个点都在直线(80.7,60)上。
通过 r 0 θ r0\theta r0θ 坐标系可以更直观表示这种关系,如下图:图中三个点的 ( r , θ ) (r,\theta) r,θ曲线汇集在一起,该交点就是同时经过这三个点的直线。
通过 r * θ \theta θ 坐标系可以更直观表示这种关系,如下图:图中三个点的(r, θ \theta θ)曲线汇集在一起,该交点就是同时经过这三个点的直线:

img

2.Hough圆检测

继使用hough变换检测出直线之后,顺着坐标变换的思路,提出了一种检测圆的方法。

2.1如何表示一个圆?

与使用(r, θ \theta θ)来表示一条直线相似,使用(a,b,r)来确定一个圆心为(a,b)半径为r的圆。
某个圆过点 ( x 1 , y 1 ) (x_1,y_1) x1,y1,则有:$(x_1-a_1)^2 + (y_1-b_1)^2 = r_1^2 。 那 么 过 点 。 那么过点 (x_1,y_1) 的 所 有 圆 可 以 表 示 为 的所有圆可以表示为 (a_1(i),b_1(i),r_1(i)) , 其 中 ,其中 r_1 ∈ ( 0 , 无 穷 ) , 每 一 个 i 值 都 对 应 一 个 不 同 的 圆 , ∈(0,无穷),每一个 i 值都对应一个不同的圆, 0i(a_1(i),b_1(i),r_1(i)) 表 示 了 无 穷 多 个 过 点 表示了无穷多个过点 (x_1,y_1)$的圆。

2.2 如何确定多个点在同一个圆上?

如上说明,过点(x1,y1)的所有圆可以表示为 ( a 1 ( i ) , b 1 ( i ) , r 1 ( i ) ) (a_1(i),b_1(i),r_1(i)) a1(i),b1(i),r1(i),过点 ( x 2 , y 2 ) (x_2,y_2) x2,y2的所有圆可以表示为 ( a 2 ( i ) , b 2 ( i ) , r 2 ( i ) ) (a_2(i),b_2(i),r_2(i)) a2(i),b2(i),r2(i),过点 ( x 3 , y 3 ) (x_3,y_3) x3,y3的所有圆可以表示为 ( a 3 ( i ) , b 3 ( i ) , r 3 ( i ) ) (a_3(i),b_3(i),r_3(i)) a3(i),b3(i),r3(i),如果这三个点在同一个圆上,那么存在一个值 ( a 0 , b 0 , r 0 ) (a_0,b_0,r_0) a0,b0,r0,使得$ a_0 = a_1(k)=a_2(k)=a_3(k) 且b_0 = b_1(k) = b_2(k) = b_3(k) 且r_0=r_1(k)=r_2(k)=r_3(k) , 即 这 三 个 点 同 时 在 圆 ,即这三个点同时在圆 (a_0,b_0,r_0)上。$
从下图可以形象的看出:

img

首先,分析过点 ( x 1 , y 1 ) (x_1,y_1) x1,y1的所有圆 ( a 1 ( i ) , b 1 ( i ) , r 1 ( i ) ) (a_1(i),b_1(i),r_1(i)) a1(i),b1(i),r1(i),当确定 r 1 ( 4 i ) r_1(4i) r1(4i)时 , ( a 1 ( i ) , b 1 ( i ) ) (a_1(i),b_1(i)) a1(i),b1(i)的轨迹是一个以 ( x 1 , y 1 , r 1 ( i ) ) (x_1,y_1,r_1(i)) x1,y1,r1(i)为中心半径为 r 1 ( i ) r_1(i) r1(i)的圆。那么,所有圆 ( a 1 ( i ) , b 1 ( i ) , r 1 ( i ) ) (a_1(i),b_1(i),r_1(i)) a1(i),b1(i),r1(i)的组成了一个以(x1,y1,0)为顶点,锥角为90度的圆锥面。
三个圆锥面的交点A 既是同时过这三个点的圆。

opencv-python实现虹膜瞳孔边缘检测

cv2.HoughCircles函数说明:
用函数 cv2.HoughCircles(image, method, dp, minDist, circles, param1, param2, minRadius, maxRadius) , 其参数解释如下:
(1)image: 输入图像,需要灰度图
(2)method: 检测方法,常用CV_HOUGH_GRADIENT
(3)dp: 为检测内侧圆心的累加器图像的分辨率于输入图像之比的倒数,如dp=1,累加器和输入图像具有相同的分辨率,如果dp=2,累计器便有输入图像一半那么大的宽度和高度
(4)minDist: 表示两个圆之间圆心的最小距离
(5)circles: 找到的圆的输出向量,一般不设置
(6)param1: 默认值100,它是method设置的检测方法的对应的参数,对当前唯一的方法霍夫梯度法cv2.HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半
(7)param2:默认值100,它是method设置的检测方法的对应的参数,对当前唯一的方法霍夫梯度法cv2.HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值,它越小,就越可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆
(8)minRadius:默认值0,圆半径的最小值
(9)maxRadius:默认值0,圆半径的最大值

代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("E:\matlab_file\hongmoshibie\pic2.png")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #灰度图像

plt.subplot(121),plt.imshow(gray,'gray')
plt.xticks([]),plt.yticks([])
#使用HoughCircles对灰度图像进行霍夫变换
circles1 = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,
100,param1=100,param2=30,minRadius=50,maxRadius=100)
circles = circles1[0,:,:] #提取为二维
circles = np.uint16(np.around(circles)) #四舍五入,取整
for i in circles[:]:
    cv2.circle(img,(i[0],i[1]),i[2],(255,0,0),5) #画圆
    cv2.circle(img,(i[0],i[1]),2,(255,0,255),10) #画圆心

plt.subplot(122),plt.imshow(img)
plt.xticks([]),plt.yticks([]);

在这里插入图片描述
瞳孔外圆检测:
调整minRadius、maxRadius参数(将其分别设置为:minRadius=200,maxRadius=290,代码基本不变),即可检测出瞳孔的外圆。
在这里插入图片描述
Tips:
1.在霍夫圆检测之前进行高斯滤波,减少噪声
2.以前利用霍夫圆检测经常出现检测不到圆,或错误检测的情况,实则是因为参数没有设置到位。应该小心调节的参数有:
minDist:根据实际情况调节,越小检测的圆越多,错误率越大
param2:这个参数以前没有注意过,针对于虹膜检测,目标圆是较小的,所以这个值理应设置的小一点。
minRadius,maxRadius:圆半径范围

GitHub 加速计划 / opencv31 / opencv
142
15
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:3 个月前 )
d9a139f9 Animated WebP Support #25608 related issues #24855 #22569 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 1 天前
09030615 V4l default image size #25500 Added ability to set default image width and height for V4L capture. This is required for cameras that does not support 640x480 resolution because otherwise V4L capture cannot be opened and failed with "Pixel format of incoming image is unsupported by OpenCV" and then with "can't open camera by index" message. Because of the videoio architecture it is not possible to insert actions between CvCaptureCAM_V4L::CvCaptureCAM_V4L and CvCaptureCAM_V4L::open so the only way I found is to use environment variables to preselect the resolution. Related bug report is [#25499](https://github.com/opencv/opencv/issues/25499) Maybe (but not confirmed) this is also related to [#24551](https://github.com/opencv/opencv/issues/24551) This fix was made and verified in my local environment: capture board AVMATRIX VC42, Ubuntu 20, NVidia Jetson Orin. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [X] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 1 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐