精华内容
下载资源
问答
  • 形态学滤波

    2015-06-06 08:59:21
    基于VISUAL STUDIO 2008和OPENCV实现形态学滤波
  • //形态滤波时最大的窗口大小 pmf.setSlope (slope); //计算高度阈值时所用的坡度 pmf.setInitialDistance (initial_d); //距离预估地面的初始高度 pmf.setMaxDistance (max_d); //距离预估地面的最大高度 pmf....
  • MATLAB实现形态学滤波

    2018-04-17 12:58:49
    用MATLAB代码实现形态学滤波,包括形态学中各种运算方法。
  • 矢量自对偶形态学滤波算子
  • 形态学滤波matlab程序

    2018-03-20 17:21:23
    自己写的matlab形态学滤波function函数,方便调用,且实用
  • 基于形态学滤波去噪matlab代码
  • opencv 形态学滤波

    2017-09-06 22:43:46
    opencv 形态学滤波
    #include<opencv2/opencv.hpp>
    #include<iostream>
    
    using namespace cv;
    using namespace std;
    
    int main() {
    	Mat a = imread("D:\\10.jpeg");
    	Mat element = getStructuringElement(MORPH_RECT,Size(13, 13), Point(6, 6));
    	Mat dst1,dst2,dst3,dst4,dst5;
    	morphologyEx(a, dst1,MORPH_OPEN, element);//开运算
    	morphologyEx(a, dst2, MORPH_CLOSE, element);//闭运算
    	morphologyEx(a, dst3, MORPH_TOPHAT, element);//顶帽
    	morphologyEx(a, dst4, MORPH_BLACKHAT, element);//黑帽运算
    	morphologyEx(a, dst5, MORPH_GRADIENT, element);//形态学运算
    
    
    	imshow("原图", a);
    	imshow("开运算", dst1);
    	imshow("闭运算", dst2);
    	imshow("顶帽", dst3);
    	imshow("黑帽", dst4);
    	imshow("形态学", dst5);
    	waitKey(0);
    	return 0;
    
    }

    展开全文
  • 形态学滤波算法的提出,在很大程度上提高了雷达点云的滤波效果。准确高效地分离地面点和地物点,是滤波算法的关键,其中滤波阈值的确定更是学者研究的重点。等值线是空间分析中重要的研究内容。基于渐进形态学滤波算法,...
  • 形态学滤波,几何腐蚀与膨胀相关.pdf
  • 基于FPGA的图像形态学滤波算法及实现 ,马佳艺,宋欢,本文分析传统的形态学滤波原理,并根据现有的顺序滤波方法,提出改进的形态学滤波算法,在合理地利用硬件资源的基础上,有效地挖
  • 基于形态学滤波和邻域搜索的掌纹主线提取方法
  • 该方法用同态滤波和形态学滤波的方法增强了模糊操作的图像边缘, 分析了离焦模糊和人工模糊边界特点, 利用离焦模糊和人工模糊的边缘特性实现了针对数字图像伪造的被动盲取证; 实验表明,该方法能够有效地检测伪造数字...
  • 提出了一种基于区域预测的LiDAR 点云数据形态学滤波算法,该算法由点云数据建立规则格网、去除粗差点,对实验区域进行分块,然后使用各个分块区域的高程标准差预测地形坡度参数s 从而进行渐进式形态学滤波,最终确定...
  • 基于多尺度形态学滤波的CT图像疑似肺结节提取
  • 一维数学形态学滤波示例程序-mathematical_morphology_1d.rar 自己编写的一维数学形态学滤波示例程序
  • 为深入了解此类型算法,对国内外现有的基于数学形态学的点云滤波法进行系统总结,详细分析了各种方法的特点、可解决的问题及存在的问题,并结合现有基于数学形态学滤波法的主要缺陷展望了此类型算法的发展方向。
  • Task07 OpenCV框架实现形态学滤波一、前言二、形态学概述三、基本形态学操作3.1腐蚀3.2膨胀四、高级形态学操作4.1开闭运算4.2形态学梯度4.3黑帽顶帽五、基于OpenCV的C++代码实现 一、前言 图像形态学滤波是图像滤波...

    一、前言

    图像形态学滤波是图像滤波的一个重要分支,与之前介绍过的空间域滤波(方框滤波、高斯滤波、中值滤波)以及图像边缘提取过程中的滤波相同的是,他们都是通过滤波算子掩膜计算图像(中心)像素点的过程,不同的是滤波算子(内核)和计算方式,概括如下:

    • 形态学滤波:采用结构元素(Structure element)作为内核,中心像素是通过内核区域集合运算得到的。
    • 空域平滑、锐化滤波:采用卷积元素(Convolution element)作为内核,中心像素通过内核区域算数运算(有积分、微分等)得到的。

    总体来说,图像的形态学操作是基于形状的一系列图像处理操作,在OpenCV中对图像的形态学变换提供了方便快捷的函数,包括基本形态学操作和高级形态学操作。

    二、形态学概述

    图像形态学,也叫做数学形态学(Mathematical morphology) 是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论,在图像处理中占有相当重要的地位。

    在图像处理中,对于图像形态学的应用相当的广泛,主要应用在对于图像的预处理操作当中,尤其是在对二值图像的预处理和分析方面。

    结构元素
    形态学滤波最主要特征在集合运算,而集合运算是通过由0/1组成的不同形态的结构元素实现的,首先明确结构元素的概念:
    结构元素是由元素为1或者0的矩阵组成,结构元素为1的区域定义了图像的邻域,领域内的像素在进行态学操作时要进行考虑。一般来说,二维或者平面结构的结构元素要比处理的图像小得多。结构元素的中心像素,即结构元素的原点,与输入图像中感兴趣的像素值(即要处理的像素值)相对应。

    OpenCV中获取结构元素的函数为getStructuringElement,原型为:

    Mat getStructuringElement(int shape,  //内核的形状
    						  Size esize,  //内核的尺寸
    						  Point anchor = Point(-1, -1) //锚点的位置						  )
    

    内核的形状,有三种形状可以选择。

    • 矩形:MORPH_RECT;
    • 交叉形:MORPH_CROSS;
    • 椭圆形:MORPH_ELLIPSE;

    三、基本形态学操作

    基本形态学操作有腐蚀和膨胀,在腐蚀和膨胀上面通过不同运算方式可得到高级形态学操作,其主要作用有:

    • 消除噪声(低尺寸结构元素的腐蚀操作很容易去掉分散的椒盐噪声点)
    • 分割出独立的图像元素(腐蚀),在图像中连接相邻的元素(膨胀)
    • 寻找图像中明显的极大值区域或极小值区域
    • 求出图像的梯度
    • 图像轮廓提取、图像分割、寻找图像中的明显的极大值区域或极小值区域等

    【注】:OpenCV里面的腐蚀和膨胀操作是针对白色目标区域

    3.1腐蚀

    腐蚀:用结构元素的中心点对准当前正在遍历的这个像素,然后取当前结构元素所覆盖下的原图对应区域内的所有像素的最小值,用这个最小值替换当前像素值,删除对象边界的某些像素,使二值图像减小一圈

    腐蚀是一种最大值滤波,即用结构元素内的最大值去替换锚点的像素值,具体操作为:

    1. 用结构元素,扫描图像的每一个像素

    2. 用结构元素与其覆盖的二值图像做 “与”操作

    3. 如果都为1,结果图像的该像素为1。否则为0,也就是查找被处理图像中能不能找到和结构元素相同的矩阵。如果存在那么中心点所对应的点就为1,否则为0

    简单来说,就是腐蚀图像白色边缘(像素值为1)缩小一圈,图示如下:
    在这里插入图片描述
    若图中原始图像边界点像素为src(x,y),采用结构元素element(x’,y’)处理后得到dst(x,y),公式表述为:
    dst(x,y)=max(x,y):element(x,y)0src(x+x,y+y)dst(x,y)=\underset{(x',y'):element(x',y')\neq 0}{max}src(x+x',y+y')

    在OpenCV中进行腐蚀操作可以采用函数erode(),或者采用morphologyEx() 函数并输出需要进行的形态学操作类型。如下为erode()函数原型:

    void erode(InputArray src,  //原始图像
        	   OutputArray dst, //目标图像,和源图片有一样的尺寸和类型
       		   InputArray kernel, //内核,可以使用getStructuringElement来创建结构元素
               Point anchor=Point(-1,-1), //锚点的位置,其有默认值(-1,-1),表示锚位于中心
               int iterations=1,  //迭代使用该函数的次数,默认值为1
               int borderType=BORDER_CONSTANT,  //用于推断图像外部像素的某种边界模式,默认值BORDER_DEFAULT
               const Scalar& borderValue=morphologyDefaultBorderValue()  //当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),
                )
    

    3.2膨胀

    膨胀:用结构元素的中心点对准当前正在遍历的这个像素,然后取当前结构元素所覆盖下的原图对应区域内的所有像素的最大值,用这个最大值替换当前像素值,给图像中的对象边界添加像素,使图像扩大一圈

    膨胀是一种最小值滤波,即用结构元素内的最小值去替换锚点的像素值,具体操作:

    1. 用结构元素,扫描图像的每一个像素

    2. 用结构元素与其覆盖的二值图像做 “与”操作

    3. 如果都为0,结果图像的该像素为0。否则为1
      也就是在结构元素覆盖范围下,只要有一个像素符和结构元素像素相同,那么中心点对应点就为1,否则为0

    简单来说,就是膨胀图像边缘白色(像素值为1)扩大一圈,图示如下:
    在这里插入图片描述
    类似上,公式表述为:
    dst(x,y)=min(x,y):element(x,y)0src(x+x,y+y)dst(x,y)=\underset{(x',y'):element(x',y')\neq 0}{min}src(x+x',y+y')

    在OpenCV中进行膨胀操作可以采用函数dilate(),或者采用morphologyEx() 函数并输出需要进行的形态学操作类型。如下为cv::dilate()的函数原型,和erode类似

    void dilate(InputArray src,  //原始图像
        	    OutputArray dst, //目标图像,和源图片有一样的尺寸和类型
       		    InputArray kernel, //内核,可以使用getStructuringElement来创建结构元素
                Point anchor=Point(-1,-1), //锚点的位置,其有默认值(-1,-1),表示锚位于中心
                int iterations=1,  //迭代使用该函数的次数,默认值为1
                int borderType=BORDER_CONSTANT,  //用于推断图像外部像素的某种边界模式,默认值BORDER_DEFAULT
                const Scalar& borderValue=morphologyDefaultBorderValue()  //当边界为常数时的边界值,有默认值morphologyDefaultBorderValue()
                )
    

    【注】腐蚀:删除对象边界的某些像素
              ~~~~~~~~~~膨胀:给图像中的对象边界添加像素

    四、高级形态学操作

    4.1开闭运算

    开运算:先腐蚀,再膨胀,可清除一些亮的像素点,放大局部低亮度的区域,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积。

    闭运算:先膨胀,再腐蚀,可清除一些暗的像素点,即排除小型黑洞(黑色区域)。

    4.2形态学梯度

    膨胀图与腐蚀图之差提取物体边缘,对二值图像进行这一操作可以将边缘突出出来。

    4.3黑帽顶帽

    顶帽:原图像-开运算图,突出原图像中比周围的区域
    黑帽:闭运算图-原图像,突出原图像中比周围的区域

    morphologyEx函数利用基本的膨胀和腐蚀技术,来执行更加高级形态学变换,函数原型为:

    void morphologyEx(InputArray src,  //原始图像
    			      OutputArray dst,  //目标图像
                      int op,  //形态学操作
                      InputArray kernel, //内核
                      Point anchor=Point(-1,-1), //锚点 ,其有默认值(-1,-1),表示锚位于中心
                      int iterations=1,  //迭代使用该函数的次数,默认值为1
                      int borderType=BORDER_CONSTANT,  //用于推断图像外部像素的某种边界模式,默认值BORDER_DEFAULT
                      const Scalar& borderValue=morphologyDefaultBorderValue()  //当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),
                      )
    

    表示形态学操作的类型OP可取值如下:
    在这里插入图片描述

    五、基于OpenCV的C++代码实现

    下面这段代码分为两个部分,一部分使用OpenCV自带形态学处理函数实现的,一部分使用自己构造函数实现的。
    在实现My_open开运算的同时,使用双滚动条控制结构元素的宽(W)和高(H),具体代码如下:

    #include<opencv2/opencv.hpp>
    #include<iostream>
    using namespace cv;
    //函数声明
    void my_erode(Mat& src,Mat& dst,Size dsize); 
    void my_dilate(Mat& src,Mat& dst,Size dsize);
    void my_open(Mat& src, Mat& dst, Size dsize);
    void my_close(Mat& src, Mat& dst, Size dsize);
    
    //全局定义:比较耗内存
    int h=1,w=1;
    Mat newSrc;
    Mat dst_open1;  
    
    void on_Track(int ,void*){  //回调函数
        my_open(newSrc,dst_open1,Size(2*h+1,2*w+1));
        imshow("WIN_NAME",dst_open1);
        
    }
    int main(){  //主函数
        Mat src=imread("C:/Users/Administrator/Desktop/beauty.jpg");
        Size dsize=Size(round(0.3*src.cols),round(0.3*src.rows));
        resize(src,src,dsize,0,0,CV_INTER_LINEAR);
    
        //Part1:OpenCV自带函数实现腐蚀膨胀、开闭运算、顶帽底帽等
        Mat dst_erode,dst_dilate;
        double t_beg=getTickCount();
        Mat element=getStructuringElement(MORPH_RECT,Size(7,7)); //矩形内核
        erode(src,dst_erode,element); //腐蚀:计时
        double t_end=getTickCount();
        std::cout<<"OpenCV_erode time:"<<((t_end-t_beg)*1000)/getTickFrequency()<<"ms"<<std::endl;
        
        dilate(src,dst_dilate,element);  //膨胀
        Mat dst_open;
        morphologyEx(src,dst_open,MORPH_OPEN,element);   //开运算
        /*腐蚀和膨胀也可以应用此模板,对应的参数为
        MORPH_OPEN : 开运算
        MORPH_CLOSE : 闭运算
        MORPH_ERODE : 腐蚀
        MORPH_DILATE : 膨胀
        MORPH_TOPHAT : 顶帽
        MORPH_BLACKHAT : 黑帽
        */
    
    
        //Part2:C++构造函数实现腐蚀、膨胀、开闭操作
        Mat dst_erode1(src.size(),src.type()),dst_dilate1(src.size(),src.type());
        //Size dsize(7,7);
        double t_beg1=getTickCount();
        my_erode(src,dst_erode1,Size(7,7)); //腐蚀:计时
        double t_end1=getTickCount();
        std::cout<<"My_erode time:"<<((t_end1-t_beg1)*1000)/getTickFrequency()<<"ms"<<std::endl;
        my_dilate(src,dst_dilate1,Size(7,7));
        
        //设置滚动条C++实现开运算
        int max_value=5; //设置滚动条最大值
        src.copyTo(newSrc);
        src.copyTo(dst_open1);
        namedWindow("WIN_NAME",WINDOW_AUTOSIZE); //创建窗口
        createTrackbar("h","WIN_NAME",&h,max_value,on_Track); //h滚动条
        createTrackbar("w","WIN_NAME",&w,max_value,on_Track); //w滚动条
        on_Track(0,0); //调用回调函数,并显示
        
        //进行显示、写入等操作
        waitKey(0);
        return 0;
    }
    void my_erode(Mat& src,Mat& dst,Size wsize){
        if((wsize.height%2==0) || (wsize.width%2==0)){
            printf("The length and width must be odds!");
            exit(-1);
        }
        int center_y=wsize.height/2;
        int center_x=wsize.width/2;
    
        Mat borderDst;
        copyMakeBorder(src,borderDst,center_x,center_x,center_y,center_y,BORDER_REFLECT101); //对称扩展边界
     
        for(int row=center_y;row<src.rows+center_y;row++){
            for(int col=center_x;col<src.cols+center_x;col++){
                //对模板覆盖图像区域处理
                if(src.channels() == 1){  //单通道
                    int min_Value=255;
                    for(int i=row-center_y;i<row+center_y+1;i++){
                        for(int j=col-center_x;j<col+center_x+1;j++){
                            min_Value=MIN(min_Value,borderDst.at<uchar>(i,j)); //掩膜最小值:白色区域(255)缩小一圈
                        }
                    }
                    dst.at<uchar>(row-center_y,col-center_x)=min_Value;
                }
                else{
                    for(int channel=0;channel<3;channel++){  //多通道
                        int min_Value=255;
                        //对模板覆盖图像区域处理
                        for(int i=row-center_y;i<row+center_y+1;i++){
                            for(int j=col-center_x;j<col+center_x+1;j++){
                                min_Value=MIN(min_Value,borderDst.at<Vec3b>(i,j)[channel]); //掩膜最小值:白色区域(255)缩小一圈
                            }
                        }
                        dst.at<Vec3b>(row-center_y,col-center_x)[channel]=min_Value;
                    }
                }
    
                
            }
        }
          
    }
    
    void my_dilate(Mat& src,Mat& dst,Size dsize){   //类似my_erode处理
        if(dsize.width%2 == 0 || dsize.height%2 == 0){
            printf("Kernel size do not be odds!");
            exit(-1);
        }
        int h=dsize.height/2; //row
        int w=dsize.width/2;  //col
        Mat borderSrc;
        copyMakeBorder(src,borderSrc,h,h,w,w,BORDER_REFLECT101);
    
        //对图像每一个像素遍历
        for(int row=h;row<src.rows+h;row++){
            for(int col=w;col<src.cols+w;col++){
    
                //对每一个掩膜区域逻辑处理
                if(src.channels() == 1){ //单通道
                    int max_Value=0;
                    for(int i=row-h;i<row+h+1;i++){
                        for(int j=col-w;j<col+w+1;j++){
                            max_Value=MAX(max_Value,borderSrc.at<uchar>(i,j));
                        }
                    }
                    dst.at<uchar>(row-h,col-w)=max_Value;
                }
    
                else{
                    for(int channel=0;channel<3;channel++){  //多通道
                        int max_Value=0;
                        for(int i=row-h;i<row+h+1;i++){
                            for(int j=col-w;j<col+w+1;j++){
                                max_Value=MAX(max_Value,borderSrc.at<Vec3b>(i,j)[channel]);
                            }
                        }
                        dst.at<Vec3b>(row-h,col-w)[channel]=max_Value;
                    }
                }
            }
        }
    
    }
    
    void my_open(Mat& src, Mat& dst, Size dsize) {  //开运算:先腐蚀再膨胀
    	Mat dst1;
    	src.copyTo(dst1);
    	my_erode(src, dst1,dsize);
    	my_dilate(dst1, dst,dsize);
    }
    void my_close(Mat& src, Mat& dst, Size dsize) {  //闭运算:先膨胀再腐蚀
    	Mat dst1;
    	src.copyTo(dst1);
    	my_erode(src, dst1,dsize);
    	my_dilate(dst1, dst,dsize);
    }
    
    void my_tophat(Mat src, Mat dst, Size dsize) { //顶帽:原图-开运算(注意防溢出)
    	Mat dst1;
    	src.copyTo(dst1);
    	my_open(src, dst1, dsize);
    	imshow("open", dst1);
    	for (int rows = 0; rows < src.rows; rows++) {
    		for (int cols = 0; cols < src.cols; cols++) {
                if(src.channels() == 1){
    			    dst.at<uchar>(rows, cols) = saturate_cast<uchar>(src.at<uchar>(rows, cols) - dst1.at<uchar>(rows, cols));
                }
                else{
                    dst.at<Vec3b>(rows, cols)[0] = saturate_cast<uchar>(src.at<Vec3b>(rows, cols)[0] - dst1.at<Vec3b>(rows, cols)[0]);
                    dst.at<Vec3b>(rows, cols)[1] = saturate_cast<uchar>(src.at<Vec3b>(rows, cols)[1] - dst1.at<Vec3b>(rows, cols)[1]);
                    dst.at<Vec3b>(rows, cols)[2] = saturate_cast<uchar>(src.at<Vec3b>(rows, cols)[2] - dst1.at<Vec3b>(rows, cols)[2]);
                }
            }
    	}
    	imshow("顶帽", dst);
    }
    
    
    void my_underhat(Mat src, Mat dst, Size dsize) {  //黑帽:闭运算-原图
    	Mat dst1;
    	src.copyTo(dst1);
    	my_close(src, dst1, dsize);
    	imshow("colse", dst1);
    	for (int rows = 0; rows < src.rows; rows++) {
    		for (int cols = 0; cols < src.cols; cols++) {
                if(src.channels() == 1){
    			dst.at<uchar>(rows, cols) = saturate_cast<uchar>(dst1.at<uchar>(rows, cols) - src.at<uchar>(rows, cols));
                }
                else{
                    dst.at<Vec3b>(rows, cols)[0] = saturate_cast<uchar>(dst1.at<Vec3b>(rows, cols)[0] - src.at<Vec3b>(rows, cols)[0]);
                    dst.at<Vec3b>(rows, cols)[1] = saturate_cast<uchar>(dst1.at<Vec3b>(rows, cols)[1] - src.at<Vec3b>(rows, cols)[1]);
                    dst.at<Vec3b>(rows, cols)[2] = saturate_cast<uchar>(dst1.at<Vec3b>(rows, cols)[2] - src.at<Vec3b>(rows, cols)[2]);
                }
            }
    	}
    	namedWindow("黑帽", CV_WINDOW_AUTOSIZE);
    	imshow("黑帽", dst);
    }
    

    滚动条控制内核kernel的W和H得到开运算目标图像,显示如下:
    在这里插入图片描述
    其他效果续更…

    参考博客:
    【1】【OpenCV(C++)】图像处理:形态学滤波
    【2】形态学操作——腐蚀膨胀、开闭运算、顶帽变换底帽变换 c++实现

    展开全文
  • 若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 ...本文章博客地址: OpenCV开发笔记(二十五):算法基础之形态学滤波-形态学梯度 ...本篇章学习形态学滤波-形态学梯度...

    若该文为原创文章,未经允许不得转载
    原博主博客地址:https://blog.csdn.net/qq21497936
    原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
    本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104622745
    各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

    红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)

    OpenCV开发专栏(点击传送门)

    上一篇:OpenCV开发笔记(二十四):算法基础之形态学滤波-闭运算

    下一篇:OpenCV开发笔记(二十六):算法基础之形态学滤波-顶帽(礼帽)

     

    前言

    本篇章学习形态学滤波-形态学梯度。

     

    Demo

     

    形态学梯度

    概述

           形态学梯度(Morphological Gradient)是膨胀(被减数)和腐蚀(减数)的差别,结果看上去就像前景物体的轮廓。

           形态学梯度可以保留物体的边缘轮廓。

    减法函数原型

    void subtract( InputArray src1,
                InputArray src2,
                OutputArray dst,
                InputArray mask = noArray(),
                int dtype = -1);
    
    • 参数一:InputArray类型,一般是cv::Mat,被减数;
    • 参数二:InputArray类型,一般是cv::Mat,减数;
    • 参数三;OutputArray类型,输出的目标图像,和原图像有一样的尺寸和类型;
    • 参数四:掩码可选操作掩码;这是一个8位单通道数组,指定元素;要更改的输出数组;
    • 参数五:数据类型输出阵列的可选深度;

     

    Demo源码

    void OpenCVManager::testMorphologicalGradient()
    {
        QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/2.jpg";
        cv::Mat srcMat = cv::imread(fileName1.toStdString());
    
        cv::resize(srcMat, srcMat, cv::Size(400, 300));
    
        cv::String windowName = _windowTitle.toStdString();
        cvui::init(windowName);
    
        if(!srcMat.data)
        {
            qDebug() << __FILE__ << __LINE__
                     << "Failed to load image:" << fileName1;
            return;
        }
    
        cv::Mat dstMat;
        dstMat = cv::Mat::zeros(srcMat.size(), srcMat.type());
        cv::Mat windowMat = cv::Mat(cv::Size(dstMat.cols * 2, dstMat.rows * 3),
                                    srcMat.type());
        int share1 = 2;
        int ksize1 = 5;
        int iterations1 = 1;
        int share2 = 2;
        int ksize2 = 5;
        int iterations2 = 1;
        while(true)
        {
            windowMat = cv::Scalar(0, 0, 0);
            // 原图先copy到左边
            cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows),
                                        cv::Range(0, srcMat.cols));
            cv::addWeighted(leftMat, 1.0f, srcMat, 1.0f, 0.0f, leftMat);
    
    
            cvui::window(windowMat, dstMat.cols * 2, 0, dstMat.cols, dstMat.rows, "erode");
            // 中间为调整滤波参数的相关设置
            cvui::printf(windowMat, 400 * 1 + 100, 40 + 300, "share");
            cvui::trackbar(windowMat, 400 * 1 + 100, 60 + 300, 200, &share1, 0, 2);
            // 中间为调整滤波参数的相关设置
            cvui::printf(windowMat, 400 * 1 + 100, 120 + 300, "ksize");
            cvui::trackbar(windowMat, 400 * 1 + 100, 140 + 300, 200, &ksize1, 1, 10);
            // 中间为调整滤波参数的相关设置
            cvui::printf(windowMat, 400 * 1 + 100, 200 + 300, "iterations");
            cvui::trackbar(windowMat, 400 * 1 + 100, 220 + 300, 200, &iterations1, 0, 10);
    
            cvui::window(windowMat, dstMat.cols * 2, 0, dstMat.cols, dstMat.rows, "dilate");
            // 中间为调整滤波参数的相关设置
            cvui::printf(windowMat, 400 * 1 + 100, 40 + 300 * 2, "share");
            cvui::trackbar(windowMat, 400 * 1 + 100, 60 + 300 * 2, 200, &share2, 0, 2);
            // 中间为调整滤波参数的相关设置
            cvui::printf(windowMat, 400 * 1 + 100, 120 + 300 * 2, "ksize");
            cvui::trackbar(windowMat, 400 * 1 + 100, 140 + 300 * 2, 200, &ksize2, 1, 10);
            // 中间为调整滤波参数的相关设置
            cvui::printf(windowMat, 400 * 1 + 100, 200 + 300 * 2, "iterations");
            cvui::trackbar(windowMat, 400 * 1 + 100, 220 + 300 * 2, 200, &iterations2, 0, 10);
    
            cv::Mat tempMat1;
            cv::Mat tempMat2;
            // 膨胀
            cv::dilate(srcMat,
                       tempMat1,
                       cv::getStructuringElement(share1, cv::Size(ksize1, ksize1)),
                       cv::Point(-1, -1),
                       iterations1);
    
            // 效果图copy
            cv::Mat leftMat2 = windowMat(cv::Range(srcMat.rows, srcMat.rows * 2),
                                         cv::Range(0, srcMat.cols));
            cv::addWeighted(leftMat2, 0.0f, tempMat1, 1.0f, 0.0f, leftMat2);
    
            // 腐蚀
            cv::erode(srcMat,
                      tempMat2,
                      cv::getStructuringElement(share2, cv::Size(ksize2, ksize2)),
                      cv::Point(-1, -1),
                      iterations2);
    
            // 效果图copy
            cv::Mat leftMat3 = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                                         cv::Range(0, srcMat.cols));
            cv::addWeighted(leftMat3, 0.0f, tempMat2, 1.0f, 0.0f, leftMat3);
    
            // 减法:第四个参数必须要cv::Mat(),至少不能为空
            cv::subtract(tempMat1, tempMat2, dstMat, cv::Mat());
    
    
            // 效果图copy
            cv::Mat rightMat1 = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
                                          cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::addWeighted(rightMat1, 0.0f, dstMat, 1.0f, 0.0f, rightMat1);
            // 更新
            cvui::update();
            // 显示
            cv::imshow(windowName, windowMat);
            // esc键退出
            if(cv::waitKey(25) == 27)
            {
                break;
            }
        }
    }
    

     

    工程模板:对应版本号v1.20.0

           对应版本号v1.20.0

     

    上一篇:OpenCV开发笔记(二十四):算法基础之形态学滤波-闭运算

    下一篇:OpenCV开发笔记(二十六):算法基础之形态学滤波-顶帽(礼帽)

     

    原博主博客地址:https://blog.csdn.net/qq21497936
    原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
    本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104622745

    展开全文
  • 提出一种结合形态学滤波和Hough变换提取掌纹主线的方法,在对方向性掌纹线特征子图像做形态学滤波后,将滤波图像转换至Hough变换参数空间,利用Hough变换具有的点线对偶性,检测参数空间内累加数组的峰值来确定主线的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,493
精华内容 597
关键字:

形态学滤波