• Opencv 基本操作三 实现各个形态学处理并实现多图展示


    opencv中包含的形态学操作共有腐蚀、膨胀、闭运算、开运算、形态学梯度、顶帽运算、黑帽运算、hitmiss运算8中。其中,腐蚀、膨胀运算是所有形态学运算基础。本文将对这些形态学操作的效果进行展示。
    腐蚀,即用模板对目标像素的领域进行匹配,如果邻域信息与模板完全匹配,则将像素点置255,否则置0。因为图形边缘区域的像素点是较难完全匹配模块的,所以通过该操作后图形边缘的像素点被删除,因此称该操作为腐蚀。
    膨胀,即用模板对目标像素的领域进行匹配,如果邻域信息与模板中任意一个像素匹配,则将像素点置255,否则置0。因为该操作,只要求部分匹配,一些黑点(像素值为0)特定邻域内存在白点(像素值为255),则被置为白点。所以通过该操作后图形的轮廓变大,因此称该操作为膨胀。

    通过对腐蚀膨胀运算的组合运算,因此得到了闭运算、开运算、形态学梯度。将原图与开运行、闭运算的结果进行异或运算,则就得到了顶帽运算和黑帽运算。取原图在进行开运行、闭运算后的不变区域则得到了hitmiss。注:hitmiss并不等于开运算与闭运算的并集,博主这里的描述只是为了近似理解。

    1、多图展示代码

    代码中的imshows函数用于多图展示,博主为了省事插入了两行与多图展示不相干的代码,即将图1与图2的异或结果添加到vector中。

    #include 
    #include 
    #include 
    #include 
     
    using namespace std;
    using namespace cv;
    
    //修改自以下链接,博主添加了pad,使两列图像边多了空格
    //https ://blog.csdn.net/Beking17113/article/details/122304671
    void multipleImage(vector<Mat> imgVector, Mat& dst, int imgCols, int MAX_PIXEL = 400)
    {
        //两列图像间的空白区域
        int pad = 10;
        int imgNum = imgVector.size();
        //选择图片最大的一边 将最大的边按比例变为300像素
        Size imgOriSize = imgVector[0].size();
        int imgMaxPixel = max(imgOriSize.height, imgOriSize.width);
        //获取最大像素变为MAX_PIXEL的比例因子
        double prop = imgMaxPixel < MAX_PIXEL ? (double)imgMaxPixel / MAX_PIXEL : MAX_PIXEL / (double)imgMaxPixel;
        Size imgStdSize(imgOriSize.width * prop, imgOriSize.height * prop); //窗口显示的标准图像的Size
    
        Mat imgStd; //标准图片
        Point2i location(0, 0); //坐标点(从0,0开始)
        //Mat imgWindow(imgStdSize.height * ((imgNum - 1) / imgCols + 1), imgStdSize.width * imgCols+ pad * imgCols-pad, imgVector[0].type());
        int imgRows = (imgNum - 1) / imgCols + 1;
        Mat imgWindow = Mat::zeros(imgStdSize.height * imgRows + pad * imgRows - pad, imgStdSize.width * imgCols + pad * imgCols - pad, imgVector[0].type());
        for (int i = 0; i < imgNum; i++)
        {
            location.x = (i % imgCols) * (imgStdSize.width+pad);
            location.y = (i / imgCols) * imgStdSize.height;
            resize(imgVector[i], imgStd, imgStdSize, prop, prop, INTER_LINEAR); //设置为标准大小
    
            //将imgStd复制到imgWindow的指定区域中
            imgStd.copyTo(imgWindow(Rect(location, imgStdSize)));
        }
        dst = imgWindow;
    }
    
    void imshows(vector<Mat> imgVector,string title, int imgCols=-1) {
        Mat dst,xor;
        //将图1与图2的异或结果也添加到输出中
        bitwise_xor(imgVector[0], imgVector[1], xor);
        imgVector.push_back(xor);
    
        if (imgCols == -1) {
            imgCols = imgVector.size();
        }
        multipleImage(imgVector,dst, imgCols);
        namedWindow(title);
        imshow(title, dst);
        imwrite(title+".png", dst);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    2、进行形态学操作

    int main(int argc, char *argv[])
    {
        Mat img = imread("D:/008945.png",0);//左侧:图片路径
        resize(img, img, { 512,512 });
        int thres_ = 0;
        cv::threshold(img, img, thres_, 255, THRESH_BINARY);//大于阈值返回 最大值 255 小于返回0
    
        Mat element = getStructuringElement(MORPH_RECT, Size(7, 7));
    
        Mat dilate_mat,erode_mat,close_mat, open_mat, grad_mat, tophat_mat, blackhat_mat, hitmiss_mat;
    
        //腐蚀==》使图形的轮廓变细
        //erode(img, erode_mat, element);
        morphologyEx(img, erode_mat, MORPH_ERODE, element);
    
        //膨胀==》使图形的轮廓变粗
        //dilate(img, dilate_mat, element);
        morphologyEx(img, dilate_mat, MORPH_DILATE, element);
    
        //闭运算==先做膨胀,在做腐蚀==》闭合小孔洞,消除毛刺
        morphologyEx(img, close_mat, MORPH_CLOSE, element);
    
        //开运算==先做腐蚀,在做膨胀==》移除小区域,使连通域断开
        morphologyEx(img, open_mat, MORPH_OPEN, element);
    
        //形态学梯度==膨胀-腐蚀==》得到物体的大概轮廓
        morphologyEx(img, grad_mat, MORPH_GRADIENT, element);
        
        //顶帽运算==原图形-开运算==》用于获取图形中的的尖角、毛刺等细小的白色区域 
        morphologyEx(img, tophat_mat, MORPH_TOPHAT, element);
    
        //黑帽运算==闭运算-原图像==》用于获取图形中的的缺口、孔洞区域等细小的黑色区域
        morphologyEx(img, blackhat_mat, MORPH_BLACKHAT, element);
    
        //hitmiss== 腐蚀图 并 原图补集的腐蚀图,简单解释为图像进行腐蚀膨胀时未发生变化的区域,也就是腐蚀膨胀都未击中的像素,从效果上看就是取图像的主体
        //hitmiss变换详情参考:https://www.pythonf.cn/read/168479
        morphologyEx(img, hitmiss_mat, MORPH_HITMISS, element);
    
        imshows({ img, erode_mat },"erode");
        imshows({ img, dilate_mat }, "dilate");
        imshows({ img, close_mat }, "close");
        imshows({ img, open_mat }, "open");
        imshows({ img, grad_mat }, "grad");
        imshows({ img, tophat_mat }, "tophat");
        imshows({ img, blackhat_mat }, "blackhat");
        imshows({ img, hitmiss_mat }, "hitmiss");
        waitKey();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    3、形态学运算效果

    下面图片中第一列是原图,第二列是效果图,第三列是原图与效果图的异或图。

    腐蚀

    morphologyEx(img, erode_mat, MORPH_ERODE, element);
    使图形的轮廓变细
    请添加图片描述

    膨胀

    morphologyEx(img, dilate_mat, MORPH_DILATE, element);
    使图形的轮廓变粗
    请添加图片描述

    闭运算

    morphologyEx(img, close_mat, MORPH_CLOSE, element);
    先做膨胀,在做腐蚀==》闭合小孔洞,消除毛刺
    请添加图片描述

    开运算

    morphologyEx(img, open_mat, MORPH_OPEN, element);
    先做腐蚀,在做膨胀==》移除小区域,使连通域断开
    请添加图片描述

    形态学梯度

    morphologyEx(img, close_mat, MORPH_GRADIENT, element);
    膨胀-腐蚀==》得到物体的大概轮廓
    请添加图片描述

    顶帽运算

    morphologyEx(img, tophat_mat, MORPH_TOPHAT, element);
    原图形-开运算==》用于获取图形中的的尖角、毛刺等细小的白色区域
    请添加图片描述

    黑帽运算

    morphologyEx(img, blackhat_mat, MORPH_BLACKHAT, element);
    闭运算-原图像==》用于获取图形中的的缺口、孔洞区域等细小的黑色区域
    请添加图片描述

    hitmiss

    morphologyEx(img, hitmiss_mat, MORPH_HITMISS, element);
    hitmiss== 腐蚀图 并 原图补集的腐蚀图,简单解释为图像进行腐蚀膨胀时未发生变化的区域,也就是腐蚀膨胀都未击中的像素,从效果上看就是取图像的主体。 hitmiss变换详情参考:https://www.pythonf.cn/read/168479
    请添加图片描述

  • 相关阅读:
    Git 常用命令指南:从入门到精通
    Linux入门第二天——linux命令(一)
    网络与TCP-IP
    java计算机毕业设计人才招聘系统智能化管理源码+mysql数据库+系统+lw文档+部署
    navicat的安装和配置教程
    [第一个 C# 程序]-C# 程序可以运行在任何一台可以打游戏的 Windows 机器上
    OneOS 下的 GUI 框架测试
    在行首,行尾添加文本,替换文本中的空格、制表符等
    《MySQL数据库进阶实战》读后感(SQL 小虚竹)
    Windows列出系统所有补丁(wmic)
  • 原文地址:https://blog.csdn.net/a486259/article/details/126427923