基于opencv3.4.7 编程环境win10+VS2017、ubuntu18.04+Codelite
Mat getStructuringElement(int shape, Size esize, Point anchor = Point(-1, -1));
这个函数作用是获得掩膜(类似高斯、均值模糊的卷积核),函数第一个参数表示内核(卷积核)的形状,有三种形状可以选择。
erode
以及dilate
函数之前,先定义一个Mat
类型的变量来获得getStructuringElement
函数的返回值。对于锚点的位置,有默认值Point(-1,-1)
,表示锚点位于中心点。element
形状唯一依赖锚点位置,其他情况下,锚点只是影响了形态学运算结果的偏移。void Dilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
void Erode( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL, int iterations=1 );
src
输入图像.
dst
输出图像.
element
用于膨胀的结构元素。若为NULL
, 则使用3×3
长方形的结构元素,默认NULL
iterations
膨胀的次数,默认为1
**Erode()腐蚀后Dilate()**膨胀,叫作开操作,那些离散点或游丝线、毛刺就被过滤
**Dilate()膨胀后Erode()**腐蚀,叫作闭操作,那些断裂处就被缝合。
通过
getStructuringElement
获取膨胀或者腐蚀结构,类似卷积核,膨胀是将卷积核范围内最大值赋值给中心点,腐蚀与之相反。
代码演示
利用滑动条动态调整腐蚀、膨胀力度
#include
#include
#include
#define Pic_Path "E:\\picture\\"
#define Pic_Name "13.jpg"
using namespace std;
cv::Mat src, dst,dst1;
int element_size = 0;
int max_size = 21;
void Callback_Demo(int, void*);
void Callback_Demo1(int, void*);
int main(int argc, char **argv)
{
//获取图片完整路径及名称
string pic = string(Pic_Path) + string(Pic_Name);
cout << pic << endl;
//创建窗口
cv::namedWindow("原始图片", cv::WINDOW_AUTOSIZE);
cv::namedWindow("膨胀图片", cv::WINDOW_AUTOSIZE);
cv::namedWindow("腐蚀图片", cv::WINDOW_AUTOSIZE);
//获取原始图片
src = cv::imread(pic.c_str());
cv::imshow("原始图片", src);
//创建滑动条 用于动态调整模糊值
cv::createTrackbar("膨胀调整条", "膨胀图片", &element_size, max_size, Callback_Demo);
cv::createTrackbar("膨胀调整条", "膨胀图片", &element_size, max_size, Callback_Demo);
cv::createTrackbar("腐蚀调整条", "腐蚀图片", &element_size, max_size, Callback_Demo1);
//先调用一次回调函数 显示原始图片 否则函数启动时膨胀窗口不显示图片
Callback_Demo(0, 0);
Callback_Demo1(0, 0);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
void Callback_Demo(int, void*)
{
//定义size随着滑动条的数据增长 倍率为*2+1
int s = element_size * 2 + 1;
//获得膨胀或者腐蚀的核心 类似卷积核
//参数1 卷积形状
//参数2 卷积区域
//参数3 默认 -1 -1 卷积核中心
cv::Mat structuringelement = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(s, s),cv::Point(-1, -1));
//膨胀函数
//参数1 原图像
//参数2 目标图像
//参数3 卷积核
//参数4 锚点位置 一般为-1 -1 表示中心
//参数5
cv::dilate(src, dst, structuringelement, cv::Point(-1, -1), 1);
cv::imshow("膨胀图片",dst);
return;
}
void Callback_Demo1(int, void*)
{
//定义size随着滑动条的数据增长 倍率为*2+1
int s = element_size * 2 + 1;
//获得膨胀或者腐蚀的核心 类似卷积核
//参数1 卷积形状
//参数2 卷积区域
//参数3 默认 -1 -1 卷积核中心
cv::Mat structuringelement = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(s, s), cv::Point(-1, -1));
//膨胀函数
//参数1 原图像
//参数2 目标图像
//参数3 卷积核
//参数4 锚点位置 一般为-1 -1 表示中心
//参数5
cv::erode(src, dst1, structuringelement, cv::Point(-1, -1), 1);
cv::imshow("腐蚀图片",dst1);
return;
}
高级形态学变换:
开运算:
先腐蚀,再膨胀,可清除一些小东西(亮的),放大局部低亮度的区域
闭运算:
先膨胀,再腐蚀,可清除小黑点
形态学梯度:
膨胀图与腐蚀图之差,提取物体边缘
顶帽:
原图像-开运算图,突出原图像中比周围亮的区域
黑帽:
闭运算图-原图像,突出原图像中比周围暗的区域腐蚀用于分割(isolate)独立的图像元素,
膨胀用于连接(join)相邻的元素腐蚀、膨胀可用于去噪(低尺寸结构元素的腐蚀操作很容易去掉分散的椒盐噪声点),图像轮廓提取、图像分割、寻找图像中的明显的极大值区域或极小值区域等,腐蚀和膨胀是最基本的形态学算子
结构元素
就相当于我们在滤波中所涉及到的模板(卷积核),也就是说它是一个给定像素的矩阵,这个矩阵可以是任意形状的,一般情况下都是正方形,圆形或者菱形的但是在结构元素中有一个中心点(也叫做anchor point)。和模板中心一样,处理后的结果赋值给和这个中心点对齐的像素点。处理的过程也是基本相同。结构元素和卷积模板的区别在于,膨胀是以集合运算为基础的,卷积是以算数运算为基础的。(OpenCV里面的腐蚀膨胀都是针对白色目标区域的)
膨胀:用结构元素的中心点对准当前正在遍历的这个像素,然后取当前结构元素所覆盖下的原图对应区域内的所有像素的最大值,用这个最大值替换当前像素值,给图像中的对象边界添加像素,使二值图像扩大一圈
腐蚀:用结构元素的中心点对准当前正在遍历的这个像素,然后取当前结构元素所覆盖下的原图对应区域内的所有像素的最小值,用这个最小值替换当前像素值,删除对象边界的某些像素,使二值图像减小一圈
腐蚀:删除对象边界的某些像素
膨胀:给图像中的对象边界添加像素
函数API
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() );
参数介绍
- src 原图像
BORDER_CONSTANT
。morphologyDefaultBorderValue()
示例代码
#include
#include
#include
#define Pic_Path "E:\\picture\\"
#define Pic_Name "15.png"
using namespace std;
int main(int argc, char **argv)
{
cv::Mat src, dst;
//获取图片完整路径及名称
string pic = string(Pic_Path) + string(Pic_Name);
cout << pic << endl;
//获取原始图片
src = cv::imread(pic.c_str());
if (src.empty())
return - 1;
cv::imshow("原始图片", src);
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(21, 21), cv::Point(-1, -1));
cv::dilate(src, dst, kernel, cv::Point(-1, -1), 1);
cv::imshow("膨胀图片", dst);
cv::erode(src, dst, kernel, cv::Point(-1, -1), 1);
cv::imshow("腐蚀图片", dst);
cv::morphologyEx(src, dst, CV_MOP_OPEN,kernel);
cv::imshow("开操作图片", dst);
cv::morphologyEx(src, dst, CV_MOP_CLOSE, kernel);
cv::imshow("闭操作图片", dst);
cv::morphologyEx(src, dst,CV_MOP_GRADIENT, kernel);
cv::imshow("梯度图片", dst);
cv::morphologyEx(src, dst, CV_MOP_TOPHAT, kernel);
cv::imshow("顶帽图片", dst);
cv::morphologyEx(src, dst, CV_MOP_BLACKHAT, kernel);
cv::imshow("黑帽图片", dst);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}