一、膨胀和腐蚀
膨胀和腐蚀(Dilating and Eroding)是基本的形态学操作。在OpenCV中定义了erode和dilate函数完成相应的功能。
膨胀和腐蚀主要作用有三:去除噪声;将分离的部分邻近连接起来;将密布的像素形成一块整体。
膨胀操作也类似于线性滤波,不过使用的是最大值滤波器,以kernel范围内的最大值代替中心点。
相反地,腐蚀操作使用的是最小值滤波器。
下面来看看在OpenCV中如何进行膨胀和腐蚀操作:
因为erode和dilate操作可以使用定义的Kernel形状,比如常用的矩形,还有椭圆和十字可以使用。
用getStructuringElement函数定义kernel形状:
Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1, -1))
shape可以是MORPH_RECT或者MORPH_ELLIPSE或者MORPH_CROSS。
膨胀:
void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1, -1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue())
一般我们只要关心前三个参数,dilate支持就地操作(inplace mode),所以src和dst可以相同。kernel就使用getStructuringElement()返回的Mat对象。
腐蚀:
void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1, -1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue())
使用方法和dilate()函数相同。
二、滑动条(Trackbar)和回调函数(callback function)
OpenCV给我们提供了滑动条和回调函数配套的操作,如此,我们就能够实时地通过滑动条来设置变量,并调用回调函数。
int createTrackbar(const string& trackbarname, const string& winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0)
trackbarname给出滑动条的名字。
winname是滑动条要出现的窗口的名字。
value是一个已有的变量。
count是这个滑动条的最大调整范围(从0开始)。
onChange是回调函数的函数指针,这个回调函数的原型应该符合void Foo(int, void*),第一个参数传入滑动条的位置,第二个参数传入userdata。
userdata就是传入onChange的第二个参数。
举个OpenCV教学文档中使用createTrackbar的例子:
1 int erosion_elem = 0; 2 int erosion_size = 0; 3 int const max_elem = 2; 4 int const max_kernel_size = 21; 5 6 createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo", 7 &erosion_elem, max_elem, 8 Erosion ); 9 10 createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo", 11 &erosion_size, max_kernel_size, 12 Erosion ); 13 14 void Erosion( int, void* ) 15 { 16 int erosion_type = 0; 17 if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; } 18 else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; } 19 else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; } 20 21 Mat element = getStructuringElement( erosion_type, 22 Size( 2*erosion_size + 1, 2*erosion_size+1 ), 23 Point( erosion_size, erosion_size ) ); 24 /// Apply the erosion operation 25 erode( src, erosion_dst, element ); 26 imshow( "Erosion Demo", erosion_dst ); 27 }
第6行和第10行,为Erosion Demo窗口设置了两个滑动条,并为这两个滑动条设置了名字、参数、参数可调整的范围、回调函数。这里回调函数并未使用userdata参数。
我们看第14行,Erode就是回调函数,它符合void Foo(int, void*)的函数原型。(原型是ANSI C的说法,原型定义了一个函数的名字、返回值和形参个数、类型。)
一般来说,在设置滑动条、定义回调函数之后,我们利用Erode(0, 0)来做Default start。
讲的比较简单,见谅。