1. 腐蚀是一种消除边界点,使边界向内部收缩的过程。
可以用来消除小且无意义的物体。
腐蚀的算法:
用3x3的结构元素,扫描图像的每一个像素
用结构元素与其覆盖的二值图像做“与”操作
如果都为1,结果图像的该像素为1。否则为0。
结果:使二值图像减小一圈
2. 膨胀是将与物体接触的所有背景点合并到该物体中,使边界向外部扩张的过程。
可以用来填补物体中的空洞。
膨胀的算法:
用3x3的结构元素,扫描图像的每一个像素
用结构元素与其覆盖的二值图像做“与”操作
如果都为0,结果图像的该像素为0。否则为1
结果:使二值图像扩大一圈
3. 先腐蚀后膨胀的过程称为开运算。
用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。
4. 先膨胀后腐蚀的过程称为闭运算。
用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。
腐蚀膨胀都是用一个卷积核对图像进行卷积处理,并取出结果中的极值作为结果,腐蚀是图片中黑的区域增加,膨胀是图片中高亮区域增加(消除这些小的黑斑)。
dilate使用像素邻域内的局部极大运算符来膨胀。
erode使用像素邻域内的局部极小运算符来腐蚀。
API:Mat getStructuringElement(int 内核形状,Size 内核尺寸,Point 锚点位置)
注:内核形状可以取方形MORPH_RECT,十字形MORPH_CROSS,椭圆形MORPH_ELLIPSE
锚点位置默认值Point(-1,-1),取形状的中心
通过该API就可以获得相应的计算核,接下来计算膨胀的函数为
API:void dilate(源图像,目标图像,膨胀核,锚点,int 迭代次数,int边界模式,int 边界为常数时边界值)
开运算与闭运算的结合经常用于二值图像的后处理阶段,整个过程消除了二值图像中的孤立目标,并且填补了目标区域的内部孔洞。但是这两种运算会破坏目标原本轮廓和形状,特别是对于小尺寸目标会变得十分明显。
开运算:开运算是一个先腐蚀,后膨胀的过程,用于在图像中消除小的物体,在纤细点处分离物体,在平滑化较大的物体的边界的同时不明显改变物体的体积.
闭运算:先膨胀后腐蚀的过程,能够用于消除物体中的小型黑洞
开运算:先腐蚀再膨胀,用来消除小物体
闭运算:先膨胀再腐蚀,用于排除小型黑洞
形态学梯度:就是膨胀图与俯视图之差,用于保留物体的边缘轮廓。
顶帽:原图像与开运算图之差,用于分离比邻近点亮一些的斑块。
黑帽:闭运算与原图像之差,用于分离比邻近点暗一些的斑块。
具体效果如:https://blog.csdn.net/steph_curry/article/details/78837633
opencv里有一个很好的函数getStructuringElement,我们只要往这个函数传相应的处理参数,就可以进行相应的操作了,使用起来非常方便。
API:void morpholgyEx(源,目标,int 形态学操作标志,mat 形态学操作内核,Point 锚点,int 迭代次数,int 边界模式,int 边界为常数时的边界值).
注:形态学操作标志的取值如下:MORPH_OPEN开运算 MORPH_CLOSE 闭运算 MORPH_GRENIENT 形态学梯度 MORPH_TOPHAT顶帽 MORPH_BLACKHAT黑帽 MORPH_ERODE腐蚀 MORPH_DILATE 膨胀
形态学操作内核就是前面膨胀腐蚀使用的内核
getStructuringElement
getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。函数原型:
CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
参数说明:
shape:表示内核的形状MORPH_RECT, 矩形;
MORPH_CROSS,交叉形;
MORPH_ELLIPSE,椭圆形;ksize:内核的尺寸;
anchor
:锚点的位置。
morphologyEx
morphologyEx函数利用基本的膨胀和腐蚀技术,来执行更加高级形态学变换,如开闭运算,形态学梯度,“顶帽”、“黑帽”等等。函数原型:
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:输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U, C
V_16U,CV_16S, CV_32F 或CV_64F;
dst:目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型;
op:形态学运算的类型,可以是如下之一的标识符:MORPH_OPEN – 开运算(Opening operation);
MORPH_CLOSE – 闭运算(Closing operation);
MORPH_GRADIENT -形态学梯度(Morphological gradient);
MORPH_TOPHAT - “顶帽”(“Top hat”);
MORPH_BLACKHAT - “黑帽”(“Black hat“);kernel:InputArray类型的kernel,形态学运算的内核。若为NULL时,表示的是使用参考点
位于中心3x3的核;
anchor
:锚的位置,其有默认值(-1,-1),表示锚位于中心;
iterations
:迭代使用函数的次数,默认值为1;
borderType
:用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTA
NT;
borderValue
:当边界为常数时的边界值,有默认值morphologyDefaultBorderValue()。PS:自定义核流程
Mat element = getStructuringElement(element_shape, Size(3,3), Point(1, 1) );
morphologyEx(src, dst, MORPH_OPEN, element);
使用滑动条迭代一次进行处理:
#include
#include
using namespace std;
using namespace cv;
Mat srcImage;
//开
const int g_openCoreMax = 100;
int g_nopenCoreValue=5;
void onopenCoreSizeTrackBar(int , void* );
//闭
const int g_closeCoreMax = 100;
int g_ncloseCoreValue=5;
void oncloseCoreSizeTrackBar(int, void* );
int main(int argc, char* argv[])
{
srcImage = imread("123.jpg");
namedWindow("src image", WINDOW_AUTOSIZE);
namedWindow("open image", WINDOW_AUTOSIZE);
createTrackbar("core size", "open image", &g_nopenCoreValue, g_openCoreMax, onopenCoreSizeTrackBar, 0);
onopenCoreSizeTrackBar(0, 0);
namedWindow("close image", WINDOW_AUTOSIZE);
createTrackbar("core size", "close image", &g_ncloseCoreValue, g_closeCoreMax, oncloseCoreSizeTrackBar, 0);
oncloseCoreSizeTrackBar(0, 0);
imshow("src image", srcImage);
waitKey(0);
return 0;
}
void onopenCoreSizeTrackBar(int , void* )
{
Mat openImage;
if (g_nopenCoreValue == 0 )
{
imshow("open image", srcImage);
}
else
{
if (g_nopenCoreValue % 2 == 0)
g_nopenCoreValue++;
Mat core = getStructuringElement(MORPH_RECT, Size(g_nopenCoreValue, g_nopenCoreValue));
morphologyEx(srcImage, openImage, MORPH_OPEN, core, Point(-1, -1), 1);
imshow("open image", openImage);
}
}
void oncloseCoreSizeTrackBar(int, void*)
{
Mat closeImage;
if (g_ncloseCoreValue == 0)
{
imshow("close image", srcImage);
}
else
{
if (g_ncloseCoreValue % 2 == 0)
g_ncloseCoreValue++;
Mat core = getStructuringElement(MORPH_RECT, Size(g_ncloseCoreValue, g_ncloseCoreValue));
morphologyEx(srcImage, closeImage, MORPH_CLOSE, core, Point(-1, -1),1);
imshow("close image", closeImage);
}
}
运行输出:
参考博客:https://blog.csdn.net/u012566751/article/details/54632150