前言
在上一章中描述了如何进行图像模糊,详细描述可点击查看(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 <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
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;
}
网友评论