Canny算子与霍夫变换检测圆与直线

简介: Canny算子与霍夫变换检测圆与直线

引言

canny算子是计算机视觉最常用的一种算子,是目前一种非常流行的算法,是John Canny在1986年提出的。它是一个多阶段的算法,即由多个步骤构成。虽然Canny算法年代久远,但可以说它是边缘检测的一种标准算法,而且仍在研究中广泛使用。霍夫变换是一种在图像中寻找直线、圆形以及其他简单形状的方法。霍夫变换采用类似于投票的方式来获取当前图像内的形状集合,该变换由Paul Hough(霍夫)于1962年首次提出。本文将介绍canny算子与霍夫变换检测圆与直线,附完整可运行代码,希望可以带来帮助。

一、canny算子

canny算子可以分为以下几步:

  1. 应用高斯滤波来平滑图像,目的是去除噪声
  2. 找寻图像的强度梯度(intensity gradients)
  3. 应用非最大抑制(non-maximum suppression)技术来消除边误检(本来不是但检测出来是)
  4. 应用双阈值的方法来决定可能的(潜在的)边界
  5. 利用滞后技术来跟踪边界

先看下lena经canny算子的效果图:

高斯滤波其实就是将所指像素用周围的像素的某种均值代替(即卷积核),卷积核尺寸越大,去噪能力越强,因此噪声越少,但图片越模糊,canny检测算法抗噪声能力越强,但模糊的副作用也会导致定位精度不高。高斯的卷积核大小推荐:一般情况下,尺寸5 * 5,3 * 3也行。

二、canny算子代码

1. import cv2
2. img =  cv2.imread("lena.png")
3. img_5 = cv2.Canny(img, 100, 200)
4. cv2.namedWindow("W5")
5. cv2.imshow("W5", img_5)
6. cv2.imwrite("canny_img.jpg",img_5)
7. cv2.waitKey()
8. cv2.destroyAllWindows()

三、霍夫变换检测直线

霍夫直线检测利用图像与霍夫空间中点与线的对偶性,将图像空间中待检测的离散像素点集通过参数方程映射为霍夫空间中极坐标上的曲线集,并将曲线的交点作为通过n个离散点的直线方程参数映射到图像空间中的直线。即点(图像空间)-线(霍夫空间)-交点(霍夫空间)-线(图像空间)。将找直线问题转换为找交点问题,同时考虑到笛卡尔坐标系存在垂直线无法检测的问题,因而利用极坐标去表示,转换为曲线交点检测。

HoughLine函数:

HoughLine(inputimage,outputline,double rho,double theta,int tereshold,double srn=0,double stn=0)

霍夫变换基于opencv的实现

@para1:输入图像,需要为8位单通道二进制图像

@para2:储存输出的矢量线条,用θ,ρ表示。ρ为直线离坐标原点(图像左上角)的距离。θ表示弧度线条旋转角度(0为垂线,π/2为水平线)

@para3:以像素为单位的距离精度(即搜索直线时ρ轴的步进分辨率,一般为1)

@para4:以弧度为单位的角度精度(即搜索直线时θ轴的步进分辨率,一般为CV_PI/180,即1度)

@para5:累加空间的阈值参数,即识别直线时在累加空间必须达到的阈值,大于threshold的线段才能被认为检测到。

@para6:默认值0。对于多尺度霍夫变换srn表示@para3步进分辨率的除数距离。

@para7:默认值0。对于多尺度霍夫变换stn表示@para4步进分辨率的除数距离。如果srn和stn都为0时表示经典霍夫变换,否则应为正数。

四、霍夫变换检测直线代码

1. import cv2
2. import numpy as np
3. def lines_judge(img):
4.     o = img.copy()
5.     # 使用中值滤波进行降噪
6.     o = cv2.medianBlur(o, 5)
7.     # 从彩色图像变成单通道灰度图像
8.     gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
9.     # 绘制边缘图像
10.     binary = cv2.Canny(o, 50, 150)
11. 
12.     # 检测直线 不限步长,不限角度,至少50个点确定一条线
13.     lines = cv2.HoughLines(binary, 1, np.pi / 180, 285)
14.     # print(lines)
15.     # print(lines.shape)
16.     try:
17.         list = [ line for line in lines]
18.     except TypeError or IndentationError:
19. print("未检测到直线!")
20.     else:
21.         for line in lines:
22.             rho, theta = line[0]
23.             a = np.cos(theta)
24.             b = np.sin(theta)
25.             x0 = a * rho
26.             y0 = b * rho
27.             x1 = int(x0 + 1000 * (-b))
28.             y1 = int(y0 + 1000 * (a))
29.             x2 = int(x0 - 1000 * (-b))
30.             y2 = int(y0 - 1000 * (a))
31.             cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
32.     cv2.imshow("img", img)
33. 
34. cap = cv2.VideoCapture(0) # 调用本地摄像头
35. while True:
36.     flag,frame = cap.read()
37.     if not flag:
38.         break
39. lines_judge(frame)
40.     if ord("q") == cv2.waitKey(1):
41.         break
42. cv2.waitKey()
43. cv2.destroyAllWindows()

五、霍夫变换检测直线效果

车道识别视频

看看代码运行的效果:我在电脑里插入一段视频,和前面的原理类似,捕获每一帧,如果在这一帧里检测到直线就标出来,没检测的话在对话框里给出反馈:没检测到直线。这样在调整参数时,更加直观。

六、霍夫变换检测圆

Hough Transform(霍夫变换)是早期的一种以投票方案进行图形拟合的算法。所谓拟合就是要将图像中的一些边缘用数学方式来描述,可以使人们更好的操作使用图像提供的信息。相比较最小二乘法、鲁棒估计以及RANSAC方法,霍夫变换的优点在于可以进行多目标的拟合。本次在此讨论研究霍夫圆的拟合原理。

霍夫圆算法的实现一共可分为两个步骤:

  • 建立霍夫参数三维空间,并对空间内各个单元进行投票
  • 设置阈值从投票结果中筛选合适的圆,并做非极大化抑制

详细了解可以看这篇文章:霍夫变换检测圆

七、霍夫变换检测圆代码

1. import cv2
2. import numpy as np
3. 
4. def decodeDisplay(video, flag):
5.     gay_img = cv2.cvtColor(video, cv2.COLOR_BGRA2GRAY)
6.     img = cv2.medianBlur(gay_img, 7)  # 进行中值模糊,去噪点
7.     cimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
8.     circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 50, param1=100, param2=30, minRadius=100, maxRadius=150)
9.     if circles is not None:
10.         circles = np.uint16(np.around(circles))
11. print(circles)
12.         for i in circles[0, :]:  # 遍历矩阵每一行的数据
13.             cv2.circle(video, (i[0], i[1]), i[2], (0, 255, 0), 2)
14.             cv2.circle(video, (i[0], i[1]), 2, (0, 0, 255), 3)
15.         cv2.imshow("gay_img", video)
16.     else:
17.         pass
18.         # 如果识别不出,显示圆心不存在
19.         # print('x: None y: None')
20.         # cv2.imshow('frame', video)
21. 
22. def detect():
23.     cap = cv2.VideoCapture(0)
24.     while True:
25.         # 逐帧捕获
26.         ret, frame = cap.read()
27.         # cv2.imshow("img", frame)
28.         flag = cv2.waitKey(1)
29.         if ord("q") == flag:
30.             break
31.         else:
32.             flag = decodeDisplay(frame, flag)
33. # 一切完成后,释放捕获
34.     cap.release()
35.     cv2.destroyAllWindows()
36. 
37. 
38. if __name__ == '__main__':
39. detect()

八、霍夫变换检测圆效果

霍夫变换检测圆

同样我们直接看视频:在我的手里是一个圆形的物体,我调用本地摄像头,对图片检测。可以看到,检测效果很好,绿色的标记一直跟着我的手在运动;并且左下角不断输出着圆心的坐标。

好啦,今天的分享就到这里啦!有什么问题或者发现错误的地方都可以在评论区或者私信联系我哦!

文章最后附canny算子可视调参数的工具链接:https://pan.baidu.com/s/1jIWS1zif8ddi-1LPIjrEaw?pwd=xpj0 

提取码:xpj0


相关文章
|
算法 计算机视觉 Python
OpenCV中Canny边缘检测和霍夫变换的讲解与实战应用(附Python源码)
OpenCV中Canny边缘检测和霍夫变换的讲解与实战应用(附Python源码)
1224 0
|
并行计算
最新YOLOv8(2023年8月版本)安装配置!一条龙傻瓜式安装,遇到问题评论区提问
最近需要使用YOLOv8,百度了一下现在网上大多数教程都是比较早期的教程,很多文件已经大不相同,于是我根据官方readme文档,总结了一套安装方法,只需要按照本教程,复制每一段代码,按照教程配置好相应文件即可直接使用。
10041 2
|
计算机视觉
OpenCV-计算轮廓周长cv::arcLength
OpenCV-计算轮廓周长cv::arcLength
430 0
|
开发者
静态方法和实例方法的区别是什么?
静态方法和实例方法在面向对象编程中各自扮演着重要的角色,开发者需要根据具体的业务需求和设计原则来合理地使用它们,以实现高效、可读和易于维护的代码结构。
578 68
|
存储 人工智能 API
DeepSeek——DeepSeek模型部署实战
本文介绍了DeepSeek大模型的本地部署方法、使用方式及API接入。首先,通过下载Ollama平台部署DeepSeek-R1模型,提供7种不同参数版本(1.5b至671b),用户可根据硬件选择合适的模型大小。接着,文章详细描述了如何在终端运行命令启动模型,并通过Chatbox官网下载并接入DeepSeek API,实现本地和云端模型的交互。最后,提及了DeepSeek官网和集成工具如POE的使用,帮助用户更好地利用DeepSeek进行开发和应用。
|
机器学习/深度学习 XML Oracle
关系型数据库Oracle发展历程
【7月更文挑战第5天】
644 5
|
Python
Python软件包及环境管理器conda实战篇
详细介绍了如何使用conda进行Python软件包管理及环境管理,包括查看、安装、卸载软件包,切换源,管理不同版本的Python环境,以及解决使用过程中可能遇到的错误。
668 2
Python软件包及环境管理器conda实战篇
|
算法 计算机视觉
图像处理之调整亮度与对比度
图像处理之调整亮度与对比度
486 6
|
算法 C++
【动态规划】零基础解决路径问题(C++)
【动态规划】零基础解决路径问题(C++)
|
开发者 Python
【Python】已解决:SyntaxError: positional argument follows keyword argument
【Python】已解决:SyntaxError: positional argument follows keyword argument
974 0

热门文章

最新文章