OpenCV:九、形态学操作(膨胀与腐蚀)

前言

在上一章中描述了如何进行图像模糊,详细描述可点击查看(https://www.jianshu.com/writer#/notebooks/47386368/notes/77175002)

目标

本章中,将学习如何:

  • 什么是膨胀与腐蚀
  • 形态学处理——膨胀
  • 形态学处理——腐蚀
  • 动态调整结构元素大小
  • 代码演示

什么是膨胀与腐蚀

  • 膨胀与腐蚀属于形态学范畴,具体的含义根据字面意思来理解即可。用更形象的话就是“增肥”与“减肥”。他们的运用广泛:消除噪声;分割(isolate)独立的图像元素、、连接(join)相邻的元素以及寻找图像中明显的极大值区域或极小值区域。

形态学处理——膨胀

  • 相关AIP:
    void dilate( InputArray src, OutputArray dst, InputArray kernel,
    Point anchor = Point(-1,-1), int iterations = 1,
    int borderType = BORDER_CONSTANT,
    const Scalar& borderValue = morphologyDefaultBorderValue() );


    数学公式.png
  • 跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状。形态学操作——膨胀(感官上图像黑色部分变细)


    膨胀处理效果图.png

形态学处理——腐蚀

  • 相关AIP:
    void erode( InputArray src, OutputArray dst, InputArray kernel,
    Point anchor = Point(-1,-1), int iterations = 1,
    int borderType = BORDER_CONSTANT,
    const Scalar& borderValue = morphologyDefaultBorderValue() );


    数学公式.png
  • 腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值。形态学处理——腐蚀(感官上图像黑色部分变粗)


    腐蚀处理效果图.png

动态调整结构元素大小

TrackBar - createTrackbar(const String & trackbarname, const String winName, int* value, int count, Trackbarcallback func, void* userdata=0)
其中最中要的是 callback 函数功能。如果设置为NULL就是说只有值update,但是不会调用callback的函数。

代码演示

#include 
#include 
#include 

using namespace cv;
using namespace std;

Mat src, erode_dst, dilate_dst;
char dilate_Win[] = "Dilation windows", erode_Win[] = "Erosion windows";
int dilat_element = 0, erode_element = 0;
int dilate_size = 0, erode_size = 0;
int const MAX_ELEMENT = 2;
int const MAX_KERNEL_SIZE = 21;

void dilation(int, void*);
void erosion(int, void*);

int main(int argc, char* argv[])
{
    //  1、加载图像,可以是BGR或者灰度图像
    src = imread("D:/浏览器下载/谷歌下载/lena512color.tiff");
    if (!src.data) {
        printf("could not load image...\n");
        return -1;
    }
    char input_win[] = "input image";
    namedWindow(input_win, WINDOW_AUTOSIZE);
    imshow(input_win, src);
    // 2、创建两个窗口(一个用于膨胀dilation,另一个用于erosion)
    // 每次移动任何滑块时,都会调用dilation或erosion函数,它将根据当前的trackbar值更新输出图像
    namedWindow(dilate_Win, WINDOW_AUTOSIZE);
    namedWindow(erode_Win, WINDOW_AUTOSIZE);
        // 3、为每个操作创建两组滑块
    // 3.1 第一个滑块返回dilat_element或erode_element
    createTrackbar("卷积核类型:", dilate_Win, &dilat_element, MAX_ELEMENT, dilation);
    // 3.2 第二个滑块返回dilate_size或erode_size
    createTrackbar("卷积核大小:", dilate_Win, &dilate_size, MAX_KERNEL_SIZE, dilation);
    createTrackbar("卷积核类型:", erode_Win, &erode_element, MAX_ELEMENT, erosion);
    createTrackbar("卷积核大小:", erode_Win, &erode_size, MAX_KERNEL_SIZE, erosion);
    dilation(0, 0);
    erosion(0, 0);
    waitKey(0);
    return 0;
}
// 膨胀
void dilation(int, void*)
{
    int dilate_type;    // 内核选择三中形状中的任何一种
    if (0 == dilat_element){ dilate_type = MORPH_RECT; }
    else if (1 == dilat_element){ dilate_type = MORPH_CROSS; }
    else if (2 == dilat_element){ dilate_type = MORPH_ELLIPSE; }
    int s = dilate_size * 2 + 1;
    Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));  // 获取结构元素
    dilate(src, dilate_dst, kernel, Point(-1, -1), dilate_type);
    imshow(dilate_Win, dilate_dst);
    return;
}

// 腐蚀
void erosion(int, void*)
{
    int erosion_type;   // 内核选择三中形状中的任何一种
    if (0 == erode_element){ erosion_type = MORPH_RECT; }
    else if (1 == erode_element){ erosion_type = MORPH_CROSS; }
    else if (2 == erode_element){ erosion_type = MORPH_ELLIPSE; }
    int s = erode_size * 2 + 1;
    Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));  // 获取结构元素
    erode(src, erode_dst, kernel, Point(-1, -1), erosion_type);
    imshow(erode_Win, erode_dst);
    return;
}

你可能感兴趣的:(OpenCV:九、形态学操作(膨胀与腐蚀))