Hough变换实例 很清晰的
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数字图像处理第八次作业
实验内容
1、拍摄一张包含硬币、橡皮等物品的照片,通过Hough 变换检测出圆形的硬币个数并区分不同半径的硬币。最终计算出照片中的总钱数。
解:Hough 变换的实质是对图像进行坐标的变换,将图像空间的线条变为参数空间的聚集点,从而将原始图像中检测给定形状的曲线问题,变成寻找参数空间中的峰点的问题。
它不仅可以检测直线,而且可以很方便地检测圆、椭圆和抛物线等形状。由于这里需要检测圆形的硬币,所以下面给出检测圆的具体方法:
因为圆的图像空间方程为:222()()x a y b r -+-=,
我们需要通过Hough 变换,将图像空间(,)x y 对应到参数空间(,,)a b r ,然后对其进行累加完成检测。但是显然这种方法的计算量是非常大的,所以一般都是先对灰度图像进行边缘提取,利用边界像素的灰度梯度信息估计出下式中的角度θ,以此来降低计算量:
cos cos a x r b y r θ
θ=-*⎧⎨=-*⎩ (1)
一般在检测过程中需要对图像进行预处理,使得检测更加准确和容易。检测过程如下所示:
○
1真彩色图像转为灰度图像; ○
2去除噪声,进行中值滤波; ○
3转为二值图像,利用边缘算子进行图像边缘提取; ○
4最后进行图像的平滑和填充。 这里处理的图像并没有太多噪声,所以处理的时候略去了中值滤波的步骤,直接对边缘提取后的图像进行Hough 变换检测圆形。
根据式(1),我们需要对半径r 和角度θ进行搜索,所以这里应该首先设置半径和角度方向的搜索步长step_r 和step_angle ,接着给出半径搜索的最大和最小值,当然这两个数值需要根据经验来自己确定。最后就可以根据这些确定半径和角度的最大搜索次数。
由于Hough变换需要用到稀疏矩阵,也即首先得找到图像矩阵中的非零量,针对这些非零量进行进一步的处理。这个操作可以直接通过Matlab中的find语句来实现:
>> [rows, cols] = find(BW); %找出矩阵中的非零值
接着只需要根据式(1)计算出对应参数空间的参数a b
和,根据,a b的范围确定hough空间累加器hough_adder是否自增。
由于这里的图像中不止一个圆形,所以不能直接利用hough_adder中的最大值来确定半径,需要设置一定的阈值thre来确定一定半径的圆,当阈值设置合理后才可以找出图像中的圆。接着对阈值范围内的点进行搜索,当满足圆周内外各5个像素点时,该点可以认为是我们搜寻的圆上的点。对其相应的坐标赋1即可。
经过上述的步骤,便通过hough变换的思想将图像的中的圆给检测出来了。并且可以将圆心坐标和圆的半径都显示出来。
那接下来按照题目的意思是需要我们计算总的钱数,所以首先需要区分一元和五角的硬币,也就是区分圆的半径。由于这里我们设置搜索出来的圆的半径是逐渐递增的,所以只需要判断在两个相邻点之间圆的半径是否存在跳变即可。因为如果是不同的一元硬币,那么他们的半径即使相差一点也不会很多。这样我们便可以得出首先将圆分成两类(这里只考虑一元和五角的两种情况),然后在每一类中再寻找半径相似的圆位于不同坐标的个数,也就是同样面值的硬币的个数了。
可以通过如下代码实现:
从以上代码我们可以看出,这里只要当相邻两个半径相差超过5即可认定为
是不同的硬币了。
接着在相同的硬币中,通过循环搜索当前半径和之前像素点的半径,当横纵坐标相差都小于10的时候可以认为是同一个点,也即是同一个硬币,否则将硬币数加一。
最后通过统计得到的总硬币数计算出总钱数。
下面先给出具体代码:
clc,clear all
Image = imread('final.bmp');
imshow(Image),title('原始图像');
Gray = rgb2gray(Image);
bw = im2bw(Gray); % 先转为二值图像
BW = edge(bw); % 然后提取边缘
figure
imshow(BW),title('图像边缘);
step_r = 1; % 设定半径搜索步长
step_angle = 0.1; % 设定角度搜索步长
r_min = 50; % 最小半径和最大半径,确定搜索范围
r_max = 100;
thre = 0.8; % 设定阈值
%***************hough变换*********************************
[m, n] = size(BW);
Count_r = round((r_max-r_min)/step_r)+1; % °半径最大搜索次数
hough_adder = zeros(m, n, Count_r);
Count_angle = round(2*pi/step_angle); % 角度最大搜索次数
[rows, cols] = find(BW); % 找出矩阵中的非零值
count = size(rows); % 计算非零值的个数
for Count_Num = 1 : count
for Count_R = 1 : Count_r
for Count_Angle = 1 : Count_angle
a =
round(rows(Count_Num)-(r_min+(Count_R-1)*step_r)*cos(Count_Angle*step_angle ));
b =
round(cols(Count_Num)-(r_min+(Count_R-1)*step_r)*sin(Count_Angle*step_angle) );
isTrue = (a>0 && a<=m && b>0 && b<=n);
if(isTrue)
hough_adder(a,b,Count_R) = hough_adder(a,b,Count_R) + 1;
% 参数空间累加器加1
end
end