图像处理之霍夫变换圆检测算法
霍夫变换检测圆原理

霍夫变换检测圆原理霍夫变换是一种用于在数字图像或视频中检测几何形状的技术。
其中一种最常用的应用是在二维空间中检测圆形。
霍夫变换的基本原理是将图像空间中的每个点转换为霍夫空间中的一组参数,该参数描述了一个可能的圆,然后在霍夫空间中搜索最具有代表性的参数集合,以确定图像中是否存在圆。
本文将详细介绍霍夫变换检测圆的原理和过程。
1. 霍夫变换霍夫变换是一种将图像中的点集映射到参数空间中表示为极坐标的技术。
对于给定的形状,如直线、圆形或椭圆,霍夫变换可以生成一组参数,以描述该形状的每个可能的实例。
这可以通过对每个可能的中心点和半径组合进行枚举来实现,在霍夫空间中将它们表示为参数空间的样条曲线。
2. 检测圆圆在霍夫空间中用其圆心坐标和半径表示。
要检测一个圆,首先需要在图像空间中检测出可能的圆心。
这可以通过在图像中运行边缘检测算法,如Canny算子,来找到。
找到圆心后,需要枚举半径来计算每个可能的圆周上的点,并将这些点转换到霍夫空间中。
在霍夫空间中,表示每个圆形的样条曲线交点组成强投票区域,这些点表示了最有可能表示检测到的圆形的半径和中心点的参数组合。
- 预处理图像,包括调整亮度、增强对比度、边缘检测等- 使用霍夫变换算法将图像空间中的点转换为霍夫空间中的参数点- 找到霍夫空间中的投票区域,它表示了每个可能的圆形的中心点和半径- 确定投票最多的区域,并将其作为检测到的圆形的属性优点:- 可以用于检测各种形状,不仅仅是圆形- 在处理边缘检测和圆检测问题时具有广泛的适用性- 可以处理噪声or具有较高的鲁棒性- 需要较长的计算时间和更高的计算能力- 对于大规模数据集,内存需求也很高- 在处理复杂形状时可能会有问题。
例如,如果两个圆形共享一条边,则霍夫变换可能会将它们错误地识别为单个圆形5. 总结霍夫变换是一种强大的技术,可以用于在图像或视频中检测几何形状。
在特定的应用程序中,它可以提供更准确和鲁棒的结果,而不会受到传统计算机视觉方法的限制。
霍夫圆算法识别重叠圆

霍夫圆算法可以用于识别图像中的重叠圆。
霍夫圆检测算法是霍夫变换的一个扩展,它专门用于在数字图像中检测圆形形状。
其基本原理是通过寻找图像中所有可能的圆心和半径组合来确定圆形。
具体步骤如下:
1. 边缘检测:首先对原始图像执行Canny边缘检测以获取边缘信息。
2. 计算梯度:使用Sobel算子或其他梯度计算方法,确定每个像素点的邻域梯度值。
3. 初始化累加器:创建一个累加器空间,用于记录所有可能的圆心(a,b)和半径r。
4. 遍历边缘点:对于Canny边缘二值图中的所有非零像素点,按照其梯度方向(即切线的垂直方向)画线,并将这些线段经过的累加器中的点(a,b)对应的N(a,b)增加1。
5. 统计排序:统计并排序累加器中的值,较大的N(a,b)表明对应点更可能是真实的圆心。
6. 估计半径:针对每个可能的圆心(a,b),计算Canny图中所有非零点到圆心的距离,并进行排序。
根据设定的阈值选择可能的半径。
当需要处理重叠圆的情况时,霍夫圆算法可能需要进一步的优化或与其他技术结合使用以提高准确率和鲁棒性。
例如,可以通过调整参数、增强边缘检测的准确性或采用多尺度分析等策略来改善检测性能。
hough 变换检测圆的一般步骤

hough 变换检测圆的一般步骤霍夫变换是一种图像处理算法,可用于检测图像中的圆形。
下面是霍夫变换检测圆的一般步骤:1.导入图像:首先,将要检测圆的图像导入到计算机中。
图像可以来自于摄像机、存储设备或是从其他算法的输出中获得。
2.灰度化处理:将彩色图像转换为灰度图像。
这是因为灰度图像只有一个通道,可以简化后续处理步骤。
3. 边缘检测:使用边缘检测算法(如Canny算子)对灰度图像进行处理,提取图像中的边缘。
这一步骤可以帮助找到圆形的边界。
4.霍夫变换:将边缘图像输入到霍夫变换中。
霍夫变换将边缘点从笛卡尔坐标系转换到霍夫空间,形成二维投票器矩阵。
在投票器矩阵中,每个圆形都有一个对应的概率值,用于表示该圆形的可能性。
5.阈值设置:在霍夫变换之后,需要设置一个阈值来确定哪些圆形应被认为是检测到的圆形。
根据应用的需求和图像的噪声程度,可以调整阈值的大小。
较高的阈值会产生较少的圆形,而较低的阈值会产生较多的圆形。
6.圆形检测:根据阈值从投票器矩阵中选择可能的圆形。
这些圆形可能包含噪声或重叠的圆形。
因此,需要进行圆形重叠或去噪的处理。
7.圆形参数提取:从霍夫空间中获取每个候选圆形的参数,如圆心的坐标和半径长度。
8.绘制圆形:根据提取的参数,在原始图像上绘制检测到的圆形。
这样一来,圆形就会在图像中展示出来。
9.输出结果:最后,将包含检测到的圆形的图像保存或显示出来。
可以使用不同的颜色或标记形式来区分不同的圆形。
霍夫变换是一种广泛应用于图像处理和计算机视觉领域的算法。
通过这一变换,我们可以快速准确地检测图像中的圆形,为后续的分析和应用提供基础。
霍夫变换原理检测圆的原理

霍夫变换原理检测圆的原理霍夫变换(Hough Transform)是一种数字图像处理技术,主要用于检测图像中的模式或物品,如直线、圆或任何其他形状。
其中,检测圆的原理是基于霍夫变换的圆检测算法。
首先,需要明确圆的数学表达式。
圆的一般方程为:(x –a)^2 + (y –b)^2 = r^2其中,a和b表示圆心的坐标,r表示半径。
基于这个数学表达式,可以推导出霍夫圆变换的算法原理。
相比于霍夫直线变换,霍夫圆变换需要考虑三个参数:圆心x坐标、圆心y坐标和半径r。
因此,在霍夫圆变换中,需要构建一个三维空间来表示所有满足圆方程的点。
具体而言,可以将三个参数分别设定成三个坐标轴,其中,x轴表示圆心x坐标,y轴表示圆心y坐标,z轴表示半径r。
接下来,对于给定的图像,利用霍夫圆变换来检测其中所有圆。
步骤如下:1. 选择图像中的一个点。
2. 在三维空间中,遍历所有可能的圆心位置和半径大小。
3. 如果当前遍历到的圆心和半径位置满足圆的方程,那么就在三维空间中标记这个点。
4. 重复步骤1~3,对于所有图像中的点进行遍历。
5. 经过遍历后,在三维空间中,所有标记的点都应该落在同一频繁性最高的球面上。
6. 在球面上,可以定义一个圆心和半径,这个圆心和半径就是最终检测出的圆的位置和大小。
7. 重复步骤1~6,对于所有图像中的圆进行遍历。
霍夫圆变换需要对所有可能的圆心位置和半径大小进行遍历,因此计算量非常大。
为了减少计算时间,通常采用一些优化方法,例如逐步增加圆的半径大小或设定一个半径范围。
总体而言,霍夫圆变换是一种有效的圆检测算法,它不仅可以检测出图像中的所有圆,还可以确定它们的位置和大小。
在计算机视觉、医学图像处理等领域广泛应用。
hough变换检测圆原理

hough变换检测圆原理
Hough变换是一种常用的图像处理算法,用于检测图像中的圆形目标。
其原理是将图像中的每个像素点转换为极坐标系下的参数空间,并在该空间中寻找圆心和半径相对应的峰值。
具体实现步骤如下:
1. 对图像进行边缘检测,得到一系列边缘点。
2. 在极坐标系下,将每个边缘点表示为一个三元组(r,θ,a),
其中r表示边缘点到图像原点的距离,θ表示边缘点与x轴的夹角,a表示圆心坐标在x轴上的投影。
3. 在参数空间中建立一个二维数组,表示每个可能的圆心(a,b)和半径r对应的计数值。
4. 遍历所有的边缘点,在参数空间中对应的位置上增加计数值。
5. 在参数空间中寻找计数值最大的位置,该位置所对应的圆心
和半径即为检测到的圆形目标。
通过Hough变换,我们可以快速高效地检测图像中的圆形目标。
该算法在计算复杂度和空间复杂度上相对较高,但其检测精度和鲁棒性较为优秀,广泛应用于计算机视觉和机器人领域。
- 1 -。
霍夫变换检测圆算法流程

霍夫变换检测圆算法流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor.I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!霍夫变换检测圆的算法流程详解霍夫变换是一种在图像处理中广泛使用的经典算法,尤其在检测直线、圆等几何形状方面表现出色。
霍夫变换圆形检测

霍夫变换圆形检测霍夫变换检测圆的原理:⼤家都知道三点可以确定⼀个圆,以这三点做所有半径的圆则必有⼀个公共交点,这个交点为以三点为圆的圆⼼。
霍夫变换检测圆形的原理跟检测直线的原理是⼀样的。
圆的表达式为(x-a)2+(y-b)2=r2,把问题转换成在求解经过像素点最多的 (a,b,r) 参数对。
常⽤检测圆的⽅法:(本⽂⽤的不是该⽅法)参考链接:https:///lancer2015/p/6852488.htmlhttps:///poem_qianmo/article/details/26977557代码如下:#include <opencv2/opencv.hpp> #include <iostream>#include <math.h>using namespace cv;using namespace std;int main(int argc, char** argv) {Mat src, dst;src = imread("L:/8.png");if (!src.data){printf("could not load image...\n");return -1;}char INPUT_TITLE[] = "input image";char OUTPUT_TITLE[] = "hough circle demo";namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);imshow(INPUT_TITLE, src);//中值滤波Mat moutput;//GaussianBlur(src, moutput,Size(5,5),0,0);medianBlur(src, moutput, 3);cvtColor(moutput, moutput, CV_BGR2GRAY);//霍夫圆检测vector<Vec3f>pcircles;HoughCircles(moutput,pcircles, CV_HOUGH_GRADIENT, 1, 10, 100, 30, 5, 50); src.copyTo(dst);for (size_t i = 0; i < pcircles.size(); i++){Vec3f cc = pcircles[i];circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 0, 255), 1.5, LINE_AA); //画圆形 //参数:1.要画的图像 2.圆⼼ 3.半径 4.颜⾊ 5.线的粗细 6.线条类型circle(dst, Point(cc[0], cc[1]), 2, Scalar(0, 255, 0), 2, LINE_AA); //画圆⼼ }imshow(OUTPUT_TITLE, dst);waitKey(0);return0;}实验结果:原图检测图:。
霍夫变换检测同心圆

霍夫变换检测同心圆引言霍夫变换是一种图像处理技术,用于检测图像中的特定形状。
本文将介绍如何使用霍夫变换来检测同心圆。
首先,我们将简要介绍霍夫变换的原理和应用领域。
然后,我们将详细讨论如何在图像中检测同心圆,并提供相关代码示例和实验结果。
霍夫变换原理霍夫变换是由Paul Hough于1962年提出的一种图像处理技术。
它可以用来检测图像中的直线、圆等特定形状。
霍夫变换的基本思想是将图像空间中的点映射到参数空间中,从而使特定形状在参数空间中对应于一个明显的峰值。
以检测直线为例,对于每个图像空间中的点(x, y),我们可以通过一条直线方程ρ = x cos(θ) + y sin(θ)来表示。
其中,ρ是直线到原点的距离,θ是直线与x轴之间的角度。
通过遍历所有可能的ρ和θ值,并统计通过每个点(x, y)的直线数量,在参数空间中找到峰值点即可得到最终检测到的直线。
类似地,我们可以将同心圆表示为一组参数(a, b, r),其中(a, b)是圆心坐标,r 是半径。
通过遍历所有可能的(a, b, r)值,并统计通过每个点(x, y)的圆数量,在参数空间中找到峰值点即可得到最终检测到的同心圆。
霍夫变换检测同心圆步骤以下是使用霍夫变换检测同心圆的步骤:1.读取图像:首先,我们需要从文件或其他数据源中读取待处理的图像。
2.预处理图像:为了提高检测效果,我们通常需要对图像进行预处理。
常见的预处理操作包括灰度化、平滑滤波、边缘检测等。
3.参数空间初始化:根据待检测同心圆的半径范围,初始化参数空间。
参数空间通常以三维数组形式表示,其中第一维表示圆心x坐标,第二维表示圆心y坐标,第三维表示半径r。
4.遍历图像空间:对于每个图像空间中的点(x, y),计算其对应于参数空间中所有可能(a, b, r)值的投票。
投票操作可以简单地增加对应(a, b, r)位置的计数器。
5.寻找峰值点:在参数空间中找到投票数量最多的点,该点对应于检测到的同心圆。
霍夫变换能检测圆的原理

霍夫变换能检测圆的原理
霍夫变换是通过在极坐标系中进行投票来检测圆的方法。
其原理如下:
1. 遍历图像的所有点,对于每个点,判断它是否为边缘点(即灰度值超过某个阈值)。
2. 对于每个边缘点,以该点为圆心,在极坐标系中遍历所有可能的半径值。
3. 对于每个半径值,计算在该圆上的所有点的极坐标,并将其转换为参数空间中的一个点。
4. 在参数空间中统计每个点的投票数。
每个投票数表示图像中有多少个边缘点在对应的圆上。
5. 根据投票数确定参数空间中的峰值,即表示图像中存在的圆。
霍夫变换的关键在于参数空间的构造。
参数空间通常为一个二维空间,其中一个维度表示圆心的横坐标,另一个维度表示圆心的纵坐标。
不同的半径值对应于不同的圆,因此需要遍历所有可能的半径值。
由于参数空间维度较高,实际计算时通常采用累加器数组来存储投票数。
霍夫变换的优点是能够检测各种尺寸的圆,但由于需要遍历所有可能的圆心和半径值,计算复杂度较高。
因此在实际应用中,通常会使用一些优化方法来加速霍夫变换的计算过程。
图像处理中的霍夫变换算法

图像处理中的霍夫变换算法霍夫变换算法是一种基于数学理论的图像处理方法,用于检测图像中的直线、圆和其他形状。
它广泛应用于计算机视觉、机器人和自然语言处理等领域。
在本文中,我们将探讨霍夫变换算法及其在图像处理中的应用。
一、霍夫变换的原理霍夫变换是一种图像处理技术,用于检测图像中的直线和圆。
它可以将图像中的点转换成一系列参数空间中的曲线。
对于每个曲线,计算它在参数空间中的过程称为霍夫变换。
在霍夫变换中,直线和圆的参数被表示为二元组 $(a, b)$ 或三元组 $(x_{o}, y_{o}, r)$。
对于直线 $(x, y)$,其参数空间可以表示为 $(a, b)$,其中 $a$ 是经过 $(x, y)$ 的斜率,$b$ 是截距。
对于圆$(x, y)$,其参数空间可以表示为 $(x_{o}, y_{o}, r)$,其中$(x_{o}, y_{o})$ 是圆心的坐标,$r$ 是半径。
在进行霍夫变换时,需要建立一个二维数组,用于记录每个参数 $(a, b)$ 或 $(x_{o}, y_{o}, r)$ 对应的曲线通过的点数。
对于每个点,计算其对应的参数,并在相应的数组元素中增加计数器。
最后,遍历整个参数空间的数组,找出计数器最大的元素,该元素对应的曲线即为图像中检测到的直线或圆。
二、霍夫变换的优点和缺点霍夫变换算法在图像处理领域中有以下优点:1. 对图像噪声不敏感:霍夫变换算法能够在噪声存在的情况下进行图像处理,而且处理后的结果不会受到噪声的影响。
2. 能够检测多条直线:霍夫变换算法能够检测到图像中的多条直线,而且没有数量限制。
3. 能够检测特殊形状:霍夫变换算法能够检测到图像中的特殊形状,如圆、椭圆、曲线等。
但霍夫变换算法也有一些缺点:1. 计算复杂度高:由于需要遍历整个参数空间的数组,霍夫变换算法的计算复杂度较高。
2. 跟分辨率有关:霍夫变换算法需要适当地选择参数空间的分辨率,否则对于某些参数可能会漏检或误检。
圆检测 cht算法

圆检测 cht算法
圆检测是计算机视觉和图像处理中的一种常见技术,用于检测
图像中的圆形物体。
其中,CHT(霍夫变换)算法是一种经典的用于
检测圆的算法之一。
霍夫变换(Hough Transform)是一种在图像处理中用于检测几
何形状的技术。
CHT算法是霍夫变换的一种扩展,用于检测圆形物体。
它的基本思想是将图像空间中的像素点映射到参数空间中,以
便在参数空间中进行圆的检测。
CHT算法的步骤如下:
1. 边缘检测,首先对图像进行边缘检测,以便找到可能包含圆
的边缘。
2. 参数空间,对于每个边缘点,根据其可能的圆心位置和半径,将其映射到参数空间中。
3. 投票,在参数空间中,对于每组圆心和半径的参数,统计投
票数,以确定哪些参数对应于图像中的实际圆。
4. 圆检测,根据投票结果,在图像中标记出检测到的圆。
从实现的角度来看,CHT算法的关键在于对参数空间的投票统计和圆的检测。
在实际应用中,还需要考虑参数空间的离散化、投票阈值的选择以及对噪声和局部最大值的处理等问题。
此外,CHT算法也有一些局限性,例如对噪声敏感、对参数空间的离散化要求较高等。
因此,在实际应用中,可能需要结合其他技术和优化手段来提高圆检测的准确性和鲁棒性。
总的来说,CHT算法是一种经典的圆检测算法,通过在参数空间中进行投票统计来检测圆形物体,但在实际应用中需要综合考虑算法的实现细节和局限性。
opencv霍夫圆检测原理

opencv霍夫圆检测原理
霍夫圆检测是一种用于检测图像中圆形的图像处理算法。
OpenCV是一个开源
的计算机视觉库,提供了许多功能强大的工具和算法,其中包括霍夫圆检测算法。
霍夫圆检测算法的原理是基于霍夫变换的思想。
霍夫变换是一种将坐标从图像
空间转换到参数空间的数学变换。
对于霍夫圆检测,我们需要考虑以下几个参数:
1. 圆心的坐标 (x, y)。
2. 圆的半径 r。
算法的核心思想是在参数空间中,对于每个给定的像素点,我们遍历所有可能
的圆心坐标和半径组合,检查这个圆是否与图像中其他边缘点匹配。
如果匹配成功,则这个圆在参数空间上对应的位置加1。
在实际应用中,我们通常会在图像上进行边缘检测,例如使用Canny边缘检测
算法。
然后,对于检测到的边缘点,我们使用霍夫圆检测算法来寻找与之匹配的圆。
OpenCV提供了一个函数`HoughCircles`来实现霍夫圆检测。
这个函数需要输入
一个二值图像(通常为边缘检测后的图像),以及一些其他参数,如最小和最大半径、圆心间的最小距离等。
除了霍夫圆检测算法,OpenCV还提供了其他基于霍夫变换的检测算法,例如
霍夫直线检测、霍夫椭圆检测等。
这些算法都是非常有用的工具,在计算机视觉和图像处理领域中得到广泛应用。
总结起来,霍夫圆检测是一种有效的图像处理算法,可以用于检测图像中的圆形。
OpenCV提供了方便的函数来实现这一算法,使我们能够轻松地在应用中使用它。
圆环检测算法范文

圆环检测算法范文圆环通常由内外两个圆组成,内圆和外圆的半径可以不同。
圆环检测算法的主要目标是找到图像中存在的圆环,并给出其位置和半径。
下面介绍一种常用的圆环检测算法:霍夫变换(Hough Transform)。
1.图像预处理:首先,将彩色图像转换为灰度图像,这样有利于后续的处理。
然后,进行图像平滑处理,使用高斯滤波器去除图像中的噪声,使得检测结果更加准确。
2. 边缘检测:利用边缘检测算法,例如Canny边缘检测算法,从图像中提取出所有的边缘信息。
边缘通常是由圆环的轮廓形成的。
3.霍夫变换圆检测:霍夫变换是一种常用的图形处理算法,可以检测二维图像中的各种形状,包括圆形。
在圆环检测中,我们需要使用霍夫变换圆检测算法,来检测图像中的圆环。
霍夫变换圆检测算法的基本思想是,在图像中所有可能的圆,并统计通过圆心的点的数量。
具体步骤如下:-初始化参数:设置最小和最大半径范围,以及圆心的步长。
-在图像中遍历每一个像素,对于每一个边缘点,分别在指定半径范围内圆心,并统计通过圆心的边缘点数量。
-根据统计结果,选择具有最大值的圆心和半径作为检测结果。
-如果存在多个圆环,迭代进行上述步骤。
4.圆心和半径精化:通过最小二乘法或其他优化方法,对检测到的圆心和半径进行精化,提高定位的准确性。
5.绘制检测结果:将检测到的圆心和半径在原始图像上进行标记,以便于可视化和后续处理。
除了霍夫变换,还有其他一些常用的圆环检测算法,例如基于模板匹配的方法、梯度变换方法等。
不同的算法适用于不同的场景和需求。
总结起来,圆环检测算法是一种重要的计算机视觉算法,可以准确地检测和定位图像中的圆环。
其中霍夫变换是一种常用的圆检测算法,通过统计圆心和半径的数量,选择具有最大统计值的圆心和半径作为检测结果。
经过圆心和半径的精化处理,可以得到更加准确的定位结果。
圆环检测算法在很多领域有广泛的应用,例如机器人导航、工业检测、医学影像等。
圆检测算法

圆检测算法圆检测算法介绍圆检测算法是一种基于边缘检测的图像处理算法,用于在图像中自动检测出所有的圆形物体。
该算法可以应用于许多领域,如机器视觉、医学图像处理、工业自动化等。
原理圆检测算法的原理是基于霍夫变换(Hough Transform)和边缘检测。
首先通过边缘检测算法,将图像中的所有边缘提取出来,并将其表示为极坐标系下的点。
然后对每个点进行遍历,通过霍夫变换将其转化为一个参数空间中的曲线。
最后,在参数空间中找到所有能够拟合成圆形的曲线,即可得到图像中所有的圆。
具体步骤1. 边缘检测:使用常见的边缘检测算法(如Sobel、Canny)提取图像中的所有边缘,并将其表示为极坐标系下的点。
2. 参数空间:定义一个参数空间(Hough Space),用来表示所有可能成为圆心和半径组合(x,y,r)。
3. 霍夫变换:对于每个点(x_i,y_i),在参数空间中生成一个曲线L_i = {(x,y)| (x-x_i)^2 + (y-y_i)^2 = r^2},表示所有可能成为以该点为圆心的圆。
将所有点的曲线相加,得到参数空间中的总曲线。
4. 圆检测:在参数空间中寻找所有能够拟合成圆形的曲线。
这可以通过设定一个阈值来实现。
当某个点(x,y,r)在参数空间中对应的值超过阈值时,则认为该点对应一个圆。
5. 圆心和半径计算:根据参数空间中找到的圆心和半径信息,在原图像中画出所有检测到的圆。
应用圆检测算法广泛应用于机器视觉、医学图像处理、工业自动化等领域。
例如,在制造业中,可以使用该算法自动检测产品表面上的孔洞、凸起等特征;在医学图像处理中,可以使用该算法自动检测肿瘤等病变区域。
优缺点优点:1. 可以检测任意大小、位置和方向的圆形物体;2. 对于噪声和缺失数据具有较好的鲁棒性;3. 可以快速地处理大量数据。
缺点:1. 对于非圆形物体或非完整圆形物体的检测效果较差;2. 对于大量数据的处理需要较高的计算资源。
总结圆检测算法是一种基于边缘检测和霍夫变换的图像处理算法,可以自动检测出图像中所有的圆形物体。
图像处理之霍夫变换圆检测算法

图像处理之霍夫变换圆检测算法图像处理之霍夫变换圆检测算法之前写过⼀篇⽂章讲述霍夫变换原理与利⽤霍夫变换检测直线, 结果发现访问量还是蛮多,有点超出我的意料,很多⼈都留⾔说代码写得不好,没有注释,结构也不是很清晰,所以我萌发了再写⼀篇,介绍霍夫变换圆检测算法,同时也尽量的加上详细的注释,介绍代码结构.让更多的⼈能够读懂与理解.⼀:霍夫变换检测圆的数学原理根据极坐标,圆上任意⼀点的坐标可以表⽰为如上形式, 所以对于任意⼀个圆, 假设中⼼像素点p(x0, y0)像素点已知, 圆半径已知,则旋转360由极坐标⽅程可以得到每个点上得坐标同样,如果只是知道图像上像素点, 圆半径,旋转360°则中⼼点处的坐标值必定最强.这正是霍夫变换检测圆的数学原理.⼆:算法流程该算法⼤致可以分为以下⼏个步骤三:运⾏效果图像从空间坐标变换到极坐标效果, 最亮⼀点为圆⼼.图像从极坐标变换回到空间坐标,检测结果显⽰:四:关键代码解析个⼈觉得这次注释已经是⾮常的详细啦,⽽且我写的还是中⽂注释/*** 霍夫变换处理 - 检测半径⼤⼩符合的圆的个数* 1. 将图像像素从2D空间坐标转换到极坐标空间* 2. 在极坐标空间中归⼀化各个点强度,使之在0〜255之间* 3. 根据极坐标的R值与输⼊参数(圆的半径)相等,寻找2D空间的像素点* 4. 对找出的空间像素点赋予结果颜⾊(红⾊)* 5. 返回结果2D空间像素集合* @return int []*/public int[] process() {// 对于圆的极坐标变换来说,我们需要360度的空间梯度叠加值acc = new int[width * height];for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {acc[y * width + x] = 0;}}int x0, y0;double t;for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {if ((input[y * width + x] & 0xff) == 255) {for (int theta = 0; theta < 360; theta++) {t = (theta * 3.14159265) / 180; // ⾓度值0 ~ 2*PIx0 = (int) Math.round(x - r * Math.cos(t));y0 = (int) Math.round(y - r * Math.sin(t));if (x0 < width && x0 > 0 && y0 < height && y0 > 0) {acc[x0 + (y0 * width)] += 1;}}}}}// now normalise to 255 and put in format for a pixel arrayint max = 0;// Find max acc valueif (acc[x + (y * width)] > max) {max = acc[x + (y * width)];}}}// 根据最⼤值,实现极坐标空间的灰度值归⼀化处理int value;for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {value = (int) (((double) acc[x + (y * width)] / (double) max) * 255.0); acc[x + (y * width)] = 0xff000000 | (value << 16 | value << 8 | value); }}// 绘制发现的圆findMaxima();System.out.println("done");return output;}完整的算法源代码, 已经全部的加上注释package com.gloomyfish.image.transform.hough;/***** 传⼊的图像为⼆值图像,背景为⿊⾊,⽬标前景颜⾊为为⽩⾊* @author gloomyfish**/public class CircleHough {private int[] input;private int[] output;private int width;private int height;private int[] acc;private int accSize = 1;private int[] results;private int r; // 圆周的半径⼤⼩public CircleHough() {System.out.println("Hough Circle Detection...");}public void init(int[] inputIn, int widthIn, int heightIn, int radius) {r = radius;width = widthIn;height = heightIn;input = new int[width * height];output = new int[width * height];input = inputIn;for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {output[x + (width * y)] = 0xff000000; //默认图像背景颜⾊为⿊⾊}}}public void setCircles(int circles) {accSize = circles; // 检测的个数}/*** 霍夫变换处理 - 检测半径⼤⼩符合的圆的个数* 1. 将图像像素从2D空间坐标转换到极坐标空间* 2. 在极坐标空间中归⼀化各个点强度,使之在0〜255之间* 3. 根据极坐标的R值与输⼊参数(圆的半径)相等,寻找2D空间的像素点 * 4. 对找出的空间像素点赋予结果颜⾊(红⾊)* 5. 返回结果2D空间像素集合* @return int []*/public int[] process() {// 对于圆的极坐标变换来说,我们需要360度的空间梯度叠加值acc = new int[width * height];acc[y * width + x] = 0;}}int x0, y0;double t;for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {if ((input[y * width + x] & 0xff) == 255) {for (int theta = 0; theta < 360; theta++) {t = (theta * 3.14159265) / 180; // ⾓度值0 ~ 2*PIx0 = (int) Math.round(x - r * Math.cos(t));y0 = (int) Math.round(y - r * Math.sin(t));if (x0 < width && x0 > 0 && y0 < height && y0 > 0) {acc[x0 + (y0 * width)] += 1;}}}}}// now normalise to 255 and put in format for a pixel arrayint max = 0;// Find max acc valuefor (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {if (acc[x + (y * width)] > max) {max = acc[x + (y * width)];}}}// 根据最⼤值,实现极坐标空间的灰度值归⼀化处理int value;for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {value = (int) (((double) acc[x + (y * width)] / (double) max) * 255.0); acc[x + (y * width)] = 0xff000000 | (value << 16 | value << 8 | value); }}// 绘制发现的圆findMaxima();System.out.println("done");return output;}private int[] findMaxima() {results = new int[accSize * 3];int[] output = new int[width * height];// 获取最⼤的前accSize个值for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {int value = (acc[x + (y * width)] & 0xff);// if its higher than lowest value add it and then sortif (value > results[(accSize - 1) * 3]) {// add to bottom of arrayresults[(accSize - 1) * 3] = value; //像素值results[(accSize - 1) * 3 + 1] = x; // 坐标Xresults[(accSize - 1) * 3 + 2] = y; // 坐标Y// shift up until its in right placeint i = (accSize - 2) * 3;while ((i >= 0) && (results[i + 3] > results[i])) {for (int j = 0; j < 3; j++) {int temp = results[i + j];results[i + j] = results[i + 3 + j];results[i + 3 + j] = temp;}i = i - 3;if (i < 0)break;}}}// 根据找到的半径R,中⼼点像素坐标p(x, y),绘制圆在原图像上System.out.println("top " + accSize + " matches:");for (int i = accSize - 1; i >= 0; i--) {drawCircle(results[i * 3], results[i * 3 + 1], results[i * 3 + 2]);}return output;}private void setPixel(int value, int xPos, int yPos) {/// output[(yPos * width) + xPos] = 0xff000000 | (value << 16 | value << 8 | value); output[(yPos * width) + xPos] = 0xffff0000;}// draw circle at x yprivate void drawCircle(int pix, int xCenter, int yCenter) {pix = 250; // 颜⾊值,默认为⽩⾊int x, y, r2;int radius = r;r2 = r * r;// 绘制圆的上下左右四个点setPixel(pix, xCenter, yCenter + radius);setPixel(pix, xCenter, yCenter - radius);setPixel(pix, xCenter + radius, yCenter);setPixel(pix, xCenter - radius, yCenter);y = radius;x = 1;y = (int) (Math.sqrt(r2 - 1) + 0.5);// 边缘填充算法,其实可以直接对循环所有像素,计算到做中⼼点距离来做// 这个⽅法是别⼈写的,发现超赞,超好!while (x < y) {setPixel(pix, xCenter + x, yCenter + y);setPixel(pix, xCenter + x, yCenter - y);setPixel(pix, xCenter - x, yCenter + y);setPixel(pix, xCenter - x, yCenter - y);setPixel(pix, xCenter + y, yCenter + x);setPixel(pix, xCenter + y, yCenter - x);setPixel(pix, xCenter - y, yCenter + x);setPixel(pix, xCenter - y, yCenter - x);x += 1;y = (int) (Math.sqrt(r2 - x * x) + 0.5);}if (x == y) {setPixel(pix, xCenter + x, yCenter + y);setPixel(pix, xCenter + x, yCenter - y);setPixel(pix, xCenter - x, yCenter + y);setPixel(pix, xCenter - x, yCenter - y);}}public int[] getAcc() {return acc;}}测试的UI类:package com.gloomyfish.image.transform.hough;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.image.BufferedImage;import java.io.File;import javax.imageio.ImageIO;import javax.swing.BorderFactory;import javax.swing.JButton;import javax.swing.JPanel;import javax.swing.JSlider;import javax.swing.event.ChangeEvent;import javax.swing.event.ChangeListener;public class HoughUI extends JFrame implements ActionListener, ChangeListener {/****/public static final String CMD_LINE = "Line Detection";public static final String CMD_CIRCLE = "Circle Detection";private static final long serialVersionUID = 1L;private BufferedImage sourceImage;// private BufferedImage houghImage;private BufferedImage resultImage;private JButton lineBtn;private JButton circleBtn;private JSlider radiusSlider;private JSlider numberSlider;public HoughUI(String imagePath){super("GloomyFish-Image Process Demo");try{File file = new File(imagePath);sourceImage = ImageIO.read(file);} catch(Exception e){e.printStackTrace();}initComponent();}private void initComponent() {int RADIUS_MIN = 1;int RADIUS_INIT = 1;int RADIUS_MAX = 51;lineBtn = new JButton(CMD_LINE);circleBtn = new JButton(CMD_CIRCLE);radiusSlider = new JSlider(JSlider.HORIZONTAL, RADIUS_MIN, RADIUS_MAX, RADIUS_INIT);radiusSlider.setMajorTickSpacing(10);radiusSlider.setMinorTickSpacing(1);radiusSlider.setPaintTicks(true);radiusSlider.setPaintLabels(true);numberSlider = new JSlider(JSlider.HORIZONTAL, RADIUS_MIN, RADIUS_MAX, RADIUS_INIT);numberSlider.setMajorTickSpacing(10);numberSlider.setMinorTickSpacing(1);numberSlider.setPaintTicks(true);numberSlider.setPaintLabels(true);JPanel sliderPanel = new JPanel();sliderPanel.setLayout(new GridLayout(1, 2));sliderPanel.setBorder(BorderFactory.createTitledBorder("Settings:"));sliderPanel.add(radiusSlider);sliderPanel.add(numberSlider);JPanel btnPanel = new JPanel();btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));btnPanel.add(lineBtn);btnPanel.add(circleBtn);JPanel imagePanel = new JPanel(){private static final long serialVersionUID = 1L;protected void paintComponent(Graphics g) {if(sourceImage != null){Graphics2D g2 = (Graphics2D) g;g2.drawImage(sourceImage, 10, 10, sourceImage.getWidth(), sourceImage.getHeight(),null);g2.setPaint(Color.BLUE);g2.drawString("原图", 10, sourceImage.getHeight() + 30);if(resultImage != null){g2.drawImage(resultImage, resultImage.getWidth() + 20, 10, resultImage.getWidth(), resultImage.getHeight(), null); g2.drawString("最终结果,红⾊是检测结果", resultImage.getWidth() + 40, sourceImage.getHeight() + 30);}}}};this.getContentPane().setLayout(new BorderLayout());this.getContentPane().add(sliderPanel, BorderLayout.NORTH);this.getContentPane().add(btnPanel, BorderLayout.SOUTH);// setup listenerthis.lineBtn.addActionListener(this);this.circleBtn.addActionListener(this);this.numberSlider.addChangeListener(this);this.radiusSlider.addChangeListener(this);}public static void main(String[] args){String filePath = System.getProperty ("user.home") + "/Desktop/" + "zhigang/hough-test.png";HoughUI frame = new HoughUI(filePath);// HoughUI frame = new HoughUI("D:\\image-test\\lines.png");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setPreferredSize(new Dimension(800, 600));frame.pack();frame.setVisible(true);}@Overridepublic void actionPerformed(ActionEvent e) {if(e.getActionCommand().equals(CMD_LINE)){HoughFilter filter = new HoughFilter(HoughFilter.LINE_TYPE);resultImage = filter.filter(sourceImage, null);this.repaint();}else if(e.getActionCommand().equals(CMD_CIRCLE)){HoughFilter filter = new HoughFilter(HoughFilter.CIRCLE_TYPE);resultImage = filter.filter(sourceImage, null);// resultImage = filter.getHoughSpaceImage(sourceImage, null);this.repaint();}}@Overridepublic void stateChanged(ChangeEvent e) {// TODO Auto-generated method stub}}五:霍夫变换检测圆与直线的图像预处理使⽤霍夫变换检测圆与直线时候,⼀定要对图像进⾏预处理,灰度化以后,提取图像的边缘使⽤⾮最⼤信号压制得到⼀个像素宽的边缘, 这个步骤对霍夫变换⾮常重要.否则可能导致霍夫变换检测的严重失真.第⼀次⽤Mac发博⽂,编辑不好请见谅!。
matlab霍夫变换检测圆

MATLAB霍夫变换检测圆1. 引言霍夫变换是一种在图像处理中常用的技术,它可以用于检测图像中的直线、圆等形状。
本文将介绍如何使用MATLAB中的霍夫变换函数来检测图像中的圆。
2. 霍夫变换原理霍夫变换是一种基于数学原理的图像处理方法,它可以将图像中的点映射到参数空间中,并通过对参数空间的分析来检测出图像中存在的特定形状。
对于圆的检测,我们需要定义一个二维参数空间,其中两个参数分别表示圆心的横坐标和纵坐标,而第三个参数表示圆的半径。
对于每个图像点,我们可以遍历所有可能的圆心和半径组合,并在参数空间中增加相应位置上的计数器。
通过遍历所有图像点,并在参数空间中增加计数器后,我们可以找到在参数空间中计数最高的位置,该位置对应于最有可能是圆心和半径组合。
因此,通过对参数空间进行分析,我们可以找到图像中存在的圆。
3. MATLAB实现MATLAB提供了houghcircles函数来实现霍夫变换检测圆。
该函数需要输入图像和一些参数,并返回检测到的圆的信息。
首先,我们需要读取图像并将其转换为灰度图像。
通过以下代码可以实现:img = imread('image.jpg');gray_img = rgb2gray(img);接下来,我们可以使用houghcircles函数来检测图像中的圆。
该函数需要指定一些参数,例如霍夫变换的灵敏度、最小半径和最大半径等。
以下是一个示例代码:sensitivity = 0.9;min_radius = 10;max_radius = 50;[centers, radii, metric] = houghcircles(gray_img, 'Sensitivity', sensitivity, 'MinRadius', min_radius, 'MaxRadius', max_radius);在上述代码中,centers是一个包含检测到的圆心坐标的矩阵,radii是一个包含检测到的圆半径的向量,metric是一个包含每个圆的强度值(表示检测到的可信度)的向量。
圆形检测和中心提取算法

圆形检测和中心提取算法
圆形检测和中心提取是图像处理中的一个常见任务,以下是一个基于霍夫变换的圆形检测和中心提取算法的简要概述:
基于霍夫变换的圆形检测:
边缘检测:使用图像处理技术(如Canny边缘检测)找到图像中的边缘。
霍夫变换:对于每个边缘点,利用霍夫变换在参数空间中寻找可能的圆心和半径。
霍夫变换会累加通过每个边缘点的所有可能圆的参数。
投票和阈值:对霍夫变换的结果进行投票,找到投票数最高的圆。
设定阈值以过滤掉低投票的圆。
圆形检测:通过霍夫变换找到的圆心和半径进行圆形检测。
中心提取:
圆形检测结果:从上述步骤中得到的圆形检测结果,包括圆心和半径。
中心提取:根据圆心和半径信息,提取圆的中心坐标。
可选后处理:可以进行一些后处理步骤,例如去除重复的中心、滤除离散点等。
这只是基于霍夫变换的一种常见方法。
除此之外,也有其他方法,比如基于梯度信息的方法,例如基于梯度的圆形检测(Gradient-Based Circular Object Detection, GCOD)等。
在实际应用中,具体的算法选择取决于图像特性、噪声情况以及需要满足的应用需求。
1。
霍夫圆检测 matlab

霍夫圆检测 matlab一、什么是霍夫圆检测?霍夫圆检测是一种基于霍夫变换的图像处理技术,用于检测图像中的圆形物体。
它通过在极坐标空间中对圆心和半径进行投票来检测圆形物体,从而实现对图像中圆形物体的识别和定位。
二、霍夫圆检测的原理1. 极坐标系下的表示方法在直角坐标系下,一个圆可以表示为(x-a)²+(y-b)²=r²,其中a,b为圆心坐标,r为半径。
但这种表示方法不方便进行霍夫变换。
因此,在极坐标系下,一个圆可以表示为:x=a+r*cosθy=b+r*sinθ其中a,b为圆心坐标,r为半径,θ为极角。
2. 霍夫变换在直角坐标系下进行霍夫变换时,每个点都会在Hough空间中投出一条直线。
同样地,在极坐标系下进行霍夫变换时,每个点都会在Hough空间中投出一个圆。
具体来说,在极坐标系下进行霍夫变换时,需要对每个点进行以下操作:(1)确定该点所属的所有可能的圆心位置。
(2)对于每个圆心位置,确定该点可能对应的所有半径。
(3)在Hough空间中对这些圆心和半径进行投票。
最终,在Hough空间中得到投票数最多的圆心和半径即为所检测到的圆形物体的位置和大小。
三、在Matlab中实现霍夫圆检测Matlab提供了一个函数houghcircles,用于实现霍夫圆检测。
该函数需要输入以下参数:1. 图像:需要进行霍夫圆检测的图像。
2. 半径范围:需要检测的圆形物体的半径范围,以[minRadius,maxRadius]表示。
3. 阈值:投票数阈值,只有得票数大于该阈值的圆才会被认为是有效的圆形物体。
默认值为0.5*max(max(acc)),其中acc为Hough空间中每个点的投票数矩阵。
4. 边缘检测算子:用于提取图像边缘的算子。
默认值为'canny'。
5. 梯度阈值:边缘梯度阈值,只有梯度大于该阈值的像素才会被认为是边缘像素。
默认值为0.2*max(max(gradmag)),其中gradmag为图像梯度矩阵。
霍夫圆算法

Hough Transform是一种图像处理技术,用于检测图像中的圆圈。
霍夫圆变换是霍夫变换算法的变体,专为检测图像中的圆而设计。
它可用于检测任何大小的圆圈,但对于检测小或部分模糊的圆圈特别有用。
霍夫圆变换背后的基本思想是将图像中的每个点表示为参数空间中的正弦曲线。
正弦曲线由以下方程定义:x = x0 + r * cos(θ)y = y0 + r * sin(θ)其中(x0,y0)是圆的中心,r是半径,θ是点相对于圆中心的角度。
通过分析这些正弦曲线,可以检测到图像中存在圆圈。
Hough Circle Transform算法的工作原理是首先将图像转换为二进制格式,将圆的一部分像素设置为1,所有其他像素设置为0。
然后,对于设置为1的每个像素,该算法将计算一系列可能的圆中心和半径的正弦曲线。
这些正弦曲线在参数空间中的交集对应于可能的圆中心。
最后,算法将选择参数空间中交集最多的圆,这些圆被认为是图像中的真实圆。
值得注意的是,该算法对噪声很敏感,可能会产生假阳性,因此它通常与其他算法结合使用图像处理技术以提高其准确性。
一些可用于提高霍夫圆变换性能的方法包括预处理图像以消除噪声,在参数空间中使用更高级的投票方案,以及应用阈值来消除弱检测。
还值得注意的是,霍夫圆变换算法有不同的变体,例如广义霍夫变换,可用于检测椭圆等其他形状,以及渐进概率霍夫变换,这是霍夫圆变换算法的更有效变体。
总之,霍夫圆变换是霍夫变换算法的变体,用于检测图像中的圆。
它的工作原理是将图像中的每个点表示为参数空间中的正弦曲线,并分析这些正弦曲线的交集,以检测圆的存在。
虽然它是一种强大的技术,但它可能对噪音敏感,因此它经常与其他图像处理技术结合使用,以提高其准确性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图像处理之霍夫变换圆检测算法一:霍夫变换检测圆的数学原理根据极坐标,圆上任意一点的坐标可以表示为如上形式, 所以对于任意一个圆, 假设中心像素点p(x0, y0)像素点已知, 圆半径已知,则旋转360由极坐标方程可以得到每个点上得坐标同样,如果只是知道图像上像素点, 圆半径,旋转360°则中心点处的坐标值必定最强.这正是霍夫变换检测圆的数学原理.二:算法流程该算法大致可以分为以下几个步骤三:运行效果图像从空间坐标变换到极坐标效果, 最亮一点为圆心.图像从极坐标变换回到空间坐标,检测结果显示:四:关键代码解析个人觉得这次注释已经是非常的详细啦,而且我写的还是中文注释[java]view plaincopy1./**2. * 霍夫变换处理 - 检测半径大小符合的圆的个数3. * 1. 将图像像素从2D空间坐标转换到极坐标空间4. * 2. 在极坐标空间中归一化各个点强度,使之在0〜255之间5. * 3. 根据极坐标的R值与输入参数(圆的半径)相等,寻找2D空间的像素点6. * 4. 对找出的空间像素点赋予结果颜色(红色)7. * 5. 返回结果2D空间像素集合8. * @return int []9. */10.public int[] process() {11.12.// 对于圆的极坐标变换来说,我们需要360度的空间梯度叠加值13. acc = new int[width * height];14.for (int y = 0; y < height; y++) {15.for (int x = 0; x < width; x++) {16. acc[y * width + x] = 0;17. }18. }19.int x0, y0;20.double t;21.for (int x = 0; x < width; x++) {22.for (int y = 0; y < height; y++) {23.24.if ((input[y * width + x] & 0xff) == 255) {25.26.for (int theta = 0; theta < 360; theta++) {27. t = (theta * 3.14159265) / 180; // 角度值0 ~ 2*PI28. x0 = (int) Math.round(x - r * Math.cos(t));29. y0 = (int) Math.round(y - r * Math.sin(t));30.if (x0 < width && x0 > 0 && y0 < height && y0 > 0) {31. acc[x0 + (y0 * width)] += 1;32. }33. }34. }35. }36. }37.38.// now normalise to 255 and put in format for a pixel array39.int max = 0;40.41.// Find max acc value42.for (int x = 0; x < width; x++) {43.for (int y = 0; y < height; y++) {44.45.if (acc[x + (y * width)] > max) {46. max = acc[x + (y * width)];47. }48. }49. }50.51.// 根据最大值,实现极坐标空间的灰度值归一化处理52.int value;53.for (int x = 0; x < width; x++) {54.for (int y = 0; y < height; y++) {55. value = (int) (((double) acc[x + (y * width)] / (double) max) *255.0);56. acc[x + (y * width)] = 0xff000000 | (value << 16 | value << 8 |value);57. }58. }59.60.// 绘制发现的圆61. findMaxima();62. System.out.println("done");63.return output;64.}完整的算法源代码, 已经全部的加上注释[java]view plaincopy1.package com.gloomyfish.image.transform.hough;2./***3. *4. * 传入的图像为二值图像,背景为黑色,目标前景颜色为为白色5. * @author gloomyfish6. *7. */8.public class CircleHough {9.10.private int[] input;11.private int[] output;12.private int width;13.private int height;14.private int[] acc;15.private int accSize = 1;16.private int[] results;17.private int r; // 圆周的半径大小18.19.public CircleHough() {20. System.out.println("Hough Circle Detection...");21. }22.23.public void init(int[] inputIn, int widthIn, int heightIn, int radius) {24. r = radius;25. width = widthIn;26. height = heightIn;27. input = new int[width * height];28. output = new int[width * height];29. input = inputIn;30.for (int y = 0; y < height; y++) {31.for (int x = 0; x < width; x++) {32. output[x + (width * y)] = 0xff000000; //默认图像背景颜色为黑色33. }34. }35. }36.37.public void setCircles(int circles) {38. accSize = circles; // 检测的个数39. }40.41./**42. * 霍夫变换处理 - 检测半径大小符合的圆的个数43. * 1. 将图像像素从2D空间坐标转换到极坐标空间44. * 2. 在极坐标空间中归一化各个点强度,使之在0〜255之间45. * 3. 根据极坐标的R值与输入参数(圆的半径)相等,寻找2D空间的像素点46. * 4. 对找出的空间像素点赋予结果颜色(红色)47. * 5. 返回结果2D空间像素集合48. * @return int []49. */50.public int[] process() {51.52.// 对于圆的极坐标变换来说,我们需要360度的空间梯度叠加值53. acc = new int[width * height];54.for (int y = 0; y < height; y++) {55.for (int x = 0; x < width; x++) {56. acc[y * width + x] = 0;57. }58. }59.int x0, y0;60.double t;61.for (int x = 0; x < width; x++) {62.for (int y = 0; y < height; y++) {63.64.if ((input[y * width + x] & 0xff) == 255) {65.66.for (int theta = 0; theta < 360; theta++) {67. t = (theta * 3.14159265) / 180; // 角度值0 ~ 2*PI68. x0 = (int) Math.round(x - r * Math.cos(t));69. y0 = (int) Math.round(y - r * Math.sin(t));70.if (x0 < width && x0 > 0 && y0 < height && y0 > 0) {71. acc[x0 + (y0 * width)] += 1;72. }73. }74. }75. }76. }77.78.// now normalise to 255 and put in format for a pixel array79.int max = 0;80.81.// Find max acc value82.for (int x = 0; x < width; x++) {83.for (int y = 0; y < height; y++) {84.85.if (acc[x + (y * width)] > max) {86. max = acc[x + (y * width)];87. }88. }89. }90.91.// 根据最大值,实现极坐标空间的灰度值归一化处理92.int value;93.for (int x = 0; x < width; x++) {94.for (int y = 0; y < height; y++) {95. value = (int) (((double) acc[x + (y * width)] / (double) max) * 255.0);96. acc[x + (y * width)] = 0xff000000 | (value << 16 | value <<8 | value);97. }98. }99.100.// 绘制发现的圆101. findMaxima();102. System.out.println("done");103.return output;104. }105.106.private int[] findMaxima() {107. results = new int[accSize * 3];108.int[] output = new int[width * height];109.110.// 获取最大的前accSize个值111.for (int x = 0; x < width; x++) {112.for (int y = 0; y < height; y++) {113.int value = (acc[x + (y * width)] & 0xff);114.115.// if its higher than lowest value add it and then sort 116.if (value > results[(accSize - 1) * 3]) {117.118.// add to bottom of array119. results[(accSize - 1) * 3] = value; //像素值120. results[(accSize - 1) * 3 + 1] = x; // 坐标X121. results[(accSize - 1) * 3 + 2] = y; // 坐标Y122.123.// shift up until its in right place124.int i = (accSize - 2) * 3;125.while ((i >= 0) && (results[i + 3] > results[i])) { 126.for (int j = 0; j < 3; j++) {127.int temp = results[i + j];128. results[i + j] = results[i + 3 + j];129. results[i + 3 + j] = temp;130. }131. i = i - 3;132.if (i < 0)133.break;134. }135. }136. }137. }138.139.// 根据找到的半径R,中心点像素坐标p(x, y),绘制圆在原图像上140. System.out.println("top " + accSize + " matches:");141.for (int i = accSize - 1; i >= 0; i--) {142. drawCircle(results[i * 3], results[i * 3 + 1], results[i * 3 + 2]);143. }144.return output;145. }146.147.private void setPixel(int value, int xPos, int yPos) {148./// output[(yPos * width) + xPos] = 0xff000000 | (value << 16 | val ue << 8 | value);149. output[(yPos * width) + xPos] = 0xffff0000;150. }151.152.// draw circle at x y153.private void drawCircle(int pix, int xCenter, int yCenter) { 154. pix = 250; // 颜色值,默认为白色155.156.int x, y, r2;157.int radius = r;158. r2 = r * r;159.160.// 绘制圆的上下左右四个点161. setPixel(pix, xCenter, yCenter + radius);162. setPixel(pix, xCenter, yCenter - radius);163. setPixel(pix, xCenter + radius, yCenter);164. setPixel(pix, xCenter - radius, yCenter);165.166. y = radius;167. x = 1;168. y = (int) (Math.sqrt(r2 - 1) + 0.5);169.170.// 边缘填充算法,其实可以直接对循环所有像素,计算到做中心点距离来做171.// 这个方法是别人写的,发现超赞,超好!172.while (x < y) {173. setPixel(pix, xCenter + x, yCenter + y);174. setPixel(pix, xCenter + x, yCenter - y);175. setPixel(pix, xCenter - x, yCenter + y);176. setPixel(pix, xCenter - x, yCenter - y);177. setPixel(pix, xCenter + y, yCenter + x);178. setPixel(pix, xCenter + y, yCenter - x);179. setPixel(pix, xCenter - y, yCenter + x);180. setPixel(pix, xCenter - y, yCenter - x);181. x += 1;182. y = (int) (Math.sqrt(r2 - x * x) + 0.5);183. }184.if (x == y) {185. setPixel(pix, xCenter + x, yCenter + y);186. setPixel(pix, xCenter + x, yCenter - y);187. setPixel(pix, xCenter - x, yCenter + y);188. setPixel(pix, xCenter - x, yCenter - y);189. }190. }191.192.public int[] getAcc() {193.return acc;194. }195.196.}测试的UI类:[java]view plaincopy1.package com.gloomyfish.image.transform.hough;2.3.import java.awt.BorderLayout;4.import java.awt.Color;5.import java.awt.Dimension;6.import java.awt.FlowLayout;7.import java.awt.Graphics;8.import java.awt.Graphics2D;9.import java.awt.GridLayout;10.import java.awt.event.ActionEvent;11.import java.awt.event.ActionListener;12.import java.awt.image.BufferedImage;13.import java.io.File;14.15.import javax.imageio.ImageIO;16.import javax.swing.BorderFactory;17.import javax.swing.JButton;18.import javax.swing.JFrame;19.import javax.swing.JPanel;20.import javax.swing.JSlider;21.import javax.swing.event.ChangeEvent;22.import javax.swing.event.ChangeListener;23.24.public class HoughUI extends JFrame implements ActionListener, ChangeListener {25./**26. *27. */28.public static final String CMD_LINE = "Line Detection";29.public static final String CMD_CIRCLE = "Circle Detection";30.private static final long serialVersionUID = 1L;31.private BufferedImage sourceImage;32.// private BufferedImage houghImage;33.private BufferedImage resultImage;34.private JButton lineBtn;35.private JButton circleBtn;36.private JSlider radiusSlider;37.private JSlider numberSlider;38.public HoughUI(String imagePath)39. {40.super("GloomyFish-Image Process Demo");41.try{42. File file = new File(imagePath);43. sourceImage = ImageIO.read(file);44. } catch(Exception e){45. e.printStackTrace();46. }47. initComponent();48. }49.50.private void initComponent() {51.int RADIUS_MIN = 1;52.int RADIUS_INIT = 1;53.int RADIUS_MAX = 51;54. lineBtn = new JButton(CMD_LINE);55. circleBtn = new JButton(CMD_CIRCLE);56. radiusSlider = new JSlider(JSlider.HORIZONTAL, RADIUS_MIN, RADIUS_MAX, RADIUS_INIT);57. radiusSlider.setMajorTickSpacing(10);58. radiusSlider.setMinorTickSpacing(1);59. radiusSlider.setPaintTicks(true);60. radiusSlider.setPaintLabels(true);61. numberSlider = new JSlider(JSlider.HORIZONTAL, RADIUS_MIN, RADIUS_MAX, RADIUS_INIT);62. numberSlider.setMajorTickSpacing(10);63. numberSlider.setMinorTickSpacing(1);64. numberSlider.setPaintTicks(true);65. numberSlider.setPaintLabels(true);66.67. JPanel sliderPanel = new JPanel();68. sliderPanel.setLayout(new GridLayout(1, 2));69. sliderPanel.setBorder(BorderFactory.createTitledBorder("Settings:"));70. sliderPanel.add(radiusSlider);71. sliderPanel.add(numberSlider);72. JPanel btnPanel = new JPanel();73. btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));74. btnPanel.add(lineBtn);75. btnPanel.add(circleBtn);76.77.78. JPanel imagePanel = new JPanel(){79.80.private static final long serialVersionUID = 1L;81.82.protected void paintComponent(Graphics g) {83.if(sourceImage != null)84. {85. Graphics2D g2 = (Graphics2D) g;86. g2.drawImage(sourceImage, 10, 10, sourceImage.getWidth(), sourceImage.getHeight(),null);87. g2.setPaint(Color.BLUE);88. g2.drawString("原图", 10, sourceImage.getHeight() + 30);89.if(resultImage != null)90. {91. g2.drawImage(resultImage, resultImage.getWidth() + 20, 10, resultImage.getWidth(), resultImage.getHeight(), null);92. g2.drawString("最终结果,红色是检测结果", resultImage.getWidth() + 40, sourceImage.getHeight() + 30);93. }94. }95. }96.97. };98.this.getContentPane().setLayout(new BorderLayout());99.this.getContentPane().add(sliderPanel, BorderLayout.NORTH);100.this.getContentPane().add(btnPanel, BorderLayout.SOUTH);101.this.getContentPane().add(imagePanel, BorderLayout.CENTER);102.103.// setup listener104.this.lineBtn.addActionListener(this);105.this.circleBtn.addActionListener(this);106.this.numberSlider.addChangeListener(this);107.this.radiusSlider.addChangeListener(this);108. }109.110.public static void main(String[] args)111. {112. String filePath = System.getProperty ("user.home") + "/Desktop/" + "zhigang/hough-test.png";113. HoughUI frame = new HoughUI(filePath);114.// HoughUI frame = new HoughUI("D:\\image-test\\lines.png");115. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);116. frame.setPreferredSize(new Dimension(800, 600));117. frame.pack();118. frame.setVisible(true);119. }120.121.@Override122.public void actionPerformed(ActionEvent e) {123.if(e.getActionCommand().equals(CMD_LINE))124. {125. HoughFilter filter = new HoughFilter(HoughFilter.LINE_TYPE);126. resultImage = filter.filter(sourceImage, null);127.this.repaint();128. }129.else if(e.getActionCommand().equals(CMD_CIRCLE))130. {131. HoughFilter filter = new HoughFilter(HoughFilter.CIRCLE_TYPE);132. resultImage = filter.filter(sourceImage, null);133.// resultImage = filter.getHoughSpaceImage(sourceImage, null);134.this.repaint();135. }136.137. }138.139.@Override140.public void stateChanged(ChangeEvent e) {141.// TODO Auto-generated method stub142.143. }144.}五:霍夫变换检测圆与直线的图像预处理使用霍夫变换检测圆与直线时候,一定要对图像进行预处理,灰度化以后,提取图像的边缘使用非最大信号压制得到一个像素宽的边缘, 这个步骤对霍夫变换非常重要.否则可能导致霍夫变换检测的严重失真。