形态学
形态学(morphology)是生物学的一个分支,其关注的是动植物的形态和结构等。这里用同一词语表示图像处理的数学形态学的内容。数学形态学的语言是集合论,其中的集合表示图像的对象,如:二值化图像中,所有白色像素的集合是该图像的一个完整形态学描述。集合中每两个分量提供一个像素的坐标,第三个分量则对应于其离散灰度值。更高维度空间的集合可以包含其他的图像属性,譬如颜色和随时间变化的分量。除了基本的集合定义之外,集合的反射和平移的概念在形态学中用得也很广泛。一个集合B的反射表示B',定义如下:B'={w|w=-b,b∈B}。如果B是描述图像中物体的像素的集合(二维点),则B'是B中(x,y)坐标被(-x,-y)替代的点的集合。集合B按照点z=(z1,z2)表示(B)z的平移定义:(B)z={c|c=b+z,b∈B}。图像表示如下:
集合反射操作类似于空间卷积中执行的翻转(旋转)操作。在形态学中集合的反射和平移用来表达基于结构元(SE)的操作:研究一幅图像中感兴趣特性所用的小集合或子图像。对于结构元的操作可以使用下图做一些简单的介绍:
当我们使用“结构元包含在几何中”这样的术语时,我们明确地指出A和B的元素完全重叠。
形态学梯度运算:
#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; int main() { Mat image = imread("1.jpg"); imshow("【原始图】形态学梯度", image); Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); morphologyEx(image, image, MORPH_GRADIENT, element); imshow("【效果图】形态学梯度", image); waitKey(0); return 0; }
形态学综合示例:
#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; Mat g_srcImage, g_dstImage;//原始图和效果图 int g_nElementShape = MORPH_RECT;//元素结构的形状 //变量接收的TrackBar位置参数 int g_nMaxIterationNum = 10; int g_nOpenCloseNum = 0; int g_nErodeDilateNum = 0; int g_nTopBlackHatNum = 0; static void on_OpenClose(int, void*);//回调函数 static void on_ErodeDilate(int, void*);//回调函数 static void on_TopBlackHat(int, void*);//回调函数 int main() { g_srcImage = imread("1.jpg"); if (!g_srcImage.data) { printf("Oh,no,读取srcImage错误~! \n"); return false; } imshow("【原始图】", g_srcImage); namedWindow("【开运算/闭运算】", 1); namedWindow("【腐蚀/膨胀】", 1); namedWindow("【顶帽/黑帽】", 1); //参数赋值 g_nOpenCloseNum = 9; g_nErodeDilateNum = 9; g_nTopBlackHatNum = 2; //分别为三个窗口创建滚动条 createTrackbar("迭代值", "【开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1, on_OpenClose); createTrackbar("迭代值", "【腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationNum * 2 + 1, on_ErodeDilate); createTrackbar("迭代值", "【顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat); //轮询获取按键信息 while (1) { int c; //执行回调函数 on_OpenClose(g_nOpenCloseNum, 0); on_ErodeDilate(g_nErodeDilateNum, 0); on_TopBlackHat(g_nTopBlackHatNum, 0); //获取按键 c = waitKey(0); //按下键盘按键Q或者ESC,程序退出 if ((char)c == 'q' || (char)c == 27) break; //按下键盘按键1,使用椭圆(Elliptic)结构元素结构元素MORPH_ELLIPSE if ((char)c == 49)//键盘按键1的ASII码为49 g_nElementShape = MORPH_ELLIPSE; //按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECT else if ((char)c == 50)//键盘按键2的ASII码为50 g_nElementShape = MORPH_RECT; //按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_CROSS else if ((char)c == 51)//键盘按键3的ASII码为51 g_nElementShape = MORPH_CROSS; //按下键盘按键space,在矩形、椭圆、十字形结构元素中循环 else if ((char)c == ' ') g_nElementShape = (g_nElementShape + 1) % 3; } return 0; } static void on_OpenClose(int, void*) { //偏移量的定义 int offset = g_nOpenCloseNum - g_nMaxIterationNum;//偏移量 int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值 //自定义核 Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset)); //进行操作 if (offset < 0) //此句代码的OpenCV2版为: //morphologyEx(g_srcImage, g_dstImage, CV_MOP_OPEN, element); //此句代码的OpenCV3版为: morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element); else //此句代码的OpenCV2版为: //morphologyEx(g_srcImage, g_dstImage, CV_MOP_CLOSE, element); //此句代码的OpenCV3版为: morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element); //显示图像 imshow("【开运算/闭运算】", g_dstImage); } static void on_ErodeDilate(int, void*) { //偏移量的定义 int offset = g_nErodeDilateNum - g_nMaxIterationNum; //偏移量 int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值 //自定义核 Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset)); //进行操作 if (offset < 0) erode(g_srcImage, g_dstImage, element); else dilate(g_srcImage, g_dstImage, element); //显示图像 imshow("【腐蚀/膨胀】", g_dstImage); } static void on_TopBlackHat(int, void*) { //偏移量的定义 int offset = g_nTopBlackHatNum - g_nMaxIterationNum;//偏移量 int Absolute_offset = offset > 0 ? offset : -offset;//偏移量绝对值 //自定义核 Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset)); //进行操作 if (offset < 0) morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element); else morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element); //显示图像 imshow("【顶帽/黑帽】", g_dstImage); }morphologyEx
填充:
#include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; int main() { Mat src = imread("1.jpg"); imshow("【原始图】", src); Rect ccomp; floodFill(src, Point(50, 300), Scalar(155, 255, 55), &ccomp, Scalar(20, 20, 20), Scalar(20, 20, 20)); imshow("【效果图】", src); waitKey(0); return 0; }floodfill
--------------------------continue----------------------------------------