Python图像处理【19】基于霍夫变换的目标检测
基于霍夫变换的目标检测
- 0. 前言
- 1. 使用圆形霍夫变换统计图像中圆形对象
- 2. 使用渐进概率霍夫变换检测直线
- 2.1 渐进霍夫变换原理
- 2.2 直线检测
- 3. 使用广义霍夫变换检测任意形状的对象
- 3.1 广义霍夫变换原理
- 3.2 检测自定义形状
- 小结
- 系列链接
0. 前言
霍夫变换 (Hough Transform
, HT
) 是一种特征提取技术,旨在使用在参数空间中执行的投票过程来查找特定形状的对象实例。经典的霍夫变换可用于检测图像中的直线:
- 我们可以使用极参数 ( ρ , θ ) (ρ,\theta) (ρ,θ) 表示直线,其中 ρ ρ ρ 是线段的长度, θ θ θ 是线和 x x x 轴之间的夹角
- 为了探索 ( ρ , θ ) (ρ,θ) (ρ,θ) 参数空间,首先在 ρ − θ ρ-θ ρ−θ 空间中创建二维直方图
- 然后,对于 ρ ρ ρ 和 θ θ θ 的每个值,计算输入图像中接近由参数构建的直线的非零像素的数量,并相应地将数组 ( ρ , θ ) (ρ,θ) (ρ,θ) 递增
- 因此,每个非零像素都可以被认为是对潜在候选线的投票
- 最可能的线对应于获得最高投票的参数值,即
2D
直方图中的局部最大值。
可以使用类似的投票过程来查找圆的参数空间中的最大值,从而将该方法扩展到检测椭圆或其他曲线,更进一步,可以将该方法推广到其他任何任意形状。曲线的参数越多,使用霍夫变换检测曲线的空间和计算成本就越高。在本节中,我们将学习如何使用不同类型的霍夫变换来检测图像中不同形状的对象。
1. 使用圆形霍夫变换统计图像中圆形对象
在本节中,我们将学习如何使用圆形霍夫变换来统计图像中的圆形对象,并使用 scikit-image.transform
模块实现圆形对象统计。
(1) 首先导入所有必需的库函数:
import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread
from skimage.color import rgb2gray
from skimage.transform import hough_circle, hough_circle_peaks
from skimage.feature import canny
from skimage.draw import circle_perimeter
from skimage.util import img_as_ubyte
from sklearn.neighbors import KDTree
(2) 加载输入图像并使用 Canny
边缘检测器检测边缘:
orig = imread('1.png')
h, w = orig.shape[:2]
image = rgb2gray(orig)
edges = canny(image, sigma=1, low_threshold=0.15, high_threshold=0.45)
(3) 将函数 hog_circle()
应用于边缘图像,以搜索半径值在 10
到 20
像素之间的圆,并进行投票。选择得票最多的圆,我们将 total_num_peaks
参数设置为一个较高值。为了避免多次检测到同一单元,我们需要通过使用参数 min_xdistance
和 min_ydistance
确保检测到的两个相邻峰值之间的最小间隔。
hough_radii = np.arange(10, 20, 1)
hough_res = hough_circle(edges, hough_radii)accums, cx, cy, radii = hough_circle_peaks(hough_res, hough_radii,min_xdistance = 10,min_ydistance = 10,#num_peaks = 5,total_num_peaks=400)
(4) 使用 circle_perimeter()
函数绘制图像上检测到的圆,在参数空间和圆形霍夫变换上执行迭代。为了保证最小的间距,使用 KDTree
数据结构查询半径内的所有圆形:
circles = []
image = orig.copy()
for center_y, center_x, radius in zip(cy, cx, radii):circy, circx = circle_perimeter(center_y, center_x, radius, shape=image.shape)if len(circles) > 1:tree = KDTree(np.array(circles), leaf_size=2) count = tree.query_radius(np.array([[center_y, center_x]]), r=10, count_only=True)if count[0] > 0: continuecircles.append([center_y, center_x])for j in range(-3,4):image[np.minimum(circy+j,h-1), np.minimum(circx+j,w-1)] = (255, 0, 0)print(len(cx))
(5) 最后,绘制原始输入图像,用 Canny
检测到的边缘,以及使用霍夫变换检测到的圆:
plt.figure(figsize=(20, 8))
plt.gray()
plt.subplots_adjust(0,0,1,0.975,0.05,0.05)
plt.subplot(131), plt.imshow(orig), plt.axis('off'), plt.title('original', size=10)
plt.subplot(132), plt.imshow(edges), plt.axis('off'), plt.title('edges with canny', size=10)
plt.subplot(133), plt.imshow(image), plt.axis('off'), plt.title('circle detected', size=10)
plt.suptitle('Counting circles with Circle Hough transform, number of circles={}'.format(len(circles)), size=12)
plt.show()
2. 使用渐进概率霍夫变换检测直线
2.1 渐进霍夫变换原理
霍夫变换是一种流行的提取集合形状的常用方法,变换主要方面是参数化、累加器设计、投票模式和峰值检测。概率霍夫变换 (Probabilistic Hough Transform
, PHT
) 的目的是最大程度地减少投票中使用的点的比例,同时几乎可以达到标准霍夫变换的水平。
渐进概率霍夫变换 (Progressive Probabilistic Hough Transform
, PPHT
) 是自适应概率霍夫变换 (Adaptive Probabilistic Hough Transform
, APHT
) 的一种形式,其目的是通过利用可靠检测具有不同数量支持点的线(特征)所需的投票分数的差异,最大限度地减少检测线(或其他几何特征)所需要的计算量。
PPHT
反映了算法固有的直线检测过程的渐进性,该过程首先找到最长(最显着)的线,然后再检测较短的线。用于投票的分数不需要特别指定或使用先验知识,因为在概率霍夫变换中,它是输入数据固有的复杂函数。该算法非常适合对实时性要求较高的应用,因为投票和直线检测可以并行计算,最显著的特征很可能首先被检测到。实验表明,在许多情况下,PPHT
比标准 HT
更具优势。PPHT
算法描述如下:
- 循环选择新的随机点进行投票
- 投票后,检验计数是否可能是由于随机噪声引起
- 检验过程需要与每个bin更新的阈值进行一次比较
- 当检测到一条线时,支持点会撤回选票
- 支持该线的其余点将从尚未投票的点集中删除,然后进行下一次随机选择
PPHT
算法具有以下优势:
- 只需根据累加器决定是否检测到特征
- 算法允许被中断,仍然可以输出检测到的显著特征
- 该算法不需要停止迭代的条件,当所有点被投票或被分配给某个特征时,计算停止
在霍夫变换中,只有一小部分点可以投票,而其余部分作为检测到的特征的支持证据。例如,如果以最小线长度的形式给出约束,则可以在选择投票点之前测试停止条件。在本节中,我们将学习如何使用 transform
模块的 PPHT
实现,在图像中检测直线。
2.2 直线检测
(1) 首先导入所需的库和函数,读取输入图像,然后将其转换为灰度图像:
import matplotlib.pyplot as plt
from skimage.io import imread
from skimage.color import rgb2gray
from skimage.feature import canny
from skimage.color import rgb2gray
from skimage.transform import probabilistic_hough_line
(2) 调用函数 probabilitic_hough_line()
,其中:
line_length
参数指定的检测线的最小可接受长度line_gap
参数指定的形成直线的像素之间的最大间隙
image = rgb2gray(imread('1.png')) # the image have pixel values in the range [0,1]
edges = canny(image, 2, 30/255, 80/255)
lines = probabilistic_hough_line(edges, threshold=20, line_length=20, line_gap=5)
最后,绘制输入图像、边缘图像和输出图像:
fig, axes = plt.subplots(1, 3, figsize=(30, 20), sharex=True, sharey=True)
ax = axes.ravel()
plt.gray()
ax[0].imshow(image, cmap=plt.cm.gray)
ax[0].set_title('Input image', size=10)
ax[1].imshow(edges, cmap=plt.cm.gray)
ax[1].set_title('Canny edges', size=10)
ax[2].imshow(edges * 0)
for line in lines:p0, p1 = lineax[2].plot((p0[0], p1[0]), (p0[1], p1[1]), linewidth=5)
ax[2].set_xlim((0, image.shape[1]))
ax[2].set_ylim((image.shape[0], 0))
ax[2].set_title('Probabilistic Hough', size=10)
for a in ax:a.set_axis_off()
plt.axis('off')
plt.tight_layout()
plt.show()
3. 使用广义霍夫变换检测任意形状的对象
3.1 广义霍夫变换原理
广义霍夫变换 (Generalized Hough Transform
, GHT
) 是指使用模板匹配的原理对霍夫变换的变体;这种修改使霍夫变换可用于检测其模型所描述的任意对象。GHT
的原始实现使用边缘信息来定义从边缘点的方向到形状的参考点映射。参考点是其形状的局部坐标系的原点,GHT
测量参考点能否被认为是形状的局部坐标系的原点。
广义霍夫变换解释了如何使用任意非解析形状的边界来构建图像空间和霍夫变换空间之间的映射,可以利用这样的映射来检测图像中特定形状的实例。此外,形状的变化(例如旋转,比例变化或图形逆转)对应于该映射的直接转换。但是,最显着的特征是,可以组合这些映射,从简单形状和组件形状的映射中构建复杂形状的映射。这使得广义霍夫成为一种通用变换,可以用来寻找任意复杂的形状。
在本节中,我们将学习如何使用 OpenCV
的 createGeneralizedHoughard()
函数来检测任意形状(作为模板图像提供)。
3.2 检测自定义形状
(1) 我们首先导入所需的库和函数:
from matplotlib.pylab import imshow, title, show
from skimage.filters import threshold_otsu
import cv2
import numpy as np
import matplotlib,pylab as plt
(2) 读取输入和模板图像,将它们转换为灰度图像,并使用 Canny
进行边缘检测:
orig = cv2.imread('match_shapes.png')
img = 255-cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
templ = 255-cv2.imread('shape2.png', 0)
edges = cv2.Canny(img, 130,150)
(3) 使用 cv2
中的 createGeneralizedHoughBallard()
函数检测源图像内部的模板形状,并检索图像内部形状的位置以及对形状的相应投票:
alg = cv2.createGeneralizedHoughBallard()
alg.setTemplate(templ)
[positions,votes] = alg.detect(edges)
(4) 在检测到的包含形状的区域周围绘制边界框,在图像内部找到的可能位置的坐标表示形状的中心坐标:
clone = orig.copy() #np.dstack([edges, edges, edges])
for i in range(len(positions[0])):pos, scale, angle = positions[0][i][:2], positions[0][i][2], positions[0][i][3]print(pos, scale, angle)# need to write code here to rotate the bounding rect if angle is not zero and scale is not 1cv2.rectangle(clone, (int(pos[0]) - templ.shape[1]//2, int(pos[1]) - templ.shape[0]//2), (int(pos[0] + templ.shape[1]//2), int(pos[1] + templ.shape[0]//2)), (0,0,255), 2)
(5) 最后,绘制输入和模板图像以及边界框,在图像中可以看出,虽然模板图像与源图像中对象略有不同,但该算法仍可以正确找到图像内部的形状:
plt.figure(figsize=(20, 8))
plt.gray()
plt.subplots_adjust(0,0,1,0.975,0.05,0.05)
plt.subplot(131), plt.imshow(img), plt.axis('off'), plt.title('input', size=10)
plt.subplot(132), plt.imshow(templ), plt.axis('off'), plt.title('template', size=10)
plt.subplot(133), plt.imshow(clone), plt.axis('off'), plt.title('object detection with generalized Hough', size=10)
plt.show()
小结
霍夫变换是一种特征提取 (feature extraction
) 技术,在图像分析、计算机视觉等领域应用广泛,利用霍夫变换可以辨别并提取图像中的目标特征。本节中,我们学习了霍夫变换的基本原理,进一步将广义霍夫变换将其扩展到检测任意形状对象,并学习了如何利用霍夫变换检测图像中的目标对象。
系列链接
Python图像处理【1】图像与视频处理基础
Python图像处理【2】探索Python图像处理库
Python图像处理【3】Python图像处理库应用
Python图像处理【4】图像线性变换
Python图像处理【5】图像扭曲/逆扭曲
Python图像处理【6】通过哈希查找重复和类似的图像
Python图像处理【7】采样、卷积与离散傅里叶变换
Python图像处理【8】使用低通滤波器模糊图像
Python图像处理【9】使用高通滤波器执行边缘检测
Python图像处理【10】基于离散余弦变换的图像压缩
Python图像处理【11】利用反卷积执行图像去模糊
Python图像处理【12】基于小波变换执行图像去噪
Python图像处理【13】使用PIL执行图像降噪
Python图像处理【14】基于非线性滤波器的图像去噪
Python图像处理【15】基于非锐化掩码锐化图像
Python图像处理【16】OpenCV直方图均衡化
Python图像处理【17】指纹增强和细节提取
Python图像处理【18】边缘检测详解
相关文章:

Python图像处理【19】基于霍夫变换的目标检测
基于霍夫变换的目标检测 0. 前言1. 使用圆形霍夫变换统计图像中圆形对象2. 使用渐进概率霍夫变换检测直线2.1 渐进霍夫变换原理2.2 直线检测 3. 使用广义霍夫变换检测任意形状的对象3.1 广义霍夫变换原理3.2 检测自定义形状 小结系列链接 0. 前言 霍夫变换 (Hough Transform,…...

Spring+SprinMVC+MyBatis注解方式简易模板
SpringSprinMVCMyBatis注解方式简易模板代码Demo GitHub访问 ssm-tpl-anno 一、数据准备 创建数据库test,执行下方SQL创建表ssm-tpl-cfg /*Navicat Premium Data TransferSource Server : 127.0.0.1Source Server Type : MySQLSource Server Version :…...

Python基础第五篇(Python数据容器)
文章目录 一、数据容器入门二、数据容器 list 列表(1),list 列表定义(2),list列表的索引(3),list列表的常见操作(4),list列表的遍历 三、数据容器:tuple(元组)(1),tuple元组定义(2),tuple元组的索引(3),tuple元组的常见操作(4),tuple元组的遍…...

【H3C】配置AAA认证和Telnet远程登陆,S5130 Series交换机
AAA配置步骤为: 1.开启telent远程登陆服务 2.创建用户,设置用户名、密码、用户的服务类型 3.配置终端登录的数量 4.配置vlan-if的ip地址,用来远程登陆 5.允许对应的vlan通过 1.开启telent远程登陆服务 sys …...

GaussDB数据库中的MERGE INTO介绍
一、前言 二、GaussDB MERGE INTO 语句的原理概述 1、MERGE INTO 语句原理 2、MERGE INTO 的语法 3、语法解释 三、GaussDB MERGE INTO 语句的应用场景 四、GaussDB MERGE INTO 语句的示例 1、示例场景举例 2、示例实现过程 1)创建两个实验表,并…...

2024年上海高考数学最后四个多月的备考攻略,目标140+
亲爱的同学们,寒假已经来临,春节即将到来,距离2024年上海高考已经余额不足5个月了。作为让许多学子头疼,也是拉分大户的数学科目,你准备好了吗?今天,六分成长为您分享上海高考数学最后四个多月的…...

SSL证书自动化管理有什么好处?如何实现SSL证书自动化?
SSL证书是用于加密网站与用户之间传输数据的关键元素,在维护网络安全方面,管理SSL证书与部署SSL证书一样重要。定期更新、监测和更换SSL证书,可以确保网站的安全性和合规性。而自动化管理可以为此节省时间,并避免人为错误和不必要…...

路由器初始化配置、功能配置
实验环境 拓扑图 Ip规划表(各组使用自己的IP规划表) 部门 主机数量 网络地址 子网掩码 网关 可用ip Vlan 市场部 38 192.168.131.0 255.255.255.0 192.168.131.1 2-254 11 研发部 53 192.168.132.0 255.255.255.0 192.168.132.1 2-2…...

node介绍
1.node是什么 Node是一个基于Chrome V8引擎的JS运行环境。 Node不是一个独立的语言、node不是JS框架。 Node是一个除了浏览器之外的、可以让JS运行的环境 Node.js是一个让JS运行在服务端的开发平台,是使用事件驱动,异步非阻塞I/O,单线程&…...

海外抖音TikTok、正在内测 AI 生成歌曲功能,依靠大语言模型 Bloom 进行文本生成歌曲
近日,据外媒The Verge报道,TikTok正在测试一项新功能,利用大语言模型Bloom的AI能力,允许用户上传歌词文本,并使用AI为其添加声音。这一创新旨在为用户提供更多创作音乐的工具和选项。 Bloom 是由AI初创公司Hugging Fac…...

【ARM 嵌入式 编译系列 3.6 -- 删除lib中的某个文件】
请阅读【嵌入式开发学习必备专栏 之 ARM GCC 编译专栏】 文章目录 删除lib中的某个文件 删除lib中的某个文件 比如,如果要删除 libc.a 静态库中的特定对象文件并重新使用这个静态库,在终端中可以使用 ar 命令。ar 是一个归档工具,它可以创建…...

web架构师编辑器内容-图层拖动排序功能的开发
新的学习方法 用手写简单方法实现一个功能然后用比较成熟的第三方解决方案即能学习原理又能学习第三方库的使用 从两个DEMO开始 Vue Draggable Next: Vue Draggable NextReact Sortable HOC: React Sortable HOC 列表排序的三个阶段 拖动开始(dragstart&#x…...

3.RHCSA脚本配置及通过node2改密码
运行脚本发现node2不成功 脚本破解 选第二个 Ctrl x 换行 破解成功后做node2的改密码题 回到redhat, 发现检测程序检测密码题成功,得了8分....

AtCoder Regular Contest 170(A~B)
A - Yet Another AB Problem 给你两个字符串S和T,你可以对S执行操作,选择两个字符,将前面的改为A,后面的改为B,最少操作几次可以把S改成T。如果改不成就输出-1。 从左往右一个一个改过去,分类讨论&#x…...

rk1126, 实现 yolov8 目标检测
基于 RKNN 1126 实现 yolov8 目标检测 Ⓜ️ RKNN 模型转换 ONNX yolo export model./weights/yolov8s.pt formatonnx导出 RKNN 这里选择输出 concat 输入两个节点 onnx::Concat_425 和 onnx::Concat_426 from rknn.api import RKNNONNX_MODEL ./weights/yolov8s.onnxRKNN_MOD…...

【软件测试】学习笔记-网站可扩展性架构设计
可扩展性,指的是网站的架构设计能够快速适应需求的变化,当需要增加新的功能实现时,对原有架构不需要做修改或者做很少的修改就能够快速实现新的业务需求。 从这个定义中,我们很容易就可以得出衡量网站可扩展性设计优秀与否的主要标…...

深度学习常用代码总结(k-means, NMS)
目录 一、k-means 算法 二、NMS 一、k-means 算法 k-means 是一种无监督聚类算法,常用的聚类算法还有 DBSCAN。k-means 由于其原理简单,可解释强,实现方便,收敛速度快,在数据挖掘、数据分析、异常检测、模式识别、金…...
数据结构·顺序表应用
本节应用是要用顺序表实现一个通讯录,收录联系人的姓名、性别、电话号码、住址、年龄 顺序表的实现在上一节中已经完成了,本节的任务其实就是应用上节写出来的代码的那些接口函数功能,做出来一个好看的,可…...

第一个 OpenGL 程序:旋转的立方体(VS2022 / MFC)
文章目录 OpenGL API开发环境在 MFC 中使用 OpenGL初始化 OpenGL绘制图形重置视口大小 创建 MFC 对话框项目添加 OpenGL 头文件和库文件初始化 OpenGL画一个正方形OpenGL 坐标系改变默认颜色 重置视口大小绘制立方体使用箭头按键旋转立方体深度测试添加纹理应用纹理换一个纹理 …...

剩余银饰的重量 - 华为OD统一考试
OD统一考试(C卷) 分值: 100分 题解: Java / Python / C 题目描述 有N块二手市场收集的银饰,每块银饰的重量都是正整数,收集到的银饰会被熔化用于打造新的饰品。 每一回合,从中选出三块 最重的…...

redis远程连接不上解决办法
问题描述: redis远程服务端运行在192.168.3.90计算机上,客户端计算机(ip:192.168.3.110)通过redsi-cli.exe客户端工具连接时,没有反应,连接不上。 如图所示: 解决步骤: 步骤一&…...

利用Anaconda安装pytorch和paddle深度学习环境+pycharm安装后不能调用pytorch和paddlepaddle框架
问题现象: 之前安装后不能在添加pytorch和paddlepaddle框架 原因(疑似): 在终端中显示pytorch和paddle在C盘但是安装是安装在J盘 解决办法: 卸载、删除文件重新安装后可以看到文件位置在J盘中 但是选择时还是显示C…...

Eclipses安装教程
一、下载开发工具包 1、开发工具包JDK 下载地址链接:https://www.oracle.com/cn/java/technologies/downloads/ 下载教程: 1)点击链接,可以跳转到页面 2)下滑页面,找到开发工具包 3) 记住下载之…...

安装python版opencv的一些问题
安装python版opencv的一些问题 OpenCV是知名的开源计算机视觉算法库,提供了C\Python\Java版共享库。 在Python中使用OpenCV格外简单,一句命令就能安装,一行import就能引入,可谓是神器。然而,在实际使用中可能遇到一些…...

RabbitMQ入门实战
RabbitMQ 是一个开源的消息中间件,实现了高级消息队列协议(AMQP),用于在分布式系统中进行消息传递。它能够在应用之间传递消息,解耦应用组件,提高系统的可伸缩性和可维护性。RabbitMQ 使用高级消息队列协议…...

vue3-模版引用ref
1. 介绍 概念:通过 ref标识 获取真实的 dom对象或者组件实例对象 2. 基本使用 实现步骤: 调用ref函数生成一个ref对象 通过ref标识绑定ref对象到标签 代码如下: 父组件: <script setup> import { onMounted, ref } …...

C# 十大排序算法
以下是常见的十大排序算法(按照学习和实现的顺序排列): 冒泡排序(Bubble Sort)选择排序(Selection Sort)插入排序(Insertion Sort)希尔排序(Shell Sort&…...

面试之Glide如何绑定Activity的生命周期
Glide绑定Activity生命周期 Glide.with() 下面都是它的重载方法,Context,Activity,FragmentActivity, Fragment, android.app.Fragment fragment,View都可以作为他的参数,内容大同小异,都是先getRetriever࿰…...

从 fatal 错误到 sync.Map:Go中 Map 的并发策略
为什么 Go 语言在多个 goroutine 同时访问和修改同一个 map 时,会报出 fatal 错误而不是 panic?我们该如何应对 map 的数据竞争问题呢? 这篇文章将带你一步步了解背后的原理,并引出解决 map 并发问题的方案。 Map 数据竞争 首先…...

Simon算法详解
0.0 Intro 相关的算法: Deutsh-Jozsa算法: 第一个量子算法对经典算法取得指数级加速的算法 美中不足在于只能确定函数是平衡的还是非平衡的,无法确定函数具体的内容,即无法直接解出函数 Bernstein-Vazirani算法ÿ…...