膨胀、腐蚀属于形态学的操作, 简单来说就是基于形状的一系列图像处理操作
膨胀腐蚀是基于高亮部分(白色)操作的, 膨胀是対高亮部分进行膨胀, 类似“领域扩张”, 腐蚀是高亮部分被腐蚀, 类似“领域被蚕食”
膨胀腐蚀的应用和功能:
消除噪声
分割独立元素或连接相邻元素
寻找图像中的明显极大值、极小值区域
求图像的梯度
其他相关:
开运算、闭运算
顶帽、黑帽
形态学梯度
#include "mainwindow.h"
#include
#include
#include
using namespace std;
using namespace cv;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
Mat srcImg=imread("1.bmp");
Mat dstImg;
Mat element=getStructuringElement(MORPH_RECT,Size(5,5),Point(-1,-1));
/*膨胀*/
//dilate(srcImg,dstImg,element,Point(-1,-1),3);
/*腐蚀*/
//erode(srcImg,dstImg,element,Point(-1,-1),3);
/*开运算*/
//morphologyEx(srcImg,dstImg,MORPH_OPEN,element);
/*闭运算---先膨胀再腐蚀*/
morphologyEx(srcImg,dstImg,MORPH_CLOSR,element);
/*形态学梯度*/
morphologyEx(srcImg,dstImg,MORPH_GRADIENT,element);
/*顶帽运算*/
morphologyEx(srcImg,dstImg,MORPH_TOPHAT,element);
/*黑帽运算*/
morphologyEx(srcImg,dstImg,MORPH_BLACKHAT,element);
imshow("srcImg",srcImg);
imshow("dstImg",dstImg);
}
MainWindow::~MainWindow()
{
}
膨胀就是求局部最大值的操作, 从数学角度上来讲, 膨胀或腐蚀就是将图像(或区域)A与核B进行卷积。
核可以是任意大小和形状, 它有一个独立定义的参考点(锚点), 多数情况下, 核是一个小的中间带参考点和实心正方形或者圆盘, 可以看做是一个模板或掩码。
膨胀是求局部最大值的操做, 核B与图形卷积, 即核B覆盖的区域的像素点的最大值, 并把这个最大值复制给参考点指定的像素, 这样就会使图像中的高亮区域逐渐增长, 如下图所示:
1. dilate
CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
ksize和anchor分别表示内核尺寸和锚点位置
矩形
交叉性
腐蚀和膨胀相反, 是取局部最小值, 高亮区域逐渐减小, 如下图所示:
CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
开运算、闭运算、顶帽、黒帽、形态学梯度
基于膨胀腐蚀基础, 利用morphologyEx()函数进行操作
1.
CV_EXPORTS_W void morphologyEx( InputArray src, OutputArray dst,
int op, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
概念
开运算是先腐蚀后膨胀的过程,
1)开运算可以用来消除小物体,
2)在纤细点处分离物体,
3)在平滑较大物体边界的同时不明显的改变其面积。
代码
morphologyEx(srcImg,dstImg,MORPH_OPEN,element);
概念
闭运算是先膨胀后腐蚀的过程, 闭运算可以用来消除小型黑洞(黑色区域)
代码
morphologyEx(srcImg,dstImg,MORPH_CLOSR,element);
运行结果
概念
形态学梯度是膨胀图与腐蚀图之差, 对二值图可以将团块(blob)边缘凸显出来来保留边缘轮廓
代码
morphologyEx(srcImg,dstImg,MORPH_GRADIENT,element);
运行结果
概念
顶帽运算也被称为”礼帽”, 是闭运算结果和原图像做差的结果, 可以用来分离比邻近点亮一些的斑块
代码
morphologyEx(srcImg,dstImg,MORPH_TOPHAT,element);
概念
黑帽运算是原图像和开运算做差的结果, 可以用来分离比邻近点暗一些的斑块。
代码
morphologyEx(srcImg,dstImg,MORPH_BLACKHAT,element);
运行结果
代码
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include
using namespace std;
using namespace cv;
const char* imgName; //图片路径名称
int thres_min; //二值化最小阈值
int main(int argc, char** argv)
{
if(argc>2)
{
imgName=argv[1];
thres_min=atoi(argv[2]); //const char*转为int类型
}
else
{
cout<<"argv must more than 2 !\n"<return 0;
}
Mat img = imread(imgName, 1);
if(!img.empty())
{
threshold(img, img, thres_min, 255, THRESH_BINARY);
imshow("img", img);
Mat Copy;
img.copyTo(Copy);
cvtColor(Copy, Copy, CV_BGR2GRAY);
threshold(Copy, Copy, thres_min, 255, THRESH_BINARY_INV);
imshow("copy", Copy);
vector<vector >contours;
findContours(Copy, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
if(contours.size()!=2)
{
cout<<"There are more than 2 walls"<return 0;
}
Mat draw;
draw = Mat::zeros(img.size(), CV_32FC1);
cout<0, Scalar(255), -2);
imshow("img2", draw);
Mat dilated, eroded;
Mat kernel=Mat::ones(21, 21, CV_8UC1);
dilate(draw, dilated, kernel, Point(-1,-1), 2, BORDER_CONSTANT);
imshow("dilate", dilated);
erode(dilated, eroded, kernel, Point(-1,-1), 2, BORDER_CONSTANT);
imshow("erode", eroded);
Mat diff;
absdiff(dilated, eroded, diff);
diff.convertTo(diff, CV_8UC1);
imshow("diff", diff);
vector<vector >contours2;
findContours(diff, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
Mat draw2;
draw2=Mat::zeros(img.size(), CV_32FC2);
drawContours(img, contours2, 0, Scalar(0,255,0), -1);
imshow("result", img);
}
else
{
cout<<"Read image error,please try again!\n"<return 0;
}
waitKey(0);
destroyAllWindows();
}