包括图像的腐蚀、膨胀、开、闭、形态学梯度、顶帽、黑帽、分支主题、结构元素等操作。
具体概念参考:(41条消息) 图像处理-形态学处理_Good@dz的博客-CSDN博客_图像处理 形态学
用3×3的核去扫描二值图像,当核与图像中的前景像素(值为1的像素)有交集时,则将二值图像中对应的卷积核中心位置的像素值置为1。
拓展:卷积核可以为任意形状(除1×1),且重置点可以选用卷积核中的任意位置,有‘交集‘就对重置点位置像素置1。

用3×3的核去扫描二值图像,仅当核的与前景像素有完全重合区域时,将二值图像中对应的卷积核中心位置的像素保留,其余情况下,将中心位置的像素置0。
拓展:卷积核可以为任意形状,且重置点可以选用卷积核中的任意位置。

膨胀与腐蚀的区别:膨胀只要有交集就触发,而腐蚀必须是重置点与前景像素有完全重合区域才保留。
开:腐蚀再膨胀,去除微小干扰块。

闭:膨胀再腐蚀,填充闭合区域。

基本梯度:膨胀图 - 腐蚀图
内梯度:原图 - 腐蚀图
外梯度:膨胀图 - 原图
这里opencv只能直接实现基本梯度,在使用API:morphologyEx 时,调用MORPH_GRADIENT方法即可。
内梯度、外梯度没有直接的API,一般通过已有API间接实现。
顶帽:原图 - 开操作后的图
黑帽:闭操作后的图 - 原图
注:顶帽和黑帽操作用于获取图像中的微小细节。
击中击不中: 通过特定模板,仅当输入的图像中,有与模板一模一样的块时,被击中的输入图像区域才会被保留。

使用API:morphologyEx 时,分别调用MORPH_TOPHAT 、MORPH_BLACKHAT、MORPH_HITMISS方法即可实现。
定义核形状
-
- Mat cv::getStructuringElement ( int shape,
- Size ksize,
- Point anchor = Point(-1,-1)
- )
shape——核的形状,可以定义矩形,十字形等形状,如下:
ksize——大小
anchor ——锚定点,即前文中的重置点。
注:当设计到保留横线或竖线时,可以将核定义成1×n或者n×1的形状,从而去除其余形状的线。
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 1), Point(-1, -1));
腐蚀:
- void cv::erode ( InputArray src,
- OutputArray dst,
- InputArray kernel,
- Point anchor = Point(-1,-1),
- int iterations = 1,
- int borderType = BORDER_CONSTANT,
- const Scalar & borderValue = morphologyDefaultBorderValue()
- )
膨胀:
-
- void cv::dilate ( InputArray src,
- OutputArray dst,
- InputArray kernel,
- Point anchor = Point(-1,-1),
- int iterations = 1,
- int borderType = BORDER_CONSTANT,
- const Scalar & borderValue = morphologyDefaultBorderValue()
- )
通用:
- void cv::morphologyEx ( InputArray src,
- OutputArray dst,
- int op,
- InputArray kernel,
- Point anchor = Point(-1,-1),
- int iterations = 1,
- int borderType = BORDER_CONSTANT,
- const Scalar & borderValue = morphologyDefaultBorderValue()
- )
op ——形态学操作选用,如下:
iterations——重复腐蚀和膨胀的次数。
borderType ——边界类型
borderValue ——Border value in case of a constant border. The default value has a special meaning.
- void erode_dilate(Mat& image)
- {
- Mat gray;
- cvtColor(image, gray, COLOR_BGR2GRAY);
- Mat binary;
- threshold(gray, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
- namedWindow("THRESH_OTSU", WINDOW_FREERATIO);
- imshow("THRESH_OTSU", binary);
-
- Mat dst1, dst2;
- //定义核
- int kernel_size = 5;
- Mat kernel = getStructuringElement(MORPH_RECT, Size(kernel_size, kernel_size), Point(-1, -1));
- //腐蚀
- erode(binary, dst1, kernel);
- namedWindow("erode", WINDOW_FREERATIO);
- imshow("erode", dst1);
-
- //膨胀
- dilate(binary, dst2, kernel);
- namedWindow("dilate", WINDOW_FREERATIO);
- imshow("dilate", dst2);
- }

- void QuickDemo::open_close(Mat& image)
- {
- Mat gray;
- cvtColor(image, gray, COLOR_BGR2GRAY);
- Mat binary;
- threshold(gray, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
- namedWindow("THRESH_OTSU", WINDOW_FREERATIO);
- imshow("THRESH_OTSU", binary);
-
- Mat dst1, dst2;
- //定义核
- int kernel_size = 5;
- Mat kernel = getStructuringElement(MORPH_RECT, Size(kernel_size, kernel_size), Point(-1, -1));
- //开
- morphologyEx(binary, dst1, MORPH_OPEN, kernel, Point(-1, -1), 1, 0);
- namedWindow("MORPH_OPEN", WINDOW_FREERATIO);
- imshow("MORPH_OPEN", dst1);
-
- //闭、
- morphologyEx(binary, dst2, MORPH_CLOSE, kernel, Point(-1, -1), 1, 0);
- namedWindow("MORPH_CLOSE", WINDOW_FREERATIO);
- imshow("MORPH_CLOSE", dst2);
- }

注:在边缘提取应用中,梯度边缘后,会再进行二值化,从而获取更好的边缘图像。
- void QuickDemo::shape_gradient(Mat& image)
- {
- Mat gray;
- cvtColor(image, gray, COLOR_BGR2GRAY);
-
- Mat g1, g2, g3;
- Mat dst1, dst2;
- int kernel_size = 7;
- Mat kernel = getStructuringElement(MORPH_RECT, Size(kernel_size, kernel_size), Point(-1, -1));
-
- //基本梯度
- morphologyEx(gray, g1, MORPH_GRADIENT, kernel, Point(-1, -1), 1, 0);
-
- //膨胀
- morphologyEx(gray, dst1, MORPH_DILATE, kernel, Point(-1, -1), 1, 0);
-
- //腐蚀
- morphologyEx(gray, dst2, MORPH_ERODE, kernel, Point(-1, -1), 1, 0);
-
- //外梯度
- subtract(dst1, gray, g2);
- //内梯度
- subtract(gray, dst2, g3);
-
- namedWindow("基本梯度", WINDOW_FREERATIO);
- imshow("基本梯度", g1);
-
- namedWindow("外梯度", WINDOW_FREERATIO);
- imshow("外梯度", g2);
-
- namedWindow("内梯度", WINDOW_FREERATIO);
- imshow("内梯度", g3);
-
- //最后再进行二值化,获取更好的边缘图像,选用基本梯度示例
- Mat binary;
- threshold(g1, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
- namedWindow("二值化", WINDOW_FREERATIO);
- imshow("二值化", binary);
- }

- void QuickDemo::other_method(Mat& image)
- {
- Mat gray;
- cvtColor(image, gray, COLOR_BGR2GRAY);
- Mat binary;
- threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
- namedWindow("二值化", WINDOW_FREERATIO);
- imshow("二值化", binary);
-
- Mat dst1, dst2, dst3;
- int kernel_size = 5;
- Mat kernel_1 = getStructuringElement(MORPH_RECT, Size(kernel_size, kernel_size), Point(-1, -1));
-
- //顶帽
- morphologyEx(binary, dst1, MORPH_TOPHAT, kernel_1, Point(-1, -1), 1, 0);
- namedWindow("顶帽", WINDOW_FREERATIO);
- imshow("顶帽", dst1);
- //黑帽
- morphologyEx(binary, dst2, MORPH_BLACKHAT, kernel_1, Point(-1, -1), 1, 0);
- namedWindow("黑帽", WINDOW_FREERATIO);
- imshow("黑帽", dst2);
-
- //击中击不中
- Mat kernel_2 = getStructuringElement(MORPH_CROSS, Size(kernel_size, kernel_size), Point(-1, -1));
- morphologyEx(binary, dst3, MORPH_HITMISS, kernel_2, Point(-1, -1), 1, 0);
- namedWindow("击中击不中", WINDOW_FREERATIO);
- imshow("击中击不中", dst3);
- }