最近开始上计算机视觉的实验课,使用的软件是matlab。老师布置了一项给代码添加注释的作业,是有关于霍夫变换的。刚接触这个软件和它使用的语言,所以第一次花了一个下午才弄懂这些代码,觉得有纪念意义,所以就写了这篇文章。
代码及注释如下:
%%
% https://ww2.mathworks.cn/help/images/ref/houghlines.html(注释主要来自matlab帮助中心)
clc; %清除命令行窗口的内容
clear; %清除工作空间的内容
close all; %关闭所有的Figure窗口
%% 将图像读入工作区
filename = 'circuit'; %导入实验所需图像
im = imread([filename,'.jpg']); %实验所需图像格式为jpg,进行类型转换
%%
rotI = imrotate(im,33,'crop'); %图像im旋转33°,并对旋转后的图像进行裁剪,保持输出的
%图像rotI的尺寸和输入图像im的尺寸一样(参数‘crop’的作用)
BW = edge(rotI,'canny'); %使用 Canny 方法查找边缘,创建二值图像
%% 使用二值图像进行Hough变换
[H,T,R] = hough(BW);
%{
计算Hough变换
R(沿垂于线条的向量从原点到线条的距离)
T(x轴与该向量之间的角度,以°为单位)
H(参数空间矩阵,其行和列分别对应于R和T的值)
其中R = x*cos(T) + y*sin(T)
%}
imshow(H,[],'Xdata',T,'Ydata',R,'InitialMagnification','fit');
%{
显示Hough矩阵
使用 'InitialMagnification' 名称-值对组参数以‘fit’率显示图像
‘fit’以适应窗口显示
%}
xlabel('\theta'),ylabel('\rho'); %为横纵坐标加上标签,‘\ ’为希腊字母
axis on,axis normal,hold on;
%{
axis on 绘制曲面同时显示坐标区的线条和背景
axis normal 将图框纵横比模式和数据纵横比模式的属性设置为自动
hold on 保留当前坐标区中的绘图,从而使新添加到坐标区中的绘图不会删除现有绘图
%}
%% 查找图像的Hough变换中的峰值
P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
%{
在霍夫矩阵H中找到5个极值点,阈值为H中最大值乘以0.3
只有超过该阈值才会被认定为一条符合条件的直线,在图像中表现为一个点。
对于极值点的理解,肉眼上越亮的点其值越大(不一定完全准确)。
这些点亮的原因在于:二维坐标点转换为这种类似于极坐标系后通过该点的曲线数目更多
参考资料来源:https://blog.csdn.net/YuYunTan/article/details/80141392
P为这些符合条件的坐标的集合,但P的形式为矩阵
%}
x = T(P(:,2)); y = R(P(:,1));
%{
x为矩阵P第二列全部坐标的角度值,y为矩阵P的第一列全部坐标的距离值。
我的理解:P和R类似于其他语言中的强制类型转换。(这个比喻其实不恰当,但是一时半会不知道怎么解释)
参考资料来源:https://zhidao.baidu.com/question/314711017.html
%}
plot(x,y,'s','color','white'); %绘制二维线图,坐标点形状为方形(‘s’),颜色为白色
%% 查找线条并对其绘画
lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
%{
houghlines函数可以找出标准霍夫变换的二值图像线条,其基于霍夫变换
BW是8位的单通道二进制图像
'FillGap'是一个正实数,表示同一图像中两条线段的距离。当两条线的距离小于指定值时,houghlines函数就会将这两条线合并为一条线。(这里FillGap的值为5)
'MinLength'是一个正实数,用来确定是否保存线条的长度小于这个值,线条就会被擦除,否则会保存。(这里MinLength的值为7)
参看资料来源:https://zhidao.baidu.com/question/537268196.html
返回值lines是被提取出来的线段
%}
figure, imshow(rotI), hold on; %figure创建一个新的图窗窗口
max_len = 0; %初始化max_len
for k = 1:length(lines) %遍历lines
xy = [lines(k).point1;lines(k).point2];
%{
.point1和.point2是直线的两个端点
[a;b]形式是指把矩阵b放到矩阵a之后,最后得到一个新的矩阵
lines(k).point1=[起点的x,起点的y] , links(k).point2=[终点的x,终点的y]
xy = [ 起点的x,起点的y
终点的x,重点的y] 这个样子的矩阵
资料来源:https://www.ilovematlab.cn/thread-539681-1-1.html
https://zhidao.baidu.com/question/417767976.html
%}
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green'); %画线段,宽为2,绿色
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow'); %线段起点,形状叉号,线宽为2,颜色为黄
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red'); %线段终点,形状叉号,线宽为2,颜色为红
% 可以注意一下线段和点的不同表示方式
len = norm(lines(k).point1 - lines(k).point2); %选出最长的线段
if(len > max_len)
max_len = len;
xy_long = xy;
end
end
%% 将最长线段设为青色以突出显示
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','cyan');
注释书写过程参考了以下资料及博客: