参考:https://blog.csdn.net/DeepVL/article/details/52346821
https://blog.csdn.net/bagboy_taobao_com/article/details/5574159
https://blog.csdn.net/kksc1099054857/article/details/76552976
形态学是基于形状的一系列图像处理操作,基本运算包括:腐蚀、膨胀、开、闭等。
基本原理
膨胀:就是利用一个核(叫做结构元素)与图像进行卷积。随着核的移动,每次都取核覆盖区域的最大像素值,因此最终完成的效果是将高亮区域扩大。
腐蚀:也是卷积操作。随着核的移动,每次都取核覆盖区域的最小像素值,因此最终完成的效果是将高亮区域缩小。
形态学可应用于二值图、灰度图,甚至彩色图
详细的
腐蚀是一种消除边界点,使边界向内部收缩的过程。可以用来消除小且无意义的物体。
腐蚀的算法:
用3x3的结构元素,扫描图像的每一个像素
用结构元素与其覆盖的二值图像做“与”操作
如果都为1,结果图像的该像素为1。否则为0。
结果:使二值图像减小一圈
膨胀是将与物体接触的所有背景点合并到该物体中,使边界向外部扩张的过程。可以用来填补物体中的空洞。
膨胀的算法:
用3x3的结构元素,扫描图像的每一个像素
用结构元素与其覆盖的二值图像做“与”操作
如果都为0,结果图像的该像素为0。否则为1
结果:使二值图像扩大一圈
基本功能
去除噪声
分离出独立的元素或则连接独立的元素
可以求图像梯度或则图像中的小洞
函数原型:
膨胀:dilate函数
函数原型:
void dilate(InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);
参数解析:
第一个参数:InputArray类型的src,源图像,Mat类的对象。
第二个参数:OutputArray类型的dst,目标图像,与源图像有相同的尺寸和类型。
第三个参数:InputArray类型的kernel,膨胀操作的核。当为NULL是,表示使用参考点位于中心3X3的核。
一般与getStructuringElement函数配合使用。函数介绍:http://blog.csdn.net/kksc1099054857/article/details/76569718
第四个参数:Point类型的anchor,锚的位置,有默认值(-1,-1),表示锚的中心。
第五个参数:int类型的iterations,迭代使用dilate()函数的次数,默认值为。
第六个参数:int类型的borderType,用于推断图像外部像素的某种边界模式。
第七个参数:const Scalar&类型的borderValue,当边界为常数时的边界值,用默认值morphologyDefaultBorderValue(),一般不去管它。
结论:
椭圆形边界结构效果更好
例子
python:
import cv2
import numpy as np
img = cv2.imread(‘j.png’,0)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
c++
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "highgui.h"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
/// 全局变量
Mat src, erosion_dst, dilation_dst;
int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;
/** Function Headers */
void Erosion(int, void*);//腐蚀操作
void Dilation(int, void*);//膨胀操作
/** @function main */
int main()
{
/// Load an image
src = imread("D:/xingtaixue//xx.png");
if (!src.data)
{
return -1;
}
/// Create windows
namedWindow("Erosion Demo", CV_WINDOW_AUTOSIZE);
namedWindow("Dilation Demo", CV_WINDOW_AUTOSIZE);
//Element:\n 0: Rect \n 1: Cross \n 2: Ellipse
/// 腐蚀操作滚动条
createTrackbar("Element:", "Erosion Demo", &erosion_elem, max_elem, Erosion);
createTrackbar("Kernel", "Erosion Demo", &erosion_size, max_kernel_size, Erosion);
/// 膨胀操作滚动条
createTrackbar("Element:", "Dilation Demo", &dilation_elem, max_elem, Dilation);
createTrackbar("Kernel", "Dilation Demo", &dilation_size, max_kernel_size, Dilation);
// 开始
Erosion(0, 0);
Dilation(0, 0);
waitKey(0);
return 0;
}
/** @function Erosion */
void Erosion(int, void*)
{
int erosion_type;
if (erosion_elem == 0)
{
erosion_type = MORPH_RECT; //矩形结构元素
}
else if (erosion_elem == 1)
{
erosion_type = MORPH_CROSS; //十字结构元素
}
else if (erosion_elem == 2)
{
erosion_type = MORPH_ELLIPSE;//椭圆结构元素
}
//生成核(结构元素)
Mat element = getStructuringElement(erosion_type, Size(2 * erosion_size + 1, 2 * erosion_size + 1),
Point(erosion_size, erosion_size));
//腐蚀操作
erode(src, erosion_dst, element);
imshow("Erosion Demo", erosion_dst);
}
/** @function Dilation */
void Dilation(int, void*)
{
int dilation_type;
if (dilation_elem == 0)
{
dilation_type = MORPH_RECT; //矩形结构元素
}
else if (dilation_elem == 1)
{
dilation_type = MORPH_CROSS; //十字结构元素
}
else if (dilation_elem == 2)
{
dilation_type = MORPH_ELLIPSE; //椭圆结构元素
}
//生成核(结构元素)
Mat element = getStructuringElement(dilation_type, Size(2 * dilation_size + 1, 2 * dilation_size + 1),
Point(dilation_size, dilation_size));
//腐蚀操作
dilate(src, dilation_dst, element);
imshow("Dilation Demo", dilation_dst);
}