OpenCv形态学操作

来源:互联网 发布:模型分析软件 编辑:程序博客网 时间:2024/05/23 19:06

函数介绍


在常用的腐蚀和膨胀基础上,常使用**morphology()**函数.

该方法支持常用的灰度图或是彩色图像(会分单通道处理)

  " morphologyEx函数的参数声明 "void morphologyEx( InputArray src,    //输入图像OutputArray dst,   //输出图像int op,    //表示形态学操作的标识InputArray kernel,  //自定义核Point anchor=Point(-1,-1),   //核锚点int iterations=1,   //操作迭代次数int borderType=BORDER_CONSTANT,//图像边界像素填充类型(默认为常数,配合borderValue参数)const Scalar& borderValue=morphologyDefaultBorderValue() );

op参数:

MORPH_ERODE   -->"腐蚀操作"MORPH_DILATE  -->"膨胀操作"MORPH_OPEN(MORPH_OPEN)    -->"开运算"CV_MOP_CLOSE(MORPH_CLOSE)   -->"闭运算"CV_MOP_GRADIENT(MORPH_GRADIENT)  -->"形态梯度"CV_MOP_TOPHAT(MORPH_TOPHAT)   -->"礼帽"CV_MOP_BLACKHAT(MORPH_BLACKHAT)  -->"黑帽"

kernel参数:
默认参数为NULL,表示使用系统提供的3×3内核,锚点为中心位置。
常常使用自定义内核,使用函数getStructuringElement()生成我们想要的核矩阵。

Mat getStructuringElement(int shape,  //核矩阵形状Size ksize,  //尺寸Point anchor=Point(-1,-1) //锚点位置);**shape**参数:      MORPH_RECT -->"矩形"      MORPH_CROSS -->"十字形"      MORPH_ELLIPSE -->"椭圆形"**anchor**参数:      默认为Point(-1,-1)即为核中心。  对于"十字形"核中心决定核矩阵形状(十字形为单线宽)。 可以自定义一个核矩阵:    int kernel_size;  //根据实际情况赋值    Mat kernel =  getStructuringElement(MORPH_RECT,                     Size(kernel_size*2+1,kerner_size*2+1),                       Point(kernel_size,kernel_size));

其他参数可使用默认值
所有操作支持in-place(原地输出)


形态运算


  1. 开运算

    先腐蚀-->再膨胀

    • 开运算常用与分割图片(除去小的明亮区域,剩余明亮区域被隔绝)
    • 灰度图中会消除高于其邻点的孤立点。

除去黑圈中的白点


闭运算
先膨胀-->再腐蚀

  • 闭运算常用消除噪声(亮的区域连接在一起,大小基本不变)
  • 灰度图中会消除低于其邻点的孤立点。

白色的面积随着核矩阵变大而扩大

对于开闭运算的迭代的情况下(例如2次开运算)
是执行 腐蚀–>腐蚀–>膨胀–>膨胀


形态梯度运算
膨胀的图像减去腐蚀的图像

  • 梯度运算应用于灰度图,凸显出灰度变化边界值
  • 灰度图中边缘高亮突出。

边缘突出


礼帽运算
这里写图片描述

  • 开运算是放大裂缝或局部低亮度区域,进行TOPHAT操作后,可以突出局部最大值周围的区域
  • 突出轮廓周围更亮的区域
  • 常用于分割大背景配合小图片(分割出背景)


黑帽运算
闭运算-->原图

  • 突出轮廓周围更暗的区域
    - 可以分割出图像的轮廓

这里写图片描述


代码

#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/core/types_c.h>#include <iostream>#include <opencv.hpp>using namespace cv;using namespace std;void onBarChangeListener(int,void*); //trackbar回调Mat src;int kernel_size = 7;  //核心矩阵大小int Shape_Type=0;    //核矩阵形态类型int iterations = 1;  //迭代次数int main(){    namedWindow("src",0);    namedWindow("dst_open",0);    namedWindow("dst_close",0);    namedWindow("dst_gradient",0);    namedWindow("dst_tophat",0);    namedWindow("dst_blackhat",0);    src = imread("H:\\road.png");    createTrackbar("Shape","src",&Shape_Type,2,onBarChangeListener);    createTrackbar("KernelSise","src",&kernel_size,10,onBarChangeListener);    createTrackbar("Iterations","src",&iterations,14,onBarChangeListener);    waitKey(0);    return 0;}void onBarChangeListener(int,void*){    Mat dst_open,dst_close,dst_gradient,dst_tophat,dst_blackhat;    Mat kernel;    int s_type;    //保证kernel矩阵最小为3x3    kernel_size = (kernel_size==0)?1:kernel_size;      //保证iterations迭代次数最小为1    iterations = (iterations==0)?1:iterations;         switch (Shape_Type)    {    case 0:  s_type = MORPH_RECT; break;    case 1:  s_type = MORPH_CROSS; break;    case 2:  s_type = MORPH_ELLIPSE; break;    default:  s_type = MORPH_RECT; break;    } //锚点默认为中心 kernel=getStructuringElement(s_type,Size(kernel_size*2+1,kernel_size*2+1));     morphologyEx(src,dst_open,MORPH_OPEN,                 kernel,Point(-1,-1),iterations);    morphologyEx(src,dst_close,MORPH_CLOSE,                 kernel,Point(-1,-1),iterations);    morphologyEx(src,dst_gradient,MORPH_GRADIENT,                 kernel,Point(-1,-1),iterations);    morphologyEx(src,dst_tophat,MORPH_TOPHAT,                 kernel,Point(-1,-1),iterations);    morphologyEx(src,dst_blackhat,MORPH_BLACKHAT,                 kernel,Point(-1,-1),iterations);    imshow("src",src);    imshow("dst_open",dst_open);    imshow("dst_close",dst_close);    imshow("dst_gradient",dst_gradient);    imshow("dst_tophat",dst_tophat);    imshow("dst_blackhat",dst_blackhat);}

这里写图片描述

这里写图片描述


0 0
原创粉丝点击