霍夫变换:原理剖析与 OpenCV 应用实例

news/2024/11/29 9:31:44/

在这里插入图片描述

简介:本文围绕霍夫变换相关内容展开,先是讲解霍夫变换基本原理,包含从 xy 坐标系到 kb 坐标系及极坐标系的映射等。接着介绍了 cv2.HoughLines、cv2.HoughLinesP 概率霍夫变换、cv2.HoughCircles 霍夫圆变换的函数用法、参数含义、与常规霍夫变换区别以及实现步骤,并附代码示例,助力读者理解和运用这些图像检测技术。
如果我的文章对你有帮助,请点赞收藏关注,我将会持续为您带来更多与OpenCV有关的知识。

霍夫变换:原理剖析与 OpenCV 应用实例

  • 霍夫变换基本原理
  • cv2.HoughLines函数
    • 实现一次霍夫变换
    • cv2.HoughLinesP概率霍夫变换
    • 霍夫圆变换cv2.HoughCircles
  • 致谢

霍夫变换基本原理

画一张图 y = kx+b:,用xy坐标系如图所示:
在这里插入图片描述
如果用k,b坐标系该这样表示:
在这里插入图片描述
(xy空间的一条线确定了kb空间的一个点)
我现在在xy轴里取一个点 (x0,y0):
在这里插入图片描述
此时x0,y0确定,他可能在任意一条直线上,根据公式 y0 = kx0+b,那么b = y0-kx0,所以在kb空间上:
在这里插入图片描述
说明xy的一个点对应 kb的一条线
再来观察,两个xy坐标的点 x0,y0 x1,y1,同时两点确定了一条直线,看图:
在这里插入图片描述
对应在kb空间应该是如下图:
在这里插入图片描述
我们会进行三步推理:
第一步:xy坐标系的一条直线上的两个点,对应着kb空间经过同一个点的两条直线。
第二步:推理可以知道,kb坐标系中间经过一个点的直线越多,说明在xy坐标系中是由更多的点所构成。
第三步:已知两个点确定一条直线,对于图像中的线怎么确定不是谬误,噪声呢?那多个点确定的直线不出错的概率相对来说肯定是更大的
第四步:霍夫变换选择直线的基本思路是,选择又尽可能多的直线交汇的点
但是,有一种特殊情况不能完成从xy坐标系映射到kb坐标系:垂线
在这里插入图片描述
所以可以映射到极坐标系:r = xcosa+ ysina
在这里插入图片描述

cv2.HoughLines函数

lines 返回的ndarray数组,数组的每一对数据都是(r,a) = cv2.HoughLines(image输入图像必须是八位单通道二值图像 ,rho为r的精度一般为1,theta为角度的精度一般情况使用pi/180,threshold是阈值,他是霍夫空间的直线条数大于阈值才能被认为是xy空间的直线,所以阈值越小找到的直线越多)
我们选择验证的例子基于这张图片,我给他命名为calculator.JPG放在跟代码同一个文件夹下,大家可以复制我的图片重命名自己去运行代码:
在这里插入图片描述

实现一次霍夫变换

(第一步)读取图片
(第二步)转化为灰度图
(第三步)使用cv2.Canny边缘检测获得边缘
(第四步)使用霍夫变换
(第五步)为了看到霍夫变化的差异,将原图从bgr转化成 rgb,并复制一张原图片
(第六步)对霍夫变换的结果从极坐标转换成xy坐标并在原图画线
(第七步)展示原图与画线后的图片差别

import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("calculator.JPG")
# 转化为灰度图
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#使用cv2.Canny边缘检测获得边缘
edges = cv2.Canny(gray,50,150,apertureSize = 3)
#使用霍夫变换
lines = cv2.HoughLines(edges,1,np.pi/180,133)
#为了看到霍夫变化的差异,将原图从bgr转化成 rgb,并复制一张原图片
orgb = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
oShow = orgb.copy()# 对霍夫变换的结果从极坐标转换成xy坐标并在原图画线
for line in lines:rho,theta =line[0]a = np.cos(theta)b = np.sin(theta)x0 = a*rhoy0 = b*rhox1 = int(x0+1000*(-b))y1 = int(y0+1000*(a))x2 = int(x0-1000*(-b))y2 = int(y0-1000*(a))cv2.line(orgb,(x1,y1),(x2,y2),(0,0,255),2)plt.subplot(121)
plt.imshow(oShow)
plt.axis("off")
plt.title("original")plt.subplot(122)
plt.imshow(orgb)
plt.axis("off")
plt.title('huofu')plt.show()

在这里插入图片描述

cv2.HoughLinesP概率霍夫变换

与霍夫变换的区别:

  1. 霍夫变换考虑了所有的点,而概率只考虑了一个足以进行线检测的随机点的子集
  2. 概率设置了所接受直线的最小长度
  3. 接受直线时所允许的最大像素点间距
    语法上多了两个参数 一个是最小长度minLineLength和maxLineGap

步骤上并没有太多区别,仅仅是在调用函数时后多两个参数,阈值调低(后两个参数保证了即使低阈值也不会产生很多无效的直线)。

import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("calculator.JPG")
# 转化为灰度图
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#使用cv2.Canny边缘检测获得边缘
edges = cv2.Canny(gray,50,150,apertureSize = 3)
#使用概率霍夫变换 设置minLineLength和maxLineGap
lines = cv2.HoughLinesP(edges,1,np.pi/180,1,minLineLength = 120,maxLineGap = 10)
#为了看到霍夫变化的差异,将原图从bgr转化成 rgb,并复制一张原图片
orgb = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
oShow = orgb.copy()# 对霍夫变换的结果从极坐标转换成xy坐标并在原图画线
for line in lines:x1,y1,x2,y2 = line[0]cv2.line(orgb,(x1,y1),(x2,y2),(0,0,255),2)plt.subplot(121)
plt.imshow(oShow)
plt.axis("off")
plt.title("original")plt.subplot(122)
plt.imshow(orgb)
plt.axis("off")
plt.title('huofu')plt.show()

在这里插入图片描述

霍夫圆变换cv2.HoughCircles

需要考虑圆半径和圆心x,y。两轮筛选,第一轮找出可能存在的圆心,第二轮判断半径。
circles 由圆心坐标和半径组成的ndarray= cv2.HoughCircles(image八位单通道灰度图,method检测方法 cv2.HOUGH_GRADIENT,dp累计其分辨率,若dp=1输入图像和结果具有相同的分辨率,minDist圆心之间的最小间距,太小会有多个邻近的圆,太大会漏掉一些圆,param1默认为100他是canny边缘检测的阈值,param2默认是100他越大检测到的圆越少,minRadius和maxRadius圆半径的最大值最小值 )
注意:在调用函数之前要进行平滑处理,减少噪声避免误判
使用这张图我命名为bicycly.JPG,存在和代码同一个文件夹下,大家可以复制我的图片然后重命名:在这里插入图片描述

import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("bicycle.JPG",0)
o = cv2.cvtColor(img,cv2.COLOR_BAYER_BG2RGB)
oshow = o.copy()
# 使用中值滤波
img = cv2.medianBlur(img,5)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,200,param1 = 5,param2 = 5,minRadius =3, maxRadius = 200)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:cv2.circle(o,(i[0],i[1]),i[2],(255,0,0),12)cv2.circle(o,(i[0],i[1]),2,(255,0,0),12)plt.subplot(121)
plt.imshow(oshow)
plt.axis("off")
plt.title("original")plt.subplot(122)
plt.imshow(o)
plt.axis("off")
plt.title("circle")plt.show()

在这里插入图片描述

致谢

本文参考了一些博主的文章,博取了他们的长处,也结合了我的一些经验,对他们表达诚挚的感谢,使我对 OpenCV霍夫变换 有更深入的了解,也推荐大家去阅读一下他们的文章。纸上学来终觉浅,明知此事要躬行:
【OpenCV学习笔记】之霍夫变换(Hough Transform)


http://www.ppmy.cn/news/1550867.html

相关文章

11.25c++继承、多态

练习: 编写一个 武器类 class Weapon{int atk; }编写3个武器派生类:短剑,斧头,长剑 class knife{int spd; }class axe{int hp; }class sword{int def; }编写一个英雄类 class Hero{int atk;int def;int spd;int hp; public:所有的…

QT6学习第四天 感受QT的文件编译

QT6学习第四天 感受QT的文件编译 使用纯代码编写程序新建工程 使用其他编辑器纯代码编写程序并在命令行运行使用 .ui 表单文件生成界面使用自定义 C 窗口类使用现成的QT Designer界面类 使用纯代码编写程序 我们知道QT Creator中可以用拖拽的方式在 .ui 文件上布局&#xff0c…

在 Ubuntu 上部署 MediaWiki 开源维基平台

MediaWiki 是一个功能强大的开源维基软件,全球众多组织使用它来创建协作文档网站。本文将指导你如何在 Ubuntu 服务器上安装 MediaWiki,使用 Nginx 作为 Web 服务器,PostgreSQL 作为数据库管理系统。 简介 MediaWiki 是一个灵活且强大的维基…

【vue-router】vue-router如何实现动态路由

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

常用Python集成开发环境(IDE)

好的工具可以帮助我们提高开发效率和质量,给大家介绍几个常用的 Python 集成开发环境(IDE)。 Visual Studio Code Visual Studio Code ,简称 VS Code,是一款由微软开发的开源代码编辑器,它支持多种编程语…

【工具变量】中国省级农村创业活跃度数据(2000-2022年)

一、测算方式:参考《金融与经济》黄敦平(2023)老师研究的做法,农村创业活跃度(REP)利用农村私营企业就业人数和个体就业人数之和与乡村人口总数的比重衡量农村创业活跃度,该比值越大&#xff0c…

前端页面或弹窗在线预览文件的N种方式

需求:后端返回给前端一个地址后,在前端页面上或则在弹框中显示在线的文档、表格、图片、pdf、video等等,嵌入到前端页面 方式一: 使用vue-office 地址:vue-office简介 | vue-office 个人感觉这个插件是最好用的&#x…

C语言蓝桥杯组题目

系列文章目录 文章目录 系列文章目录前言题目第一题.1, 2, 3, 4 能组成多少个互不相同且无重复数字的三位数?都是多少?第二题: 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少&…