美文网首页
形态学操作

形态学操作

作者: samychen | 来源:发表于2018-02-09 01:08 被阅读0次

      图像形态学操作是基于形状的一系列图像处理操作的合集,主要是基于集合论基础上的形态学数学。主要有四个操作:膨胀,腐蚀,开,闭。

    形态学操作——膨胀

      膨胀与腐蚀跟卷积操作类似,假设有图像A和结构元素B,B在A上面移动,其中B定义其中心是锚点,计算B覆盖下的A的最大像素值用来替代锚点的像素,其中B作为结构元素可以是任意形状。

    形态学操作——腐蚀

      腐蚀过程和膨胀过程类似,唯一不同的是以最小像素值替代锚点像素。


    膨胀与腐蚀.png
    • 获取结构元素 getStructuringElement(int shape,Size ksize,Point anchor) 其中形状shape可以是MORPH_RECT,MORPH_CROSS,MORPH_ELLIPSE,锚点默认是Point(-1,-1),意思是中心元素。
    • 膨胀 dilate(src,dst,kernel)
    • 腐蚀 erode(src,dst,kernel)
      image.png

      opencv提供了状态条TrackBar来动态调整结构元素大小。
    createTrackBar(const String& trackbarname,const String windowname,int * value,int count,Trackbarcallback func,void * userdata=0) 回调函数如果为NULL,就只会update,不会调用callback函数。

    #include "stdafx.h"
    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace cv;
    int elementsize = 3;
    int maxsize = 21;
    Mat src, dst, dst_;
    void callback(int, void *);
    
    int main(int argc, int ** argv)
    {
        int ksize = 0;
        src = imread("F:/cat.png");
        if (!src.data) {
            printf("无法加载图片\n");
            return -1;
        }
        namedWindow("input img", CV_WINDOW_AUTOSIZE);
        imshow("show img", src);
        char TrackbarName[50];
        sprintf_s(TrackbarName, "Alpha x %d", elementsize);
        namedWindow("output result", CV_WINDOW_AUTOSIZE);
        createTrackbar(TrackbarName, "output result", &elementsize, maxsize, callback);
        callback(0, 0);
        //Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
        //dilate(src, dst, kernel);
        //erode(src, dst_, kernel);
        //namedWindow("dilate result", CV_WINDOW_AUTOSIZE);
        //namedWindow("erode result", CV_WINDOW_AUTOSIZE);
        //imshow("dilate", dst);
        //imshow("erode", dst_);
        waitKey(0);
        return 0;
    }
    
    void callback(int, void *)
    {
        int s = elementsize * 2 + 1;
        Mat sturctEle = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
        dilate(src, dst, sturctEle);
        //erode(src, dst_, sturctEle);
        imshow("dilate", dst);
        //imshow("erode", dst_);
        return;
    }
    

    输出结果演示


    image.png

    形态学操作——开操作

      先腐蚀后膨胀,可以去掉小的对象


    image.png

    形态学操作——闭操作

      先膨胀后腐蚀,可以填充小对象


    image.png

    形态学梯度

      膨胀减去腐蚀


    image.png

    形态学操作——顶帽

      顶帽是原图像与开操作图像之间的差值图像


    image.png

    形态学操作——黑帽

      黑帽是闭操作图像与原图像之间的差值图像


    image.png
    #include "stdafx.h"
    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace cv;
    Mat src, dst;
    int main(int argc, int ** argv)
    {
        src = imread("F:/black_hole.png");
        if (!src.data) {
            printf("无法加载图片\n");
            return -1;
        }
        namedWindow("input img", CV_WINDOW_AUTOSIZE);
        imshow("show img", src);
        Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
        //morphologyEx(src, dst, CV_MOP_OPEN, kernel);
        //morphologyEx(src, dst, CV_MOP_CLOSE, kernel);
        //morphologyEx(src, dst, CV_MOP_GRADIENT, kernel);
        //morphologyEx(src, dst, CV_MOP_TOPHAT, kernel);
        morphologyEx(src, dst, CV_MOP_BLACKHAT, kernel);
    
        namedWindow("output result", CV_WINDOW_AUTOSIZE);
        imshow("erode", dst);
        waitKey(0);
        return 0;
    }
    
    

    morphologyEx(Mat src,Mat dst,int opt,kernel)
    其中opt是形态学操作,可以为CV_MOP_OPEN,CV_MOP_CLOSE,CV_MOP_GRADIENT,CV_MOP_TOPHAT,CV_MOP_BLACKHAT

    形态学应用

    提取水平和垂直线

      可以通过自定义结构元素实现结构元素对输入图像一些对象敏感,一些对象不敏感,这样就会让敏感对象改变而不敏感对象保留输出。通过使用膨胀与腐蚀,使用不同的结构元素来得到不同的结果。

    操作步骤:

    • 输入图像转换为灰度图像
    • 灰度图像转换为二值图像
    • 定义结构元素
    • 开操作提取水平与垂直线
    #include "stdafx.h"
    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace cv;
    Mat src, dst;
    int main(int argc, int ** argv)
    {
        src = imread("F:/line.png");
        if (!src.data) {
            printf("无法加载图片\n");
            return -1;
        }
        namedWindow("input img", CV_WINDOW_AUTOSIZE);
        Mat gray;
        cvtColor(src, gray, CV_BGR2GRAY);
        imshow("gray img", gray);
        Mat binImg;
        adaptiveThreshold(~gray, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
        imshow("binary img", binImg);
    
        Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols/16, 1), Point(-1, -1));
        Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows/16), Point(-1, -1));
        Mat temp;
        //erode(binImg, temp, hline);
        //dilate(temp, dst, hline);
        erode(binImg, temp, vline);
        dilate(temp, dst, vline);
        bitwise_not(dst, dst);
        imshow("final result", dst);
        waitKey(0);
        return 0;
    }
    
    
    
    水平线.png 垂直线.png

    扩展:去除打码平台无用的线条

    image.png
    #include "stdafx.h"
    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace cv;
    Mat src, dst;
    int main(int argc, int ** argv)
    {
        src = imread("F:/number.png");
        if (!src.data) {
            printf("无法加载图片\n");
            return -1;
        }
        namedWindow("input img", CV_WINDOW_AUTOSIZE);
        Mat gray;
        cvtColor(src, gray, CV_BGR2GRAY);
        imshow("gray img", gray);
        Mat binImg;
        adaptiveThreshold(~gray, binImg, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
        imshow("binary img", binImg);
        Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols/16, 1), Point(-1, -1));
        Mat vline = getStructuringElement(MORPH_RECT, Size(1, src.rows/16), Point(-1, -1));
        Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
        Mat temp;
    
        erode(binImg, temp, kernel);
        dilate(temp, dst, kernel);
        bitwise_not(dst, dst);
        imshow("final result", dst);
        waitKey(0);
        return 0;
    }
    
    
    

    相关文章

      网友评论

          本文标题:形态学操作

          本文链接:https://www.haomeiwen.com/subject/biwnzxtx.html