OpenCV—形态学运算定义与实现
1.形态学运算与结构元素
形态学运算是针对二值图像依据数学形态学(Mathematical Morphology)的集合论方法发展起来的图像处理方法。数学形态学起源于岩相学对岩石结构的定量描述工作,近年来在数字图像处理和机器视觉领域中得到了广泛的应用,形成了一种独特的数字图像分析方法和理论。
结构元素可以简单的定义为像素的组合,在对应的像素上定义了原点(也称锚点)。形态学滤波器的应用过程就是利用这个结构元素探测图像中每个像素的操作过程。把某个像素设为结构元素的锚点后,结构元素和图像重叠部分的像素集合就是特定形态学运算的应用对象。结构元素原则上可以是任何形状,但通常是一个简单形状,如正方形、圆形、菱形等,且把中心点作为原点。
2.腐蚀与膨胀运算
(1)腐蚀 erode
腐蚀的定义
也就是说,由B对X腐蚀所产生的二值图像E是满足以下条件的点(x,y)的集合:如果B的原点平移到点(x,y),那么B将完全包含于X中。
另一种理解,腐蚀就是把当前像素替换成所定义的像素集中的最小像素值。由于输入的二值图像只包含黑色(0)和白色(255)像素,因此如果结构元素覆盖的图像区域中有黑色像素,则锚点所在像素(x,y)将会被替换成黑色0,否则替换成白色255。而物体的边界通常会有黑色像素,所以腐蚀相当于收缩边界。
腐蚀的作用
腐蚀是一种消除边界点,使边界向内部收缩的过程。可以用来消除小且无意义的物体。
- // Read input image
- cv::Mat image= cv::imread("binary.bmp");
- if (!image.data)
- return 0;
- // Display the image
- cv::namedWindow("Image");
- cv::imshow("Image",image);
- // Erode the image
- cv::Mat eroded;
- cv::erode(image,eroded,cv::Mat());//cv::Mat()为空矩阵,此时采用默认3*3正方形结构元素
- // Display the eroded image
- cv::namedWindow("Eroded Image");
- cv::imshow("Eroded Image",eroded);
- // Erode the image with a larger s.e.定义更大的结构元素
- cv::Mat element(7,7,CV_8U,cv::Scalar(1));
- // Display the eroded image by large s.e.
- cv::erode(image,eroded,element);
- cv::namedWindow("Eroded Image (7x7)");
- cv::imshow("Eroded Image (7x7)",eroded);
- // Erode the image 3 times.腐蚀3次
- cv::erode(image,eroded,cv::Mat(),cv::Point(-1,-1),3);//cv::Point(-1,-1)表示原点是矩阵的中心点
- // Display the eroded image
- cv::namedWindow("Eroded Image (3 times)");
- cv::imshow("Eroded Image (3 times)",eroded);
- cv::waitKey(0);
原始二值图像
3×3正方形结构元素腐蚀结果
7×7正方形结构元素腐蚀结果
3×3正方形结构元素腐蚀3次结果
(2)膨胀 dilate
膨胀的定义
由B对X膨胀所产生的二值图像D是满足以下条件的点(x,y)的集合:如果B的原点平移到点(x,y),那么它与X的交集非空。
另一种理解为:膨胀是腐蚀的反运算,它把当前像素(原点所在位置(x,y))替换成所定义的像素集中的最大像素值。由于输入的二值图像只包含黑色(0)和白色(255)像素,因此当结构元素覆盖的图像中有白色(物体),则该结构元素原点所在位置(x,y)的值将会被替换成白色255。
膨胀的作用
也就是说,膨胀是将与物体接触的所有背景点合并到该物体中,使边界向外部扩张的过程。可以用来填补物体中的空洞。
- // Dilate the image
- cv::Mat dilated;
- cv::dilate(image,dilated,cv::Mat());
- // Display the dialted image
- cv::namedWindow("Dilated Image");
- cv::imshow("Dilated Image",dilated);
3×3正方形结构元素膨胀结果
(3)自定义结构元素
除了使用常规的规则结构元素,我们也可以自定义结构元素。下面使用Mat类型的构造函数创建一个3×3十字型的结构元素。
- // 创建自定义结构元素
- unsigned char m[9] = {
- 0,1,0,
- 1,1,1,
- 0,1,0
- };
- cv::Mat element1(3,3,CV_8U,m); //创建自定义矩阵element1
- //显示该结构元素
- int nr = element1.rows;
- int nl = element1.cols;
- for(int j = 0;j<nr;j++)
- {
- char *data = element1.ptr<char>(j);
- for(int i = 0; i<nl; i++)
- {
- int value = data[i];
- cout<<value<<" ";
- }
- cout<<endl;
- }
- // Display the eroded image by large s.e.
- cv::erode(image,eroded,element1);
- cv::namedWindow("Eroded Image (user define)");
- cv::imshow("Eroded Image (user define)",eroded);
自定义结构元素腐蚀结果
使用Mat_模板类自定义5×5大小十字形、菱形、方形、x形结构元素:
- cv::Mat_<uchar> cross(5,5);
- cv::Mat_<uchar> diamond(5,5);
- cv::Mat_<uchar> x(5,5);
- cv::Mat_<uchar> square(5,5);
- // Creating the cross-shaped structuring element
- cross <<
- 0, 0, 1, 0, 0,
- 0, 0, 1, 0, 0,
- 1, 1, 1, 1, 1,
- 0, 0, 1, 0, 0,
- 0, 0, 1, 0, 0;
- // Creating the diamond-shaped structuring element
- diamond <<
- 0, 0, 1, 0, 0,
- 0, 1, 1, 1, 0,
- 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 0,
- 0, 0, 1, 0, 0;
- // Creating the x-shaped structuring element
- x <<
- 1, 0, 0, 0, 1,
- 0, 1, 0, 1, 0,
- 0, 0, 1, 0, 0,
- 0, 1, 0, 1, 0,
- 1, 0, 0, 0, 1;
- // Creating the square-shaped structuring element
- square <<
- 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1;
- <span style="white-space:pre"> </span> //display x-shaped structuring element
- cout<<endl<<"x-shaped structuring element"<<endl<<endl;
- int xnr = x.rows;
- int xnl = x.cols;
- for(int j = 0;j<nr;j++)
- {
- char *data = x.ptr<char>(j);
- for(int i = 0; i<nl; i++)
- {
- int value = data[i];
- cout<<value<<" ";
- }
- cout<<endl;
- }
3.开闭运算
(1)闭运算
闭运算作用
闭运算用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。基本上所有小到不能完整容纳结构元素的空隙或间隙,都会被闭运算消除(即连起来)。
- cv::Mat element5(5,5,CV_8U,cv::Scalar(1));//5*5正方形,8位uchar型,全1结构元素
- cv::Mat closed;
- cv::morphologyEx(image, closed,cv::MORPH_CLOSE,element5);//高级形态学运算函数
- // Display the opened image
- cv::namedWindow("Closed Image");
- cv::imshow("Closed Image",closed);
- cv::waitKey(0);
5×5正方形结构元素闭运算结果
(2)开运算
开运算定义 先腐蚀后膨胀
开运算作用
用来背景中的消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。所有小到不能容纳结构元素的物体都会被移除。
- cv::Mat element5(5,5,CV_8U,cv::Scalar(1));//5*5正方形,8位uchar型,全1结构元素
- cv::Mat opened;
- cv::morphologyEx(image, opened,cv::MORPH_OPEN,element5);
- // Display the opened image
- cv::namedWindow("Opened Image");
- cv::imshow("Opened Image",opened);
- cv::waitKey(0);
5×5正方形结构元素开运算结果