形态学的四个基本操作:腐蚀、膨胀、开、闭、顶帽、黑帽。
腐蚀:腐蚀就是对一副图像做卷积运算,然后将结构体中的最小值赋给卷积核的中心。使得总体的暗区域增加。
膨胀:膨胀就是对一副图像做卷积运算,然后将结构体中的最大值赋给卷积核的中心。使得总体的亮度增加。
结构体形状可以为任意形状。
#include<opencv2/opencv.hpp>
using namespace cv;
/// 全局变量
Mat src, erosion_dst, dilation_dst;
int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;
/** Function Headers */
void Erosion(int, void*);
void Dilation(int, void*);
/** @function main */
int main(int argc, char** argv)
{
/// Load 图像
src = imread(argv[1]);
src = imread("C:/opencv/sources/samples/data/pic1.png");
if (!src.data)
{
return -1;
}
/// 创建显示窗口
namedWindow("Erosion Demo", CV_WINDOW_AUTOSIZE);
namedWindow("Dilation Demo", CV_WINDOW_AUTOSIZE);
cvMoveWindow("Dilation Demo", src.cols, 0);
/// 创建腐蚀 Trackbar
createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
&erosion_elem, max_elem,
Erosion);
createTrackbar("Kernel size:\n 2n +1", "Erosion Demo",
&erosion_size, max_kernel_size,
Erosion);
/// 创建膨胀 Trackbar
createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
&dilation_elem, max_elem,
Dilation);
createTrackbar("Kernel size:\n 2n +1", "Dilation Demo",
&dilation_size, max_kernel_size,
Dilation);
/// Default start
Erosion(0, 0);
Dilation(0, 0);
waitKey(0);
return 0;
}
/** @function Erosion */
void Erosion(int, void*)
{
int erosion_type;
if (erosion_elem == 0) { erosion_type = MORPH_RECT; }
else if (erosion_elem == 1) { erosion_type = MORPH_CROSS; }
else if (erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }
Mat element = getStructuringElement(erosion_type,
Size(2 * erosion_size + 1, 2 * erosion_size + 1),
Point(erosion_size, erosion_size));
/// 腐蚀操作
erode(src, erosion_dst, element);
imshow("Erosion Demo", erosion_dst);
}
/** @function Dilation */
void Dilation(int, void*)
{
int dilation_type;
if (dilation_elem == 0) { dilation_type = MORPH_RECT; }
else if (dilation_elem == 1) { dilation_type = MORPH_CROSS; }
else if (dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }
Mat element = getStructuringElement(dilation_type,
Size(2 * dilation_size + 1, 2 * dilation_size + 1),
Point(dilation_size, dilation_size));
///膨胀操作
dilate(src, dilation_dst, element);
imshow("Dilation Demo", dilation_dst);
}
void Dilation(int,void *)
大部分代码应该不需要解释了 (如果有任何疑问,请回头参考前面的教程)。 让我们来回顾一下本程序的总体流程:
- 装载图像 (可以是 RGB图像或者灰度图 )
- 创建两个显示窗口 (一个用于膨胀输出,一个用于腐蚀输出)
- 为每个操作创建两个 Trackbars:
3.1 第一个 trackbar “Element” 返回 erosion_elem 或者 dilation_elem
3.2 第二个 trackbar “Kernel size” 返回 erosion_size 或者 dilation_size 。
3.3 每次移动标尺, 用户函数 Erosion 或者 Dilation 就会被调用,函数将根据当前的trackbar位置更新输出图像。
3.4让我们分析一下这两个函数: - erode(腐蚀)它接受三个参数:
第一个参数是输入图像,第二个图像是输出图像,第三个是内核。
如果第三个参数不指定,则会默认为一个3X3结构大小的内核。也可以通过getStructuringElement指定内核大小以及形状,现在分析该函数。
该函数的第一个参数是指定内核类型,第二个参数是指定内核的大小,第三个是指定锚点的位置,默认位于中心。