OpenCV学习笔记(二)五形态学操作形态学操作简单来讲,形态学操作就是基于形状的一系列图像处理操作。通过将结构元素作用于输入图像来产生输出图像。最基本的形态学操作有二:腐蚀与膨胀(Erosion与Dilation)。他们的运用广泛:消除噪声分割(isolate)独立的图像元素,以及连接(join)相邻的元素。寻找图像中的明显的极大值区域或极小值区域。腐蚀操作腐蚀在形态学操作家族里是膨胀操作的孪生姐妹。它提取的是内核覆盖下的相素最小值。进行腐蚀操作时,将内核B划过图像,将内核B覆盖区域的最小相素值提取,并代替锚点位置的相素。我们使用腐蚀操作。从下面的结果图我们看到亮区(背景)变细,而黑色区域(字母)则变大了。腐蚀操作函数原型:voiderode(InputArraysrc,OutputArraydst,InputArraykernel,Pointanchor=Point(-1,-1),intiterations=1,intborderType=BORDER_CONSTANT,constScalar&borderValue=morphologyDefaultBorderValue())1可以看到前三个是必要的参数,后面都有默认的参数。InputArraykernel腐蚀操作的内核膨胀操作此操作将图像A与任意形状的内核(B),通常为正方形或圆形,进行卷积。内核B有一个可定义的锚点,通常定义为内核中心点。进行膨胀操作时,将内核B划过图像,将内核B覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展”(因此有了术语膨胀dilation)voiddilate(InputArraysrc,OutputArraydst,InputArraykernel,Pointanchor=Point(-1,-1),intiterations=1,intborderType=BORDER_CONSTANT,constScalar&borderValue=morphologyDefaultBorderValue())12开运算(Opening)开运算是通过先对图像腐蚀再膨胀实现的。dst=open(src,element)=dilate(erode(src,element))能够排除小团块物体(假设物体较背景明亮)闭运算(Closing)闭运算是通过先对图像膨胀再腐蚀实现的。dst=close(src,element)=erode(dilate(src,element))能够排除小型黑洞(黑色区域)。形态梯度(MorphologicalGradient)膨胀图与腐蚀图之差dst=morph_{grad}(src,element)=dilate(src,element)-erode(src,element顶帽(TopHat)原图像与开运算结果图之差dst=tophat(src,element)=src-open(src,element)黑帽(BlackHat)闭运算结果图与原图像之差dst=blackhat(src,element)=close(src,element)–src六图像的放大和缩小图像金字塔(ImagePyramids)一个图像金字塔是一系列图像的集合-所有图像来源于同一张原始图像-通过梯次向下采样获得,直到达到某个终止条件才停止采样。有两种类型的图像金字塔常常出现在文献和应用中:高斯金字塔(Gaussianpyramid):用来向下采样拉普拉斯金字塔(Laplacianpyramid):用来从金字塔低层图像重建上层未采样图像向下采样导致了,图像放大,造成模糊向上采样会导致丢失信息,因为他缩小了图像向上采用函数原型:voidpyrUp(InputArraysrc,OutputArraydst,constSize&dstsize=Size(),intborderType=BORDER_DEFAULT)向下采用函数原型:voidpyrDown(InputArraysrc,OutputArraydst,constSize&dstsize=Size(),intborderType=BORDER_DEFAULT)实例://将图像放大两倍pyrUp(src,dst,Size(src.cols*2,src.rows*2));//缩小两倍pyrDown(src,dst,Size(src.cols/2,src.rows/2));七图像修复图像修复图像的修复是重建图像和视频受损部分的过程,这个过程也成为图像或视频的插值。OpenCV2.4版本支持一种修复算法,函数的模型为:voidinpaint(InputArraysrc,InputArrayinpaintMask,OutputArraydst,doubleinpaintRadius,intflags)Parameters:src:输入的图像8-bit1通道或3通道inpaintMask:图像的掩码,8-bit1-channelimage.dst:输出图像inpaintRadius:表示有flags所制定的算法可以使用的邻域flag:有两种方式1.INPAINT_NS:该方法是基于Navier-Stokes方法2.INPAINT_TELEA:该方法是抑郁AlexandruTelea提出的算法如果不知道图像的掩码,则去获得它的掩码挺复杂的,应该你并不知道,什么情况下才是最优的,只能去实验。更具阈值去获得图像掩码:doublethreshold(InputArraysrc,OutputArraydst,doublethresh,doublemaxval,inttype)其中thresh为所要设置的阈值maxval为type以什么形式设置阈值。type的方式如下图所示:这里选用的是二值的方式,即当src(x,y)thresh时,将其设为maxval.一个实例:这个例子中获得的不是很好的掩码,掩码的选择可能更为的复杂。#includeopencv2/opencv.hpp#includeiostream#includeiomanipusingnamespacecv;usingnamespacestd;intmain(intargc,char**argv){//ReadthesourcefileMatsrc;src=imread(3.jpg);//CreatethemaskMatmask;cvtColor(src,mask,COLOR_RGB2GRAY);//将其转换成灰度图像,因为掩码必须是一维的/*for(inti=0;imask.rows;i++){for(intj=0;jmask.cols;j++)coutint(mask.atuchar(i,j))setw(4);coutendl;}*/coutint(mask.atuchar(mask.rows/2,mask.cols/2))endl;threshold(mask,mask,190,255,THRESH_BINARY);//ApplytheinpaintingalgorithmsMatdst,dst2;inpaint(src,mask,dst,10,INPAINT_TELEA);inpaint(src,mask,dst2,10,INPAINT_NS);//ShowtheresultsnamedWindow(ORIGINAL,WINDOW_AUTOSIZE);imshow(ORIGINAL,src);namedWindow(MASK,WINDOW_AUTOSIZE);imshow(MASK,mask);namedWindow(INPAINT_TELEA,WINDOW_AUTOSIZE);imshow(INPAINT_TELEA,dst);namedWindow(INPAINT_NS,WINDOW_AUTOSIZE);imshow(INPAINT_NS,dst2);waitKey();return0;}八颜色处理颜色空间要用三种或更多的特征来指定一种颜色,有许多的方法被称为颜色空间或者颜色模型。如何选取其中一种方法来表示一副图像要依赖于执行的运算。不同的颜色空间的转换,Opencv提供方法voidcvtColor(InputArraysrc,Outputdst,intcode,intdstCn=0)code:这是颜色空间的转换代码。例如COLOR_BGR2GRAYdstCn:这是目标图形的通道数,如果为0或省略,则通道数有src和code自动产生。常用的颜色空间:RGB颜色空间在RGB中,一幅图像有三个独立的图像平面或通道组成:红,绿,蓝(以及第四个通道透明度)。如下代码展示了,加载RGB图像,并在灰度空间和颜色空间中拆分并显示每个特定的通道。voidsplit(InputArraym,OutputArrayOfArraysmv)1.将图像的每个通道保存在mv中2.mv声明为vectormvvoidmerge(InputArrayOfArraysmv,OutputArraydst)1.将mv和并称一个图像dst#includeopencv2/opencv.hpp#includeopencv2/opencv_modules.hpp#includeopencv2/highgui/highgui.hpp#includeiostreamusingnamespacecv;usingnamespacestd;vectorMatshowSeqratedChannels(vectorMatchannels);intmain(){Matimage=imread(test.jpg);vectorMatchannels;split(image,channels);//分割图像//用灰度级显示通道namedWindow(Origin,WINDOW_NORMAL);imshow(Origin,image);namedWindow(Bluechannel,WINDOW_NORMAL);imshow(Bluechannel,channels[0]);namedWindow(Greenchannel,WINDOW_NORMAL);imshow(Greenchannel,channels[1]);namedWindow(Redchannel,WINDOW_NORMAL);imshow(Redchannel,channels[2]);coutchannels.size()endl;//显示BGR中的通道vectorMatseparated=showSeqratedChannels(channels);namedWindow(Bluechannel,WINDOW_AUTOSIZE);imshow(Bluechannel,separated[0]);namedWindow(Greenchannel,WINDOW_AUTOSIZE);imshow(Greenchannel,separated[1]);namedWindow(Redchannel,WINDOW_AUTOSIZE);imshow(Redchannel,separated[2]);coutseparated[0].size()endl;coutseparated[0].rowsendl;coutseparated[0].colsendl;waitKey();}//这个函数,将channels中的每个波段分别加上两个波段,形参三个RGB通道//其余两个通道介入的都是0像素。vectorMatshowSeqratedChannels(vectorMatchannels){vectorMatseqar(inti=0;i3;i++){Matzero=Mat::zeros(channels[0].rows,channels