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() 应用于边缘图像,以搜索半径值在 1020 像素之间的圆,并进行投票。选择得票最多的圆,我们将 total_num_peaks 参数设置为一个较高值。为了避免多次检测到同一单元,我们需要通过使用参数 min_xdistancemin_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 测量参考点能否被认为是形状的局部坐标系的原点。
广义霍夫变换解释了如何使用任意非解析形状的边界来构建图像空间和霍夫变换空间之间的映射,可以利用这样的映射来检测图像中特定形状的实例。此外,形状的变化(例如旋转,比例变化或图形逆转)对应于该映射的直接转换。但是,最显着的特征是,可以组合这些映射,从简单形状和组件形状的映射中构建复杂形状的映射。这使得广义霍夫成为一种通用变换,可以用来寻找任意复杂的形状。
在本节中,我们将学习如何使用 OpenCVcreateGeneralizedHoughard() 函数来检测任意形状(作为模板图像提供)。

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】边缘检测详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/639118.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

H5112C PWM调光 无频闪 高性价比 支持12V 24V 36V 48V 60V 72V 内置MOS

PWM调光芯片是一种常用于LED调光控制的芯片,其工作原理如下: 脉冲宽度调制(PWM):PWM是一种调制技术,通过改变信号的脉冲宽度来控制输出信号的平均功率。在PWM调光中,芯片会以一定的频率产生一系…

SpringCloud Alibaba 深入源码 - Nacos 和 Eureka 的区别(健康检测、服务的拉取和订阅)

目录 一、Nacos 和 Eureka 的区别 1.1、以 Nacos 注册流程来解析区别 一、Nacos 和 Eureka 的区别 1.1、以 Nacos 注册流程来解析区别 a)首先,我们的服务启动时。都会把自己的信息提交给注册中心,然后注册中心就会把信息保存下来. 注册的…

Midjourney常见参数列表(极速版)

前言 参数是添加到提示词末尾的选项,可以改变图片的生成方式。参数可以改变图片的长宽比(Aspect Ratios),切换不同的Midjourney模型版本(Model Versions),改变使用的放大器(Upscaler…

Leetcode 3016. Minimum Number of Pushes to Type Word II

Leetcode 3016. Minimum Number of Pushes to Type Word II 1. 解题思路2. 代码实现 题目链接:3016. Minimum Number of Pushes to Type Word II 1. 解题思路 这道题的话思路其实还是蛮简单的,显然我们的目的是要令对给定的word在键盘上敲击的次数最小…

ELK日志分析

目录 一、ELK概述 (一)ELK的定义 (二)ELK工具 1.ElasticSearch 2.Kiabana 3.Logstash (1)定义 (2)插件 ① input ② filter ③ output (三)可以添…

Spring、Spring-MVC、Mybatis、Mybatis-generator整合核心配置文件记录

Spring、Spring-MVC、Mybatis、Mybatis-generator整合核心配置文件记录 文章目录 Spring、Spring-MVC、Mybatis、Mybatis-generator整合核心配置文件记录1. spring.xml2. spring-mvc.xml3. mybatis-config.xml4. mybaits-generator.xml5. ehcach.xml6. web.xml Spring、Spring-…

快速排序(三)——hoare法

目录 ​一.前言 二.快速排序 hoare排法​ 三.结语 一.前言 本文给大家带来的是快速排序,快速排序是一种很强大的排序方法,相信大家在学习完后一定会有所收获。 码字不易,希望大家多多支持我呀!(三连+关…

Spring Boot3整合Druid(监控功能)

目录 1.前置条件 2.导依赖 错误依赖: 正确依赖: 3.配置 1.前置条件 已经初始化好一个spring boot项目且版本为3X,项目可正常启动。 作者版本为3.2.2最新版 2.导依赖 错误依赖: 这个依赖对于spring boot 3的支持不够&#…

微服务架构弹性伸缩策略方案

微服务架构的弹性伸缩策略是确保系统能够在不同工作负载下高效运行的关键。通过巧妙的策略,可以实现对每个微服务的独立伸缩,提高系统的灵活性和性能。本文将深入探讨微服务架构下的弹性伸缩方案。 1. 独立微服务的弹性伸缩 微服务架构的核心思想是将应…

用go语言删除重复文件

用go语言删除重复文件 文章目录 用go语言删除重复文件需求:将同级别目录(只有一层的目录,没子目录)下的重复文件删除打包成exe文件使用 需求:将同级别目录(只有一层的目录,没子目录)…

H5嵌入小程序适配方案

时间过去了两个多月,2024已经到来,又老了一岁。头发也掉了好多。在这两个月时间里都忙着写页面,感觉时间过去得很快。没有以前那么轻松了。也不是遇到了什么难点技术,而是接手了一个很烂得项目。能有多烂,一个页面发起…

Sim ROS2

ROS2_Galactic Ubuntu (Debian) — ROS 2 Documentation: Galactic documentation VMware界面大小调整两种方法超详细教程_vmware怎么调整虚拟机界面大小-CSDN博客 orca4 simulator https://github.com/clydemcqueen/orca4 Docker 【 全干货 】5 分钟带你看懂 Docker &#…

开源无代码应用程序生成器Saltcorn

什么是 Saltcorn ? Saltcorn 是一个无需编写任何代码即可构建数据库 Web 应用程序的平台。它配备了一个吸睛的仪表板,丰富的生态系统、视图生成器以及支持主题的界面,使用直观的点击、拖放用户界面来构建整个应用程序。 软件的特点&#xff1…

100213. 按距离统计房屋对数目 II

100213. 按距离统计房屋对数目 II - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<int> dif;void add(int l, int r, int d) {if (l > r) return;dif[l] d;dif[r 1] - d;return;}vector<long long> countOfPairs(int n, int x, in…

智慧文旅运营综合平台:重塑文化旅游产业的新引擎

目录 一、建设意义 二、包含内容 三、功能架构 四、典型案例 五、智慧文旅全套解决方案 - 210份下载 在数字化浪潮席卷全球的今天&#xff0c;智慧文旅运营综合平台作为文化旅游产业与信息技术深度融合的产物&#xff0c;正逐渐显现出其强大的生命力和广阔的发展前景。 该…

iOS长图生成的pdf性能优化记录

背景 某日产品拿来了一个由30多页高清长图生成的pdf&#xff0c;在应用中运行出现了崩溃。 排查 经过调试发现加载长图生成的pdf时&#xff0c;运行内存会出现缓慢增长&#xff0c;直至崩溃。经过代码定位发现时pdf转成image对象的过程中由于是长图生成的pdf&#xff0c;这一页…

海外抖音TikTok、正在内测 AI 生成歌曲功能,依靠大语言模型 Bloom 进行文本生成歌曲

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

使用torch求函数参数

一、先了解一下深度学习是如何优化参数的 import torch import mathclass Polynomial3(torch.nn.Module):def __init__(self):super().__init__()self.a torch.nn.Parameter(torch.randn(()))self.b torch.nn.Parameter(torch.randn(()))self.c torch.nn.Parameter(torch.r…

C语言——内存函数介绍和模拟实现(memcpy、memmove、memset、memcmp)

之前我们讲过一些字符串函数&#xff08;http://t.csdnimg.cn/ZcvCo&#xff09;&#xff0c;今天我们来讲一讲几个内存函数&#xff0c;那么可能有人要问了&#xff0c;都有字符串函数了&#xff0c;怎么又来个内存函数&#xff0c;这不是一样的么&#xff1f; 我们要知道之前…

第十二站(20天):C++泛型编程

模板 C提供了模板(template)编程的概念。所谓模板&#xff0c;实际上是建立一个通用函数或类&#xff0c; 其 类内部的类型和函数的形参类型不具体指定 &#xff0c;用一个虚拟的类型来代表。这种通用的方式称 为模板。 模板是泛型编程的基础, 泛型编程即以一种独立于任何特定…