[MATLAB] 霍夫变换提取图像直线边界

注:本文参考了清华大学出版社《MATLAB在数字图像处理中的应用》,因原文代码有多处纰漏,故做少许修改并附上本人自己的理解。

1. 概要:

图像的Hough变换是一种图像特征提取的技术,通过投票法检测特定形状并提取,其方法是在参数空间中通过投票累加获得局部最大值,从而通过值得到符合特定形状的集合,该集合即为Hough变换结果。

在Hough变换中,主要是利用图像的特殊形状,按照指定的函数进行参数空间点的累加,每取到函数形状上的点则进行投票累加,最后通过参数限制获得需要统计的点并组成点的集合,此时即可得到最终的边界点。Hough变换多用于对直线、圆、椭圆形状的检测和提取。

2. 算法原理:

Hough变换的实质是方程的点的集合的提取,即首先确定参数坐标系,再确定图像的特征形状方程,然后在图像上以某检测点为原点,对周围点进行遍历取点,找到处于方程上的点的集合,并通过设定局限值去除特征不明显的集合,最终获得符合图像特征方程的点的集合,即为图像边界。Hough变换算法适用于所有能够用方程表达出的图像特征,而其算法的复杂度也随着图像特征方程的复杂度变化。

3. 算法过程:

(1)读入图像。在本文中读取彩色图像以在图像上标出边缘区域,修改本文中的代码,灰度图像也可提取边缘;
(2)使用LoG(Laplacian of the Gaussian)边缘检测算子粗提取图像边缘。LoG算法在边缘提取中使用很多,其提取效果好且算法简单,运行速度快;
(3)使用均值滤波去除图像中的噪点。LoG算子得到的图像容易存在噪点,使用均值滤波来去除噪点,使得图像边缘更加合理,在本例中以3x3图像范围进行均值滤波操作;
(4)二值化处理均值滤波图像以突出图像边缘。二值化处理的目的一是能够通过设定阈值来明显体现出图像边缘,二是易于进行Hough变换提取边缘;
(5)通过Hough变换提取图像边缘点并表示为集合。在MATLAB中,可以用元胞数组保存点的坐标形成点的集合,并通过投票法对方程上的点的数量累加,而在提取边缘时可通过阈值忽略投票法中方程上点数量少的集合,从而可以去除无法明显体现图像特征方程的点的集合;
(6)在图像上用红色标出提取的边缘。

4. 算法代码:

根据上述原理和过程,设计以下代码:

img = imread('img.jpg');		% 读入彩色图像
origin_img = img;			% 复制彩色原图以最后对边缘上色
img = rgb2gray(img);
img = im2double(img);   %将图像转换成为灰度double类型的图像
figure;
imshow(origin_img);
title('原图');

[m,n]=size(img);		% 得到图像大小行m,列n
for i=3:m-2
	for j=3:n-2		% 计算区域从图像(3,3)开始,到(m-2,n-2)结束
		% LoG算子粗提取图像边缘
		log_margin(i,j) = -img(i-2,j)-img(i-1,j-1)-2*img(i-1,j)-img(i-1,j+1)-img(i,j+2)-2*img(i,j-1)+16*img(i,j)-2*img(i,j+1)-img(i,j+2)-img(i+1,j-1)-2*img(i+1,j)-img(i+1,j+1)-img(i+2,j);
	end
end
figure;
imshow(log_margin);
title('LoG算子提取图像边缘');

% 均值滤波处理
[m,n]=size(log_margin);
for i=2:m-1
	for j=2:n-1
		% LoG算子粗提取边缘后,进行均值滤波去除噪声(3x3范围)
		smooth(i,j) = log_margin(i-1,j-1)+log_margin(i-1,j)+log_margin(i-1,j+1)+log_margin(i,j-1)+log_margin(i,j)+log_margin(i,j+1)+log_margin(i+1,j-1)+log_margin(i+1,j)+log_margin(i+1,j+1);
		smooth(i,j) = smooth(i,j)/9;
	end
end
figure;
imshow(smooth);
title('均值滤波处理后');

% 二值化处理
binary_img = im2uint8(smooth);  % 将均值滤波后的图像转换为uint8类型图像,即图像色彩范围[0,255]
[m,n]=size(binary_img);
for i=1:m
	for j=1:n
		if binary_img(i,j)>50   % 设置二值化的阈值为80
			binary_img(i,j) = 255;  % 超过阈值的设为白点
		else
			binary_img(i,j) = 0;    %小于阈值的设为黑点
		end
	end
end
figure;
imshow(binary_img);
title('二值化处理后');

% Hough变换检测,使用(a,p)参数空间(极坐标),a∈[0,180],p∈[0,2d]
angle = 180;		% 极坐标角度的值为0~180度
distance = round(sqrt(m^2+n^2));		% 图像对角线长度最大值distance,从而确定p的取值范围为[-distance,distance]
number_ap = zeros(angle,2*distance);		% 存储每个检测点(a,p)的个数
coordinate = cell(angle,2*distance);		% 用元胞数组存储每个检测点的坐标(i,j)
% 投票法检测边缘白点
for i = 1:m
	for j = 1:n		% 遍历二值化图像的每个点
		if(binary_img(i,j) == 255)		% 仅对于每一个白点边缘点进行检测
			for k = 1:angle
				% 对每个点从1~180度遍历,取得经过该点的所有直线的p值(产生选民)
				p = round(i*cos(pi*k/180)+j*sin(pi*k/180));
				% 若p大于0,则将点存储在坐标集合(distance,2*distance)空间(投票存储器),该集合点的极坐标θ∈[0,90]
				if(p > 0)
					number_ap(k,distance+p) = number_ap(k,distance+p)+1;		% 符合直线的点(a,p)数量加1
					coordinate{k,distance+p} = [coordinate{k,distance+p},[i,j]];		% 在点集合中存储该点坐标(i,j)
				else
					ap = abs(p)+1;		% 若p小于0,则将点存储在坐标集合(0,distance)空间,该集合点的极坐标θ∈[90180]
					number_ap(k,ap) = number_ap(k,ap)+1;		% 符合直线的点(a,p)数量加1
					coordinate{k,ap} = [coordinate{k,ap},[i,j]];		% 在点集合中存储该点坐标(i,j)
				end
			end
		end
	end
end
% 绘制图像边缘
for i = 1:angle
	for j = 1:distance*2		% 遍历累加器number_ap和点坐标coordinate
		if(number_ap(i,j)>35)		% 提取直线的阈值设为35
			point = coordinate{i,j};		%提取对应点坐标
            [m,n] = size(point);
			%对满足阈值条件的累加器单元中(a,p)对应的所有点进行操作
			for k = 1:number_ap(i,j)
				origin_img(point(2*k-1),point(2*k),1) = 255;		% 每个点R分量=255,G分量=0,B分量=0
				origin_img(point(2*k-1),point(2*k),2) = 0;
				origin_img(point(2*k-1),point(2*k),3) = 0;		% 为满足阈值要求的直线上的店赋红色
			end
		end
	end
end
figure;
imshow(origin_img);
title('Hough变换后在原图上绘制边界');

代码分析:
LoG算子(Laplace of Gaussian function),常用于图像边缘处理和二值化处理中,因为该算法需要图像为灰度图像,因此将读入的彩色图像转化成为double精度的灰度图像来处理。当然,该算法并非最好的边缘提取算法,也可用其他更优的边缘提取算法来完成更高精度的边缘提取。该算法具有的局限性是会产生虚假边缘(边缘过厚或者过薄),并且该算法会产生边缘周围噪点,需要进行滤波处理。

均值滤波的处理是为了过滤掉不够明显的边缘点以及图像噪点,以得到更加好的边缘图像。但这种操作会导致图像整体亮度降低,这点会对边缘的判断产生一些负面的影响。整体来看,均值滤波对一些复杂边缘图像的处理效果更好,能够去除不明显边缘点以避免误判,但其降低图像亮度会在一定程度上影响二值化判断。

二值化处理则是一种十分单一的边缘判断,通过设定像素点亮度阈值,判断图像的边缘点。这种判断方法自然会较大地受到阈值的影响以及图片自身亮度的影响。

在Hough变换检测中,本例以检测图像直线为主,因此选用的是直线方程,所遍历的是直线方程的斜率。然而在垂直坐标系中,若直线垂直于x轴,则k无意义,且当直线无限接近垂直时,k的值为无穷大或无穷小,这会导致算法遍历的问题。因此,考虑使用极坐标系,利用极坐标系的优点来完成算法遍历。

在极坐标系中,描述点的位置只需要确定点与原点连线的距离以及角度,而在一定画幅中,距离是有限的,角度从0-180度遍历即可相当于遍历了所有斜率的直线,这样做可以避免垂直坐标系的缺点。当遍历(0,90)度时表示直线斜率为正,遍历(90,180)度时表示斜率为负,将斜率为正和斜率为负的直线分成两个部分,通过投票法完成直线的选择。在本例的角度遍历中,是以步进为1度的方式遍历的,遍历精度相对而言已经足够。但若需要提高精度,则投票存储器的大小也会发生倍数变化,并且运行时间也会大大增加,因此在无精度要求时,没有必要提高精度。

投票法的作用其实就是为了确定边缘而使用的,图像通过LoG算子提取边缘后是存在较多边缘噪点的,不适合作为实际边缘图像,经过均值滤波器处理后,大多数边缘噪点亮度降低,但仍然有一定的颜色变化,经过二值化处理之后,大多数边缘噪点才被真正地消除,边缘得到突出,二值化的目的就是为了投票过程能够变得简便,只需要进行单一值的判断来选定坐标点。然而二值化的处理方式显得比较粗暴,可能会导致本该被消除的噪点得到加强,而消除这种不必要独立点的方式就是进行选择,也就是投票法选点,从而得到更加好的边缘数据。

在本例中,霍夫变换所选取的是简单二次函数,其作用是对某个被检测点的周围进行扫描,可类似于雷达扫描一样,扫到一个点即记录一次该点所在的斜率、坐标点、点的数目。当图像上的所有像素点都完成了扫描后用阀值条件限制点的数目来确定是否能看作为一条直线边缘。

5. 代码测试:

在本例的代码测试中,使用两种图像进行测试,一张是具有简单颜色和明显边缘的图像,一张是具有复杂变化颜色和复杂边缘的图像。

(一)简单颜色和明显边缘的图像:
img
上图是使用Word文档绘制的简单图像,具有简单的颜色和十分明显的边缘,可以较为充分考量代码的效果。
使用该图像运行代码可以得到下列几个图像:
在这里插入图片描述
可以看到,由LoG算子提取后的图像边缘噪点明显,不适合确定边缘点,因此需要削弱边缘噪点,进行均值滤波处理。
在这里插入图片描述
由上图可以看到,经过均值滤波处理后边缘噪点被明显削弱,但缺陷是部分边缘的强度也遭到明显削弱,这会影响后面二值化阀值的选取。
在这里插入图片描述
二值化处理后,大部分噪点被消除,边缘突出,但仍然存在少许噪点,并且由于滤波处理导致的部分边缘强度削弱,可以看到上图对应的位置也受到了较大影响,部分边缘像素点明显变少。
在这里插入图片描述
经过Hough变换之后在原图绘制边界,从图像中可以看到的是,Hough变换也能成功地选择出边缘并进行绘制。然而在本例中,因为这几个图像的边缘长度都较长而且不具备能进行票数阀值判断的标准,因此可以发现图像上仍然有保留到噪点。可以说投票法的缺陷也就在于此,就是难以找到比较明确的阀值去确定它是否是需要的边缘。但投票法也不失为一个比较简便的方法去判断直线。

(二)复杂颜色和复杂边缘的图像:
img
实际上,使用复杂颜色和复杂边缘的图像是毫无意义的,因为其图像边缘是非常复杂而且边缘点也是很多的,投票法在这里会完全失效。并且由于在本例中所选取的霍夫变换函数也仅仅是二次函数,对于曲线是无法做到拟合的,因此霍夫变换在这里也同样完全失效。最终便只有滤波和二值化处理产生了效果。
用该图像运行可以得到下列图像:
img
同样,使用LoG提取边缘后的图像存在较多的边缘噪点,这使得图像不够细致。需要进行均值滤波处理。
img
经过均值滤波处理后,图像边缘细节大大增加,但部分边缘强度遭到削弱。
img
二值化处理后,图像被生硬地分割成了两个颜色,同时由于阀值的设置带来了很多影响,边缘强度遭到削弱的部分边缘明显被消除掉了,这导致部分边缘缺失,图像细致程度反而下降。
img
从最终绘制出来的图像可以看出,正如前面所说,霍夫变换和投票法在这里已经完全失效,无法进行选择和判断。最终的效果则相当于由二值化图像而来。

6、霍夫变换的优劣:

(一)霍夫变换是通过函数拟合来完成边缘选择的,对于具有单一颜色、简单边缘以及已知函数的图像而言,霍夫变换能够更好地选择边缘;
(二)本例的算法中,非常重要的控制变量就是阀值,一个二值化的阀值,一个投票法的阀值。二值化阀值控制着图像的精细程度,投票法的阀值控制着选取的线的长度。
(三)霍夫变换不适合用于复杂颜色、复杂边缘的图像,这种图像都不适合进行函数拟合,霍夫变换会变得没有任何作用。

7. 总结:

提取图像边界的算法至今已经是越来越丰富了,而且很多算法都非常优秀,用途也不胜枚举。本例的霍夫变换也仅仅是简单算法,没有用到多少技巧和知识,这也仅仅是边界算法的一个简单的开始。

你可能感兴趣的:(MATLAB,MATLAB,图像算法,Hough变换,提取边界)