机器视觉工具箱(MVTB)提供了许多在机器视觉和基于视觉的控制中有用的功能。这是一个有点折衷的收藏品,反映了作者对光度学、摄影测量学、色度学等领域的个人兴趣。它包括100多个功能,包括图像文件读写、采集、显示、过滤、斑点、点和线特征提取、数学形态学、单应、视觉雅可比、摄像机校准和颜色空间转换等操作。
运行此教程的实例,需要在Matlab附加功能选项中安装如下图所示的机器视觉工具箱(MVTB)、vlfeat、MATLAB Support for MINGW-W64。
获取图像的方法有读取本地图像、读取相机图像、生成图像。
%读取本地照片文件
street = iread( 'street.png') ;
about (street ) %获取照片信息
idisp(street); %在matlab显示照片
操作方法如下
cam =Videocamera("name"); %打开一个特殊相机:
im =cam.grab(); %使用grab方法抓取一幅图像
工具箱函数testpattern可以产生各种形式的简单图像,包括直线、网格点或方块、光强斜坡变化和光强正弦变化,第二个参数代表所建图像的大小。
%首先建一个全是黑色像素的帆布(像素值是0):
canvas =zeros(200,200) ;
%然后创建两个正方一形模板:
sq1=0.5*ones(40,40) ;
sq2=0.9*ones(20,20) ;
%再创建一个圆:
circle = 0.6* kcircle(30) ;
%把它们粘贴到帆布上:
canvas =ipaste (canvas, sq1,[20,40]) ;
canvas =ipaste (canvas,sq2,[ 60,120]) ;
canvas = ipaste (canvas, circle, [100, 30]) ;
%最后,在帆布上画一条线段:
canvas = iline( canvas, [30, 40],[150,190], 0.8) ;
idisp(canvas); %显示图像
一元图像处理操作,输出结果是一幅与输人图像相同大小的图像,且每一个输出像素都是对应输人像素的函数。
street = iread( 'street.png') ;
>>idisp(street)
>>ihist(street); %显示直方图
%取灰度值在30到80之间的像素点。
shadows = (street >= 30) & (street<= 80) ;
idisp ( shadows )
%显示像素值的累积直方图
ihist(street,'cdf');
%直方图均衡化
im = inormhist(street);
二元操作中,每一个输出像素都是两个输人图像中对应像素点的函数。常用的二元操作包括二进制算术运算,如加法、减法、元素操作,或者是MATLAB内置的二元矩阵函数,如max、min、bitand、atan2等。用一个unit8图像减去另一个unit8图像,就会产生另外一个unit8图像,尽管结果可能是负的。MATLAB却可以正确地把值取在[0 ,255]区间中,所以小数减大数将会得出0,而不是负值。另外,大于255的结果将会被设为255。为了实现这种纠正,图像应该首先用MATLAB函数cast转换成有符号整型,或者使用工具箱函数idouble转换成浮点型。
%互相关核
K = ones(21,21) / 21^2;
lena = iread('lena.pgm', double');
%平滑处理
idisp( iconv(K,lena) ) ;
这种平均化会使图像光滑化、模糊化或者散焦,效果如下图。
每一个输出像素都是输人图像中与之对应的21 x21相邻像素的平均值。
castle =iread('castle_sign.jpg','double','gray');
p=castle(360,:) ;
figure(9);
idisp(castle);%绘制出相对于横坐标u的图形
figure(1);
plot(p);%绘制出相对于横坐标u的图形
Du = ksobel;%sobel算子求梯度
figure(2);
idisp(iconv(castle, Du),'invsigned')%显示水平梯度图
figure(3);
idisp( iconv(castle, Du'),'invsigned')%显示垂直梯度图
figure(4);
Iu = iconv( castle, -kdgauss(2) ) ;
Iv = iconv( castle, -kdgauss(2)') ;
m=sqrt(Iu.^2+Iv.^2);
th = atan2(Iv,Iu);
%绘制出最便于观察的稀疏箭头图
quiver (1:20:numcols(th),1:20 :numrows(th),...
Iu(1:20:end,1:20:end),Iv(1:20:end, 1:20:end) )
figure(5);
% [du,dv] = isobel( castle, kagauss(2) ) ;
edges = icanny (castle, 2) ;%canny算子求边缘
idisp(edges);
由于模板匹配需要使用函数iwindow,故需要在Matlab的视觉工具箱文件夹下先运行starup_rvc.m。
此处模板匹配案例目标为在于要在一大群人中找出沃利的脸。
%读取大图
crowd = iread( 'wheres-wally.png', 'double');
figure(1);
idisp (crowd)
%读取目标人物沃利的脸
T = iread('wally.png', 'double');
figure(2);
idisp(T)
%使用匹配测度ZNCC计算模板T与每一个可能窗口位置的相似性
S = isimilarity(T, crowd, @zncc) ;
figure(3);
%显示相似度分布图像,图像中的像素的颜色表明了ZNCC相似性
idisp(S, 'colormap','jet','bar');
%取相似度最高的五个点
[mx,p] = peak2(S, 1, 'npeaks', 5) ;
% 在相似度分布图上用蓝圈和数字标号来突出这些与模板相似度高的点
%画圆
plot_circle(p, 30, 'fillcolor', 'b', 'alpha', 0.3, 'edgecolor', 'none');
% 并叠加数字以表示第一个、第二个等置信度
plot_point(p, 'sequence', 'bold', 'textsize', 24, 'textcolor', 'k');
figure(4);
idisp(crowd)
%在原图上使用透明蓝圈和数字标号来突出这些与模板相似度高的点
%画圆
plot_circle(p, 30, 'fillcolor', 'b', 'alpha', 0.3, 'edgecolor', 'none');
% 叠加数字以表示第一个、第二个等置信度
plot_point(p, 'sequence', 'bold', 'textsize', 24, 'textcolor', 'k');
如下图分别为带有目标人物的原图、原图、在相似度分布图上用蓝圈和数字标号来突出相似度最高的五个点、在原图上用蓝圈和数字标号来突出相似度最高的五个点。其中,在(261, 377)处的最好匹配事实上就是正确答案,找到了沃利。即序号为1处的人为沃利。再观察其他序号靠前的候选者,会发现在图像底部序号为2和3的也是戴着棒球帽的人,看起来也非常相似。
此处展示非线性操作中的中值滤波方法。
lena = iread('C:/Users/Administrator/Pictures/images/lena.png','gray');
spotty =lena;
npix = prod(size(lena)) ;
% 施加椒盐噪声,设定了5000个随机像素点为0,另外5000个随机像素点为最大值。这种类型噪声通常被称为脉冲噪声或椒盐噪声。
spotty (round (rand(5000,1)* (npix-1)+1)) = 0;
spotty (round(rand(5000, 1)* (npix-1)+1)) = 1.0;
figure(1);
idisp (spotty);
figure(2);
%显示中值滤波后的图片,消除椒盐噪声
idisp( irank (spotty, 5,1) );
对比结果如下图所示,图像质量得到了相当大的提高,去除了椒盐噪声。通过平滑处理也可以达到相同的效果,但是会使图像模糊,中值滤波器则有保留场景中边缘的优点。
腐蚀膨胀、闭运算示例如下。
eg_morph1
figure(1);
idisp(im)
S = ones(5,5) ;
mn = imorph(im, S,'min');%腐蚀
figure(2);
idisp(mn);
mx = imorph(mn, S,'max');%膨胀
figure(3);
idisp(mx);
mx = imorph(im, S,'max');%膨胀
figure(4);
idisp(mx);
mn = imorph(mx, S,'min');%腐蚀
figure(5);
idisp(mn);
mn = iclose(im, S);%闭运算
figure(6);
idisp(mn);
腐蚀操作原理为求取5x5窗口中所有像素的最小值。下图中,右侧图片为腐蚀处理后的结果,两个对象已经完全消失, 两个正方形也已经分离并且变得更小
上述操作的逆操作则是膨胀,它使对象变大。下图原图为先腐蚀后膨胀的对比图。两个正方形已经恢复到原来大小,但是大的正方形上已经失去了它的突起物。开操作和闭操作是分别通过工具箱函数iopen和iclose执行的。与腐蚀和膨胀不同,重复使用开操作或闭操作是无效的,因为这些操作本身就是幂等的。按顺序操作,即先腐蚀后膨胀,被称为开操作,因为它打开了缺口;先膨胀后腐蚀,被称为闭操作,因为它闭合了缺口。
形态学开操作的常见应用是去除图像中的噪声。
%读取图像
objects = iread('C:/Users/Administrator/Pictures/images/lotsblobs.png');
spotty =objects;
npix = prod(size(objects)) ;
% 加椒盐噪声
spotty (round (rand(5000,1)* (npix-1)+1)) = 0;
spotty (round(rand(5000, 1)* (npix-1)+1)) = 1.0;
objects=spotty;
figure(1);
idisp(objects);
%选择一个对称的半径为3的圆形结构化元素
s = kcircle(3);
closed = iclose(objects, S);%闭运算
clean = iopen(closed, S) ;%开运算
figure(2);
idisp(clean);
下图为先闭操作,在开操作的结果,显示孔已经被填满,但是噪声像素也已经成长为小圆圈,有些已经结块
我们也可以使用形态学操作检测目标的边缘。
objects = iread('C:/Users/Administrator/Pictures/images/lotsblobs.png');
spotty =objects;
figure(1);
idisp(objects);
s = kcircle(3);
closed = iclose(objects, S);%闭运算
clean = iopen(closed, S) ;%开运算
figure(2);
idisp(clean);
eroded = imorph(clean, kcircle(1),'min');
figure(4);
idisp (clean-eroded); %边缘提取:从原始图像中减去腐蚀后的图像:
如下图为从原始图像中减去腐蚀后的图像,结果是每个目标对象的周边剩下,层像素点。
形态交离变换是形态学结构化元素的一个变种。它的值是0, 1,或者随意。为了使结果为1, 0和1像素必须与下面的图像像素精确匹配,如果有任何一个0或1不匹配,那么结果将会为0。示例如下。
objects = iread('C:/Users/Administrator/Pictures/images/shark1.png');
figure(1);
idisp(objects);
s = kcircle(3);
closed = iclose(objects, S);%闭运算
clean = iopen(closed, S) ;%开运算
figure(2);
idisp(clean);
out = hitormiss(clean, S);%形态交离变换
figure(5);
idisp(out);
skeleton = ithin (clean) ;%目标的骨架
figure(1);
idisp(skeleton);
ends=iendpoint (skeleton) ;%骨架的终止点
figure(2);
idisp(ends);
joins = itriplepoint (skeleton) ;%找到三叉点
figure(3);
idisp(joins);
最简单的形状变化是从图像中选出一个矩形区域,这是最常见的裁剪操作。
lena = iread('C:/Users/Administrator/Pictures/images/lena.png');
[eyes, roi] = iroi (lena) ;%手动选择roi区域
figure(1);
idisp( eyes);
mouth =iroi (lena,[253, 330; 332, 370]) ;%指定roi区域
figure(2);
idisp( mouth);
示例如下。
roof = iread('roof.jpg', 'grey') ;
figure(3);
idisp( roof);
smaller = roof(1:7:end,1:7:end) ;%缩小七倍
figure(4);
idisp( smaller);
smaller = idecimate (roof,7) ; %缩小七倍,亚抽样之前,使用一种抗锯齿低通空间滤波器来减小图像空间带宽
figure(5);
idisp( smaller);
bigger = ireplicate( smaller, 7 ) ;%放大七倍
figure(6);
idisp( bigger);
smoother = ismooth( bigger, 4);%平滑处理
figure(7);
idisp( smoother);
smaller = iscale(lena, 0.1) ;%工具箱缩小函数
bigger = iscale(smaller,10) ;%工具箱放大函数
lena = iread('C:/Users/Administrator/Pictures/images/lena.png','gray');
p = ipyramid(lena);%图像金字塔
figure(8);
idisp(p);
lena_rotated = irotate(lena, pi/6);
figure(9);
idisp(lena_rotated);
图像金字塔包含了分辨率持续减小的一组图像。 最后一个元素是一个1x1的图像一单个灰色像素! 把这些图像粘贴到一个合成图像中,如下图所示。
函数iscale使用图像变形来改变图像的尺寸,而函数irotate则用变形来执行图像旋转。因此图形旋转30度通过以下命令直接实现。
lena_ rotated = irotate(lena, pi/6) ;