当前位置: 首页 > news >正文

图像处理之hough圆形检测

hough检测原理

点击图像处理之Hough变换检测直线查看
下面直接描述检测圆形的方法

基于Hough变换的圆形检测方法

对于一个半径为 r r r,圆心为 ( a , b ) (a,b) a,b的圆,我们将其表示为:
( x − a ) 2 + ( y − b ) 2 = r 2 (x-a)^2+(y-b)^2=r^2 (xa)2+(yb)2=r2
此时 x = [ x , y ] T , a = [ a , b , r ] T x=[x,y]^T,a=[a,b,r]^T x=[x,y]Ta=[a,b,r]T,其参数空间为三维。显然,图像空间上的一点 ( x , y ) (x,y) x,y,在参数空间中对应着一个圆锥,如下图所示。
在这里插入图片描述
而图像空间的一个圆就对应着这一簇圆锥相交的一个点,这个特定点在参数空间的三维参数一定,就表示一定半径一定圆心坐标的图像空间的那个圆。
上述方法是经典的Hough圆检测方法的原理,它具有精度高,抗干扰能力强等优点,但由于该方法的参数空间为三维,要在三维空间上进行证据累计的话,需要的时间和空间都是庞大的,在实际应用中不适用。为加快Hough变换检测圆的速度,学者们进行了大量研究,也出现了很多改进的Hough变换检测圆的方法。如利用图像梯度信息的Hough变换,对圆的标准方程对x求导得到下式:
2 ( x − a ) + 2 ( y − b ) d y d x = 0 2(x-a)+2(y-b)\frac{dy}{dx}=0 2(xa)+2(yb)dxdy=0
从上式看出,此时的参数空间从半径 r r r,圆心 ( a , b ) (a,b) a,b三维,变成了只有圆心 ( a , b ) (a,b) a,b的二维空间,利用这种方法检测圆其计算量明显减少了。
但这种改进的Hough变换检测圆的方法其检测精度并不高,原因在于,此种方法利用了边界斜率。
从本质上讲,边界斜率其实是用曲线在某一点的弦的斜率来代替的,这种情况下,要保证不存在误差,只有在弦长为零的情况。但在数字图像中,曲线的表现形式是离散的,其在某一点处的斜率指的是此点右向n步斜率或是左向n步斜率。如果弦长过小了,斜率的量化误差就会增大。这种方法比较适用于干扰较少的完整圆形目标。
在这里插入图片描述

主要代码:

def AHTforCircles(edge,center_threhold_factor = None,score_threhold = None,min_center_dist = None,minRad = None,maxRad = None,center_axis_scale = None,radius_scale = None,halfWindow = None,max_circle_num = None):if center_threhold_factor == None:center_threhold_factor = 10.0if score_threhold == None:score_threhold = 15.0if min_center_dist == None:min_center_dist = 80.0if minRad == None:minRad = 0.0if maxRad == None:maxRad = 1e7*1.0if center_axis_scale == None:center_axis_scale = 1.0if radius_scale == None:radius_scale = 1.0if halfWindow == None:halfWindow = 2if max_circle_num == None:max_circle_num = 6min_center_dist_square = min_center_dist**2sobel_kernel_y = np.array([[-1.0, -2.0, -1.0], [0.0, 0.0, 0.0], [1.0, 2.0, 1.0]])sobel_kernel_x = np.array([[-1.0, 0.0, 1.0], [-2.0, 0.0, 2.0], [-1.0, 0.0, 1.0]])edge_x = convolve(sobel_kernel_x,edge,[1,1,1,1],[1,1])edge_y = convolve(sobel_kernel_y,edge,[1,1,1,1],[1,1])center_accumulator = np.zeros((int(np.ceil(center_axis_scale*edge.shape[0])),int(np.ceil(center_axis_scale*edge.shape[1]))))k = np.array([[r for c in range(center_accumulator.shape[1])] for r in range(center_accumulator.shape[0])])l = np.array([[c for c in range(center_accumulator.shape[1])] for r in range(center_accumulator.shape[0])])minRad_square = minRad**2maxRad_square = maxRad**2points = [[],[]]edge_x_pad = np.pad(edge_x,((1,1),(1,1)),'constant')edge_y_pad = np.pad(edge_y,((1,1),(1,1)),'constant')Gaussian_filter_3 = 1.0 / 16 * np.array([(1.0, 2.0, 1.0), (2.0, 4.0, 2.0), (1.0, 2.0, 1.0)])for i in range(edge.shape[0]):for j in range(edge.shape[1]):if not edge[i,j] == 0:dx_neibor = edge_x_pad[i:i+3,j:j+3]dy_neibor = edge_y_pad[i:i+3,j:j+3]dx = (dx_neibor*Gaussian_filter_3).sum()dy = (dy_neibor*Gaussian_filter_3).sum()if not (dx == 0 and dy == 0):t1 = (k/center_axis_scale-i)t2 = (l/center_axis_scale-j)t3 = t1**2 + t2**2temp = (t3 > minRad_square)&(t3 < maxRad_square)&(np.abs(dx*t1-dy*t2) < 1e-4)center_accumulator[temp] += 1points[0].append(i)points[1].append(j)M = center_accumulator.mean()for i in range(center_accumulator.shape[0]):for j in range(center_accumulator.shape[1]):neibor = \center_accumulator[max(0, i - halfWindow + 1):min(i + halfWindow, center_accumulator.shape[0]),max(0, j - halfWindow + 1):min(j + halfWindow, center_accumulator.shape[1])]if not (center_accumulator[i,j] >= neibor).all():center_accumulator[i,j] = 0# 非极大值抑制plt.imshow(center_accumulator,cmap='gray')plt.axis('off')plt.show()center_threshold = M * center_threhold_factorpossible_centers = np.array(np.where(center_accumulator > center_threshold))  # 阈值化sort_centers = []for i in range(possible_centers.shape[1]):sort_centers.append([])sort_centers[-1].append(possible_centers[0,i])sort_centers[-1].append(possible_centers[1,i])sort_centers[-1].append(center_accumulator[sort_centers[-1][0],sort_centers[-1][1]])sort_centers.sort(key=lambda x:x[2],reverse=True)centers = [[],[],[]]points = np.array(points)for i in range(len(sort_centers)):radius_accumulator = np.zeros((int(np.ceil(radius_scale * min(maxRad, np.sqrt(edge.shape[0] ** 2 + edge.shape[1] ** 2)) + 1))),dtype=np.float32)if not len(centers[0]) < max_circle_num:breakiscenter = Truefor j in range(len(centers[0])):d1 = sort_centers[i][0]/center_axis_scale - centers[0][j]d2 = sort_centers[i][1]/center_axis_scale - centers[1][j]if d1**2 + d2**2 < min_center_dist_square:iscenter = Falsebreakif not iscenter:continuetemp = np.sqrt((points[0,:] - sort_centers[i][0] / center_axis_scale) ** 2 + (points[1,:] - sort_centers[i][1] / center_axis_scale) ** 2)temp2 = (temp > minRad) & (temp < maxRad)temp = (np.round(radius_scale * temp)).astype(np.int32)for j in range(temp.shape[0]):if temp2[j]:radius_accumulator[temp[j]] += 1for j in range(radius_accumulator.shape[0]):if j == 0 or j == 1:continueif not radius_accumulator[j] == 0:radius_accumulator[j] = radius_accumulator[j]*radius_scale/np.log(j) #radius_accumulator[j]*radius_scale/jscore_i = radius_accumulator.argmax(axis=-1)if radius_accumulator[score_i] < score_threhold:iscenter = Falseif iscenter:centers[0].append(sort_centers[i][0]/center_axis_scale)centers[1].append(sort_centers[i][1]/center_axis_scale)centers[2].append(score_i/radius_scale)centers = np.array(centers)centers = centers.astype(np.float64)return centers

代码效果:
在这里插入图片描述
在这里插入图片描述

全部代码可见本人GitHub仓库,如果代码有用,please click star and watching
hough检测之前需要canny算子检测基础的边缘,点击这里可以查看有关canny算法相关内容

如果本文对你有帮助,关注加点赞!!!!!

相关文章:

图像处理之hough圆形检测

hough检测原理 点击图像处理之Hough变换检测直线查看 下面直接描述检测圆形的方法 基于Hough变换的圆形检测方法 对于一个半径为 r r r&#xff0c;圆心为 &#xff08; a , b &#xff09; &#xff08;a,b&#xff09; &#xff08;a,b&#xff09;的圆&#xff0c;我们将…...

el-upload文件上传(只能上传一个文件且再次上传替换上一个文件) vue3+vite+ts

组件&#xff1a; <template><el-upload class"upload-demo" v-model:file-list"fileList" ref"uploadDemo" action"/public-api/api/file" multiple:on-preview"handlePreview" :on-remove"handleRemove&quo…...

随手笔记——根据点对来估计相机的运动综述

随手笔记——根据点对来估计相机的运动综述 说明计算相机运动 说明 简单介绍3种情况根据点对来估计相机运动所使用的方法 计算相机运动 有了匹配好的点对&#xff0c;接下来&#xff0c;要根据点对来估计相机的运动。这里由于相机的原理不同分为&#xff1a; 当相机为单目时…...

ip校园广播音柱特点

ip校园广播音柱特点IP校园广播音柱是一种基于IP网络技术的音频播放设备&#xff0c;广泛应用于校园、商业区、公共场所等地方。它可以通过网络将音频信号传输到不同的音柱设备&#xff0c;实现远程控制和集中管理。IP校园广播音柱具备以下特点和功能&#xff1a;1. 网络传输&am…...

用 Node.js 手写 WebSocket 协议

目录 引言 从 http 到 websocekt 的切换 Sec-WebSocket-Key 与 Sec-WebSocket-Accept 全新的二进制协议 自己实现一个 websocket 服务器 按照协议格式解析收到的Buffer 取出opcode 取出MASK与payload长度 根据mask key读取数据 根据类型处理数据 frame 帧 数据的发…...

Xilinx AXI VIP使用教程

AXI接口虽然经常使用&#xff0c;很多同学可能并不清楚Vivado里面也集成了AXI的Verification IP&#xff0c;可以当做AXI的master、pass through和slave&#xff0c;本次内容我们看下AXI VIP当作master时如何使用。 新建Vivado工程&#xff0c;并新建block design&#xff0c;命…...

mysql主主架构搭建,删库恢复

mysql主主架构搭建&#xff0c;删库恢复 搭建mysql主主架构环境信息安装msql服务mysql1mysql2设置mysql2同步mysql1设置mysql1同步mysql2授权测试用账户 安装配置keepalivedmysql1检查脚本mysql2检查脚本 备份策略mysqldump全量备份mysqldump增量备份数据库目录全量备份 删除my…...

pythonweek1

引言 做任何事情都要脚踏实地&#xff0c;虽然大一上已经学习了python的基础语法&#xff0c;大一下也学习了C加加中的类与对象&#xff0c;但是自我觉得基础还不太扎实&#xff0c;又害怕有什么遗漏&#xff0c;所以就花时间重新学习了python的基础&#xff0c;学习Python的基…...

进程虚拟地址空间区域划分

目录 图示 详解 代码段 备注&#xff1a;x86 32位linux环境下&#xff0c;进程虚拟地址空间区域划分 图示 详解 用户空间 用于存储用户进程代码和数据&#xff0c;只能由用户进程访问 内核空间 用于存储操作系统内核代码和数据&#xff0c;只能由操作系统内核访问 text t…...

OpenAI Code Interpreter 的开源实现:GPT Code UI

本篇文章聊聊 OpenAI Code Interpreter 的一众开源实现方案中&#xff0c;获得较多支持者&#xff0c;但暂时还比较早期的项目&#xff1a;GPT Code UI。 写在前面 这篇文章本该更早的时候发布&#xff0c;但是 LLaMA2 发布后实在心痒难忍&#xff0c;于是就拖了一阵。结合 L…...

macOS Ventura 13.5 (22G74) 正式版发布,ISO、IPSW、PKG 下载

macOS Ventura 13.5 (22G74) 正式版发布&#xff0c;ISO、IPSW、PKG 下载 本站下载的 macOS Ventura 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也…...

Electron 主进程和渲染进程传值及窗口间传值

1 渲染进程调用主进程得方法 下面是渲染进程得代码: let { ipcRenderer} require( electron ); ipcRenderer.send( xxx ); //渲染进程中调用 下面是主进程得代码: var { ipcMain } require( electron ); ipcMain.on("xxx",function () { } )...

C#设计模式之---建造者模式

建造者模式&#xff08;Builder Pattern&#xff09; 建造者模式&#xff08;Builder Pattern&#xff09;是将一个复杂对象的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。建造者模式使得建造代码与表示代码的分离&#xff0c;可以使客户端不必知道…...

output delay 约束

output delay 约束 一、output delay约束概述二、output delay约束系统同步三、output delay约束源同步 一、output delay约束概述 特别注意&#xff1a;在源同步接口中&#xff0c;定义接口约束之前&#xff0c;需要用create_generated_clock 先定义送出的随路时钟。 二、out…...

html2Canvas+jsPDF 下载PDF 遇到跨域的对象存储的图片无法显示

一、问题原因 对象存储的域名和你网址的域名不一样&#xff0c;此时用Canvas相关插件 将DOM元素转化为PDF&#xff0c;就会出现跨域错误。 二、解决办法 两步 1. 图片元素上设置属性 crossorigin"anonymous" 支持原生img和eleme组件 2. 存储桶设置资源跨域访问…...

【C#】并行编程实战:异步流

本来这章该讲的是 ASP .NET Core 中的 IIS 和 Kestrel &#xff0c;但是我看了下这个是给服务器用的。而我只是个 Unity 客户端程序&#xff0c;对于服务器的了解趋近于零。 鉴于我对服务器知识和需求的匮乏&#xff0c;这里就不讲原书&#xff08;大部分&#xff09;内容了。本…...

在家下载论文使用哪些论文下载工具比较好

在家下载论文如果不借助论文下载工具是非常艰难的事情&#xff0c;因为很多查找下载论文的数据库都是需要账号权限才可使用的。 例如&#xff0c;我们查找中文论文常用的知网、万方等数据库以及众多国外论文数据库。 在家下载知网、万方数据库论文可用下面的方法&#xff1a;…...

【LeetCode 算法】Handling Sum Queries After Update 更新数组后处理求和查询-Segment Tree

文章目录 Handling Sum Queries After Update 更新数组后处理求和查询问题描述&#xff1a;分析代码线段树 Tag Handling Sum Queries After Update 更新数组后处理求和查询 问题描述&#xff1a; 给你两个下标从 0 开始的数组 n u m s 1 和 n u m s 2 nums1 和 nums2 nums1…...

基于Linux操作系统中的MySQL数据库SQL语句(三十一)

MySQL数据库SQL语句 目录 一、SQL语句类型 1、DDL 2、DML 3、DCL 4、DQL 二、数据库操作 1、查看 2、创建 2.1、默认字符集 2.2、指定字符集 3、进入 4、删除 5、更改 6、练习 三、数据表操作 &#xff08;一&#xff09;数据类型 1、数值类型 1.1、TINYINT …...

【Matlab】基于BP神经网络的数据回归预测新数据(Excel可直接替换数据)

【Matlab】基于BP神经网络的数据回归预测新数据(Excel可直接替换数据) 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码5.1 main.m5.2 NewData.m6.完整代码6.1 main.m6.2 NewData.m7.运行结果1.模型原理 基于BP神经网络的数据回归预测是一种常见的机器学习方法,用于处…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...