OpenCV学习笔记(六)

最基本的形态学操作:膨胀腐蚀(所有操作都是对于高亮部分而言,即白色部分

主要作用:

1.消除噪声 

2.分割出独立的图像元素,连接图像中的相邻元素

3.寻找图像中明显的极大值区域或极小值区域

4.求出图像的梯度

膨胀:

通俗来说就是求出图片的局部最大值的操作,具体操作,是通过掩膜,与原图片卷积,是局部最大值(即掩膜中的中心点,所获得权值变大),这样操作使图像中的高亮区域逐渐增长。

腐蚀:

腐蚀相当于膨胀的相反操作,是一个求图像局部最小值的操作,具体操作同样是通过掩膜进行的。

在源码中,膨胀和腐蚀的函数原型一直,进行哪种操作往往取决于一个参数值

API使用:

膨胀:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv) {
	Mat src = imread("E://hashiqi.jpg");
	Mat dst;
	namedWindow("原始图像", 1);
	imshow("原始图像", src);
	namedWindow("膨胀图像", 1);
	Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
	dilate(src, dst, element);
	imshow("膨胀图像", dst);
	waitKey(0);

	
}

dilate函数,一参二参为输入输出图像,三参为内核,通俗的理解就是掩膜

而创建element函数:getStructuringElement中,一参代表内核形状,共有三种选择

矩形:MORPH_RECT;

交叉形:MORPH_CROSS;

椭圆形:MORPH_ELLIPSE;

二参为尺寸,三参为默认锚点

这个一参的用途,主要就是会将膨胀点,以不同形态输出

还有一个迭代次数,默认值为1

腐蚀:

参数同上,用法同上,因为其函数原型一致

erode(src, dst, getStructuringElement(MORPH_ELLIPSE, Size(size_value, size_value)), Point(-1, -1), 1);

结果如下:

图像的开运算

本质上为先腐蚀后膨胀操作,dilate(erode(src,element));很明了,懂得都懂

开运算可以用来消除小物体,在纤细处分离物体,并且在平滑较大物体的边界同时不明显改变其面积

图形的闭运算

同上,本质上是这个:erode(dilate(src,element));

闭运算能够排除小型黑洞(黑色区域)

形态学梯度

本质上是膨胀图和腐蚀图之差,众所周知,膨胀图求出局部最大值,腐蚀图求出局部最小值,差值得话,在视觉体验上类似一种大幅度的梯度变化,对二值图像进行这一操作可以将团块(blod)的边缘突出出来,我们可以用形态学梯度来保留物体的边缘轮廓

顶帽运算

原图像与开图像的差值,突出了比原图轮廓周围的区域更明亮的区域,且这一操作与选择的核的大小相关

在一幅图像具有大幅的背景,而微小物品比较规律的情况下,可以使用顶帽运算进行背景提取

黑帽运算

原图像与闭运算的结果图之差,突出了比原图轮廓周围的区域更暗的区域,且这一操作与选择和核的大小相关

黑帽运算用来分离比邻近点暗一些的斑点块,效果图有着非常完美的轮廓

核心API函数morphologyEx()

从图像的开闭运算,形态学梯度运算,顶帽黑帽运算的源码开始观察,会发现其实现都是写在一个morphologyEx()函数的switch结构下,也可以理解为该函数是图像形态学运算的核心API

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() )

输入输出图像不用说,op为形态学运算的类型,MORPH_OPEN,CLOSE,GRANDIENT,TOPHAT,BLACKHAT,ERODE,DILATE

四参为内核(掩膜),后面就是锚点,迭代次数,边框类型,最后一个参数暂时不用管,与边界值相关

综合示例:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;
using namespace std;

static Mat src, dst1,dst2,dst3,dst4,dst5;

static int choosen = 0;
static int choosen2 = 0;
static int kannel_size = 10;
static int isgradient = 0;

void get_choosen(int, void*);
void get_choosen2(int, void*);
void change_size(int, void*);
void is_gradient(int, void*);

static void to_open();
static void to_close();
static void to_tophat();
static void to_blackhat();

int main(int argc, char** argv) {
	src = imread("E://hashiqi.jpg",0);
	namedWindow("原图", 1);
	imshow("原图", src);
	createTrackbar("开闭选择", "原图", &choosen, 1, get_choosen);
	createTrackbar("顶帽黑帽选择", "原图", &choosen2, 1, get_choosen2);
	createTrackbar("内核值", "原图", &kannel_size, 30, change_size);
	createTrackbar("梯度展示", "原图", &isgradient, 1, is_gradient);
	namedWindow("开运算", 1);
	namedWindow("闭运算", 1);
	namedWindow("顶帽", 1);
	namedWindow("黑帽", 1);
	namedWindow("梯度", 1);
	change_size(kannel_size, 0);
	get_choosen(choosen, 0);
	waitKey(0);
}
void change_size(int temp, void*) {
	kannel_size = temp;
}
void get_choosen(int, void*) {
	if (choosen == 0) {
		to_open();
	}
	else
	{
		to_close();
	}
}
void get_choosen2(int, void*) {
	if (choosen == 0) {
		to_tophat();
	}
	else
	{
		to_blackhat();
	}
}
void is_gradient(int, void*) {
	if (isgradient == 1) {
		morphologyEx(src, dst5, MORPH_GRADIENT, getStructuringElement(MORPH_CROSS, Size(kannel_size, kannel_size), Point(-1, -1)), Point(-1, -1));
		imshow("梯度", dst5);
	}
}
void to_open() {
	morphologyEx(src, dst1, MORPH_OPEN, getStructuringElement(MORPH_CROSS, Size(kannel_size, kannel_size), Point(-1, -1)));
	imshow("开运算", dst1);
}
void to_close() {
	morphologyEx(src, dst2, MORPH_CLOSE, getStructuringElement(MORPH_CROSS, Size(kannel_size, kannel_size), Point(-1, -1)));
	imshow("闭运算", dst2);
}
void to_tophat() {
	morphologyEx(src, dst3, MORPH_TOPHAT, getStructuringElement(MORPH_CROSS, Size(kannel_size, kannel_size), Point(-1, -1)));
	imshow("顶帽", dst3);
}
void to_blackhat() {
	morphologyEx(src, dst4, MORPH_BLACKHAT, getStructuringElement(MORPH_CROSS, Size(kannel_size, kannel_size), Point(-1, -1)));
	imshow("黑帽",dst4);
}

结果如图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值