python-opencv 边缘检测、直线检测、圆检测

文章目录

Canny算法

除了将目标与背景分离开来,边缘检测也同样是一种图像分割方法,从分割结果来看,adaptiveThreshold函数显然就采取了类似边缘检测的划分方案。

Canny在1986年提出了一种边缘检测算法,因其卓越的性能和准确性而广泛应用于各种图像分析领域。opencv中提供了这种算法,其操作步骤如下

  1. 高斯滤波:采用 5 × 5 5×5 5×5的高斯滤波,对图像进行平滑,以降低灰度波动,使边缘更加明显。
  2. 梯度计算:用Sobel核函数对图像滤波,得到两个方向的一阶导数 G x ​ , G y ​ Gx​,Gy​ Gx,Gy,从而得到图像的梯度 G x 2 ​ + G y 2 ​​ Gx2​+Gy2​ ​ Gx2​+Gy2​​以及辐角 t a n − 1 G x ​ G y ​​ tan−1Gx​Gy​​ tan1GxGy​​
  3. 非极大值抑制:即抑制那些不是局部最大值的梯度值,即一个像素点,只有其梯度幅度大于周围像素点时,才被认为是边缘点。
  4. 双阈值处理:通过高阈值 t 2 ​ t2​ t2​和低阈值 t 1 ​ t1​ t1​来进一步判断边缘,某点若梯度幅度大于 t 2 ​ t2​ t2​,则被认为是边缘点;若处于 t 2 ​ t2​ t2​ t 1 ​ t1​ t1​之间,则被认为是潜在的边缘点。
  5. 边缘跟踪和连接:最后,算法跟踪由边缘像素点组成的线,并连接它们以形成完整的边缘。

t 1 ​ = 100 , t 2 ​ = 200 t1​=100,t2​=200 t1​=100,t2​=200,则Canny算法的边缘检测结果如下

在这里插入图片描述

实现代码如下。

imgs = {}
imgs['Original'] = ascent().astype(np.uint8)
imgs['edges'] = cv2.Canny(img,100,200)

for i,key in enumerate(imgs, 1):
plt.subplot(1,2,i)
plt.imshow(imgs[key],cmap = ‘gray’)
plt.title(key)
plt.axis(‘off’)

plt.show()

【Canny】即为Canny边缘检测函数,其输入参数分别是待检测图像和阈值 t 1 ​ , t 2 ​ t1​,t2​ t1​,t2​

霍夫变换-直线检测

在获取图像边缘后,可能会对边缘的形状产生兴趣。1962年,Hough提出一种直线和圆的识别方案,思路是将图像中的点映射到一个参数空间,这个空间中涵盖了某个几何形状的所有参数,这个变换便被称作霍夫变换(Hough Transform, HT)。

Python中提供了基于HT的直线检测函数,可实现如下效果。

在这里插入图片描述

代码为

img = ascent().astype(np.uint8)
m, n = img.shape

edges = cv2.Canny(img, 50, 150, apertureSize = 3)
lines = cv2.HoughLines(edges,1.1,np.pi/180,200)

【HoughLines】就是HT直线检测函数,其输入的四个参数分别是待检测图像、以像素为单位的距离精度 p r ​ pr​ pr、以弧度为单位的角度精度 p θ ​ pθ​ 以及累加平面的阈值参数。 p r ​ , p θ ​ pr​,pθ​ pr,这两个值设得越大,则会检查出越多的直线。

其检测检测结果由 ( ρ , θ ) (ρ,θ) (ρ,θ)来表示,其中 ρ ρ ρ表示直线与坐标原点 ( 0 , 0 ) (0,0) (0,0)的距离, θ θ θ是直线的垂线与 x x x轴的夹角。从而直线方程可表示为点法式

x c o s θ + y s i n θ − ρ = 0 xcosθ+ysinθ−ρ=0 xcosθ+ysinθρ=0

对于尺寸为 m m m x = 0 , x = n , y = 0 , y = m x=0,x=n,y=0,y=m x=0,x=n,y=0,y=m,记 c = c o s θ , s = s i n θ c=cosθ,s=sinθ c=cosθ,s=sinθ,则直线与四个边框的交点分别为

(0,ρs)(ρc,0)(n,ρncs)(ρmsc,m)

(0,sρ)(cρ,0)(n,sρnc)(cρms,m)

从而绘图代码如下

fig, ax = plt.subplots(1,2)

ax[0].imshow(img, cmap=‘gray’)
for line in lines:
rho,theta = line[0]
c = np.cos(theta)
s = np.sin(theta)
xs = [0, n, rho/c, (rho-ms)/c]
ys = [rho/s, (rho-nc)/s, 0, m]
i1, i2 = np.argsort(xs)[1:3]
ax[0].plot([xs[i1], xs[i2]], [ys[i1], ys[i2]], ls=‘–’)
ax[1].plot([xs[i1], xs[i2]], [ys[i1], ys[i2]], ls=‘–’)

plt.grid()
plt.show()

霍夫变换-圆形检测

opencv中提供了基于霍夫变换的圆形检测方法,可实现下图所示的检测结果。

在这里插入图片描述

其实现代码如下。

path = 'coins.png'

coins = { }
img = cv2.imread(path, cv2.IMREAD_COLOR)
gray = cv2.cv2tColor(img, cv2.COLOR_BGR2GRAY)

coins[‘gray’] = cv2.medianBlur(gray, 25)
coins[‘edge’] = cv2.Canny(coins[‘gray’],100,200)

rows = gray.shape[0]
circles = cv2.HoughCircles(coins[‘gray’], cv2.HOUGH_GRADIENT,
1, 150, param1=100, param2=30,
minRadius=1, maxRadius=300)

【HoughCircles】是opencv提供的基于霍夫变换的圆形检测工具。

函数参数说明:

  • image: 待检测灰度图像。
  • method: 检测圆的方法。
  • dp: 霍夫变换的分辨率,值越大,检测的圆越少,但越准确。
  • minDist: 圆心之间的最小距离。
  • param1: 边缘检测时使用Canny算子的高阈值,低阈值是高阈值的一半。
  • param2: 用于圆心检测的参数。
  • minRadius, maxRadius: 圆半径的最小值和最大值。

其中,opencv通提供了四种检测圆的方法,其method参数可选值如下

  • 【cv2.HOUGH_GRADIENT】霍夫梯度法,通过计算图像中的梯度来确定圆心的可能位置,然后对这些位置进行投票,以确定真实的圆心。这种方法的问题是对噪声敏感。
  • 【cv2.HOUGH_GRADIENT_ALT】霍夫梯度法的另一种实现。
  • 【cv2.HOUGH_PROBABILISTIC】概率霍夫变换,与霍夫梯度法的区别是,并不通过全局投票来确定圆心,而检查一些候选点是否符合圆的方程,它通常会产生较少的假阳性结果,但可能检测不到某些圆。
  • 【cv2.HOUGH_MULTI_SCALE】多尺度霍夫变换,将在不同尺度上应用霍夫变换,对缩放、旋转和倾斜变化具有更好的鲁棒性。和其他方法相比,该方法可能会检测到更多的圆,但也更吃计算资源。

绘图代码如下。

coins['circles'] = img
for i,key in enumerate(coins,1):
    ax = plt.subplot(1,3,i)
    plt.title(key)
    plt.imshow(coins[key])
    plt.axis('off')

th = np.deg2rad(np.arange(361))
for x,y,r in circles[0]:
xs = x + rnp.cos(th)
ys = y + rnp.sin(th)
plt.scatter(x, y, marker=‘*’, color=‘red’)
plt.plot(xs, ys, color=‘red’)

plt.show()

使用PythonOpenCV库可以很容易地实现图像中水平直线的检测。下面是一个简单的示例代码: ```python import cv2 import numpy as np # 读取图像 img = cv2.imread('image.png') # 将图像转化为灰度图像 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 将图像进行二值化处理 _, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY) # 进行Canny边缘检测 edges = cv2.Canny(thresh, 50, 150, apertureSize=3) # 检测图像中的直线 lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=100, maxLineGap=10) # 绘制检测出的直线 for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) # 显示结果图像 cv2.imshow('Result', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 代码中的步骤如下: 1. 首先读取待处理的图像。 2. 使用`cv2.cvtColor()`函数将图像转化为灰度图像。 3. 对灰度图像进行二值化处理,将图像中的目标物体与背景分离出来。 4. 使用Canny边缘检测算法检测图像中的边缘。 5. 使用`cv2.HoughLinesP()`函数检测图像中的直线,其中`minLineLength`和`maxLineGap`分别表示检测出的直线的最小长度和最大间隔。 6. 绘制检测出的直线。 7. 显示结果图像。 在上面的代码中,我们使用了`cv2.HoughLinesP()`函数来检测图像中的直线,其中参数`1`表示距离分辨率,`np.pi/180`表示角度分辨率,`100`表示阈值,`minLineLength`表示检测出的直线的最小长度,`maxLineGap`表示检测出的直线的最大间隔。这些参数的具体含义可以根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值