一、更多的形态学变化
包括开运算 (Opening)、闭运算 (Closing)、形态梯度 (Morphological Gradient)、顶帽 (Top Hat)、黑帽(Black Hat)。具体可参考《数字图像处理 第三版》(冈萨雷斯)——第九章 形态学图像处理。注:具体原理都是一些数学计算公式、方法,目前只大概了解,后面可具体研读。
二、开运算
(1)教程中的解释:
-
开运算是通过先对图像腐蚀再膨胀实现的。
-
能够排除小团块物体(假设物体较背景明亮)
-
请看下面,左图是原图像,右图是采用开运算转换之后的结果图。 观察发现字母拐弯处的白色空间消失。
(2)资料整理
开运算和闭运算都由腐蚀和膨胀复合而成, 开运算是先腐蚀后膨胀, 而闭运算是先膨胀后腐蚀。膨胀:亮区扩大;腐蚀:亮区缩小。
一般来说, 开运算可以使图像的轮廓变得光滑, 还能使狭窄的连接断开和消除细毛刺。
如图8.11所示, 开运算断开了团中两个小区域间两个像素宽的连接〈断开了狭窄连接〉,并且去除了右侧物体上部突出的一个小于结构元素的2×2的区域〈去除细小毛刺〉: 但与腐蚀不同的是, 图像大的轮廓并没有发生整体的收缩, 物体位置也没有发生任何变化。
(3)opencv代码实现
#include"stdafx.h" #include<opencv2/opencv.hpp> int open_value = 0; int open_max = 5; int morph_elem = 0; int max_elem = 2; cv::Mat src,dst; void openOperator(int,void*); int main(int argc, char** argv) { src = cv::imread("lena512color.tiff"); if (src.empty()) { printf("Image load failed..."); return -1; } cv::namedWindow("src", CV_WINDOW_NORMAL); cv::createTrackbar("Opening_value:","src", &open_value, open_max, openOperator); cv::createTrackbar("Element: 0: Rect - 1: Cross - 2: Ellipse", "src",&morph_elem, max_elem,openOperator); openOperator(0, 0); //这句注释掉时,刚开始运行时若不移动滑动条则图片不会显示 cvWaitKey(0); return 0; } void openOperator(int, void*) { /*getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1)); @用法:返回一个特定形状(shape),大小(size),及锚点(anchor)的核,锚点为(-1,-1)时默认为中心 @参数:int shape MORPH_RECT = 0, MORPH_CROSS = 1, MORPH_ELLIPSE = 2 */ cv::Mat element = cv::getStructuringElement(morph_elem, cv::Size(2 * open_value + 1, 2 * open_value + 1), cv::Point(open_value, open_value)); morphologyEx(src, dst, cv::MORPH_OPEN, element);//element 为输入的结构元,用于卷积的矩阵 /*@API:void 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形态学操作类型 MORPH_ERODE = 0, MORPH_DILATE = 1, MORPH_OPEN = 2, MORPH_CLOSE = 3, MORPH_GRADIENT = 4, MORPH_TOPHAT = 5, MORPH_BLACKHAT = 6, MORPH_HITMISS = 7 @参数:InputArray kernel,用于进行形态学操作的核,可以用getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));获取 @参数:anchor,锚点,核的锚点位置,默认(-1,-1)则为中心 @参数:iterations,腐蚀、膨胀次数次数 @参数:borderType,参数外推方法, ...具体用到再查*/ cv::imshow("src", dst); }
二、闭运算
(1)教程中的解释:
-
闭运算是通过先对图像膨胀再腐蚀实现的。
能够排除小型黑洞(黑色区域)。
(2)相关资料整理:
闭运算同样可以使轮廓变得光滑, 但与开运算相反, 它通常能够弥合狭窄的间断, 填充小的孔洞。
(3)opencv实现代码:类似开运算
三、形态梯度
-
膨胀图与腐蚀图之差
-
能够保留物体的边缘轮廓,如下所示:
四、顶帽
- 原图像与开运算结果图之差
五、黑帽
-
闭运算结果图与原图像之差
六、测试代码(官方)
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <stdlib.h> #include <stdio.h> using namespace cv; /// 全局变量 Mat src, dst; int morph_elem = 0; int morph_size = 0; int morph_operator = 0; int const max_operator = 4; int const max_elem = 2; int const max_kernel_size = 21; char* window_name = "Morphology Transformations Demo"; /** 回调函数申明 */ void Morphology_Operations( int, void* ); /** @函数 main */ int main( int argc, char** argv ) { /// 装载图像 src = imread( argv[1] ); if( !src.data ) { return -1; } /// 创建显示窗口 namedWindow( window_name, CV_WINDOW_AUTOSIZE ); /// 创建选择具体操作的 trackbar createTrackbar("Operator: 0: Opening - 1: Closing 2: Gradient - 3: Top Hat 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations ); /// 创建选择内核形状的 trackbar createTrackbar( "Element: 0: Rect - 1: Cross - 2: Ellipse", window_name, &morph_elem, max_elem, Morphology_Operations ); /// 创建选择内核大小的 trackbar createTrackbar( "Kernel size: 2n +1", window_name, &morph_size, max_kernel_size, Morphology_Operations ); /// 启动使用默认值 Morphology_Operations( 0, 0 ); waitKey(0); return 0; } /** * @函数 Morphology_Operations */ void Morphology_Operations( int, void* ) { // 由于 MORPH_X的取值范围是: 2,3,4,5 和 6 int operation = morph_operator + 2; Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); /// 运行指定形态学操作 morphologyEx( src, dst, operation, element ); imshow( window_name, dst ); }