基本形态学操作:
- 腐蚀 (Erosion)
- 膨胀 (Dilation)
其他形态学操作:
- 开运算 (Opening)
- 闭运算 (Closing)
- 形态梯度 (Morphological Gradient)
- 顶帽 (Top Hat)
- 黑帽(Black Hat)
腐蚀与膨胀:
腐蚀操作描述为:扫描图像的每一个像素,用结构元素与其覆盖的二值图像做“与”操作:如果都为1,结果图像的该像素为1,否则为0。
膨胀操作描述为:扫描图像的每一个像素,用结构元素与其覆盖的二值图像做“与”操作:如果都为0,结果图像的该像素为0,否则为1。
以上都是关于二值图像的形态学操作,对于灰度图像:
-
腐蚀操作
其中,g(x,y)为腐蚀后的灰度图像,f(x,y)为原灰度图像,B为结构元素。腐蚀运算是由结构元素确定的邻域块中选取图像值与结构元素值的差的最小值。
-
膨胀操作
其中,g(x,y)为腐蚀后的灰度图像,f(x,y)为原灰度图像,B为结构元素。 膨胀运算是由结构元素确定的邻域块中选取图像值与结构元素值的和的最大值。
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
Mat srcImage,dstImage;
int g_TrackBarValue = 0;
int g_StructElementSize = 3;
//回调函数
void Process(){
Mat element = getStructuringElement(MORPH_RECT,
Size(g_StructElementSize *2+1,g_StructElementSize*2+1),
Point(g_StructElementSize,g_StructElementSize));
if(g_TrackBarValue){
erode(srcImage,dstImage,element);
}
else{
dilate(srcImage,dstImage,element);
}
imshow("效果图像",dstImage);
}
void on_TrackbarNumChange(int ,void *){
Process();
}
void on_ElementSizeChange(int, void *){
Process();
}
int main(int argc,char **argv){
//载入一张图片
srcImage = imread("img.jpg");
if(!srcImage.data){
cout<<"input error!"<<endl;
return 0;
}
namedWindow("原始图像");
imshow("原始图像",srcImage);
namedWindow("效果图像");
//初识化
Mat element = getStructuringElement(MORPH_RECT,
Size(g_StructElementSize *2+1,g_StructElementSize*2+1),
Point(g_StructElementSize,g_StructElementSize));
dilate(srcImage,dstImage,element);
imshow("效果图像",dstImage);
//创建滑动块
createTrackbar("erode/dilate","效果图像",&g_TrackBarValue,1,on_TrackbarNumChange);
createTrackbar("size","效果图像",&g_StructElementSize,21,on_ElementSizeChange);
while(char(waitKey(1)!='q')){}
return 0;
}
膨胀图像:
腐蚀图像:
其他形态学操作:
-
开运算是通过先对图像腐蚀再膨胀实现的。
-
闭运算是通过先对图像膨胀再腐蚀实现的。
-
形态学梯度:膨胀图与腐蚀图之差
-
顶帽:原图像与开运算结果图之差
-
黑帽:闭运算结果图与原图像之差
运行形态学操作的核心函数是 morphologyEx 。
- src : 原 (输入) 图像
- dst: 输出图像
- operation: 需要运行的形态学操作。 我们有7个选项:
-
- Dilate:MORPH_DILATE:0
- Erode:MORPH_ERODE:1
- Opening: MORPH_OPEN : 2
- Closing: MORPH_CLOSE: 3
- Gradient: MORPH_GRADIENT: 4
- Top Hat: MORPH_TOPHAT: 5
- Black Hat: MORPH_BLACKHAT: 6
- element: 内核,可以使用函数:get_structuring_element:getStructuringElement <> 自定义。
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#define WINDOWNAME "效果图"
using namespace std;
using namespace cv;
//全局变量
int g_kernelsize = 0;
int g_elment = 0;
int g_operater = 0;
const int g_maxsize = 21;
const int g_maxelment = 2;
const int g_maxoperater = 6;
Mat srcImage,dstImage;
//创建回调函数
void on_Morphology(int,void *){
Mat elment = getStructuringElement(g_elment,
Size(g_kernelsize*2+1,g_kernelsize*2+1),
Point(g_kernelsize,g_kernelsize));
morphologyEx(srcImage,dstImage,g_operater,elment);
imshow(WINDOWNAME,dstImage);
}
int main(int argc,char **argv){
//载入一张图像
srcImage = imread("1.jpg");
if(!srcImage.data){
cout<<"input error!";
return 0;
}
imshow("原始图像",srcImage);
dstImage.create(srcImage.size(),srcImage.type());
//创建显示形态学操作的窗口
namedWindow(WINDOWNAME);
//选择形态学操作的方法
createTrackbar("Operator:",WINDOWNAME,&g_operater,g_maxoperater,on_Morphology);
//指定内核形状
createTrackbar("Element:",WINDOWNAME,&g_elment,g_maxelment,on_Morphology);
//指定内核大小
createTrackbar("Kernel size:",WINDOWNAME,&g_kernelsize,g_maxsize,on_Morphology);
//启动默认值
on_Morphology(0,0);
//程序结束操作
while(char(waitKey(0)) == 'q') break;
return 0;
}
腐蚀:
膨胀:
开运算:
闭运算:
形态学梯度:
顶帽:
黑帽: