形态学操作

在介绍opencv的形态学操作之前,要先介绍一下两个基础内容,一个是腐蚀,一个膨胀。膨胀和腐蚀相当于滤波的一种,只不过之前介绍的几种滤波,什么均值啊,高斯啊都是把区域的平均值或者说中值去替换中心点的像素值,而膨胀和腐蚀正好相反,膨胀是用区域中最高的像素值去替换中心点的像素值,而腐蚀则是用区域中最小的像素值去替换中心点的像素值。相关函数如下:

(1)Mat kernel = getstructuringElement(int shape,Size size,Point anchor)//用来获取结构元素,换言之就是确定操作区域,shape是区域形状,值有MORPH_RECT、MORPH_CROSS、MORPH_ELLIPSE分别代表方形,圆形,椭圆,size用来确定区域大小,Point对象当x、y都是-1就表示替换点是中心点。该函数在形态学操作中至关重要。

(2)dilate(源Mat对象,目标Mat对象,结构元素kernel)//这是膨胀操作

(3)erode(源Mat对象,目标Mat对象,结构元素kernel)//这是腐蚀操作

(4)createTrackbar("进度条名字","对应的窗口名字",int &进度条对应的控制参数,int 进度条最大值,对应的程序名字)//可以实时显示参数改变的效果,很有用

演示代码:

#include<opencv2\opencv.hpp>
#include<iostream>
#include<math.h>
#include<algorithm>

using namespace std;
using namespace cv;

void showDilate(int, void*);
void showErode(int, void*);
int elementSize = 6;//一开始赋值可以使trackbar一开始运行的时候处于该初始值
Mat src, dst;

int  main()
{
	src = imread("1.png", 0);
	if (src.empty())
	{
		printf("cannot load!!!\n");
		getchar();
		return -1;
	}
	namedWindow("原图");
	imshow("原图", src);
	namedWindow("膨胀测试");
	createTrackbar("Size ", "膨胀测试", &elementSize, 21,showDilate);
	showDilate(0, 0);//不运行一下的话一出来是个空窗口,需要拉动进度条才能出结果,运行一下可以先出现默认值效果
	namedWindow("腐蚀测试");
	createTrackbar("Size ", "腐蚀测试", &elementSize, 21, showErode);
	showErode(0, 0);

	waitKey(0);
	return 0;
}
void showDilate(int, void*)
{
	int size = elementSize * 2 + 1;//保证size是奇数
	Mat kernel = getStructuringElement(MORPH_RECT, Size(size, size), Point(-1, -1));
	dilate(src, dst, kernel);
	imshow("膨胀测试", dst);
}
void showErode(int, void*)
{
	int size = elementSize * 2 + 1;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(size, size), Point(-1, -1));
	erode(src, dst, kernel);
	imshow("腐蚀测试", dst);
}
演示效果:





=============================分割线============================================

下面开始介绍形态学操作,形态学操作主要有开操作,闭操作,形态学梯度,顶帽,黑帽。

(1)开操作:就是先腐蚀后膨胀,效果腐蚀是将像素值高的小点消去,膨胀在将没被消去的像素高的大部分还原。

(2)闭操作:就是先膨胀后腐蚀,效果是消除像素高背景下的低像素点,原理与开操作正好相反。

(3)形态学梯度:用膨胀后的像素减去腐蚀后的像素。

(4)顶帽:原图像与开操作的差值,效果和开操作相反。

(5)黑帽:原图像与闭操作的差值,效果和闭操作相反。

这些操作都采用同一个函数,只是参数不同。

morphologyEx(源Mat对象,目标Mat对象,int 形态学操作类型,结构元素kernel)//形态学操作类型:CV_MOP_OPEN、CV_MOP_CLOSE、CV_MOP_GRADIENT、CV_MOP_TOPHAT、CV_MOP_BLACKHAT,kernel同样是用来确定范围的。

演示代码:

#include<opencv2\opencv.hpp>
#include<iostream>
#include<math.h>
#include<algorithm>

using namespace std;
using namespace cv;

int main()
{
	Mat src, dst;
	src = imread("1.png", 1);
	if (src.empty())
	{
		printf("cannot load!!\n");
		return -1;
	}
	namedWindow("原图");
	imshow("原图", src);
	Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
	namedWindow("开操作");
	morphologyEx(src, dst, CV_MOP_OPEN, kernel);
	imshow("开操作", dst);
	namedWindow("闭操作");
	morphologyEx(src, dst, CV_MOP_CLOSE, kernel);
	imshow("闭操作", dst);
	namedWindow("形态学梯度操作");
	morphologyEx(src, dst, CV_MOP_GRADIENT, kernel);
	imshow("形态学梯度操作", dst);
	namedWindow("顶帽操作");
	morphologyEx(src, dst, CV_MOP_TOPHAT, kernel);
	imshow("顶帽操作", dst);
	namedWindow("黑帽操作");
	morphologyEx(src, dst, CV_MOP_BLACKHAT, kernel);
	imshow("黑帽操作", dst);

	waitKey(0);
	return 0;
}
效果图太多了,就不放了,效果也没什么特别的。。。。(就是懒)


==================================分割线==========================================

形态学操作可以用来提取图像中的信息,比如验证码什么的。不过提取时需要将图片转换成二值图,所谓二值图是指图片只有两个值,opencv中有几个函数可以将灰度图转换成二值图。

(1)threshold(源Mat对象,目标Mat对象,int 阈值,int 最大值,类型)//这是最简单的转二值图方法,就是给定一个阈值,根据类型,超过这个值的像素变成另一个值,没超过的则是另一个值,这两个值一个是最大值,一个是原值或者0,具体看类型。类型有THRESH_BINARY,THRESH_BINARY_INV,THRESH_TRUNC,THRESH_TOZERO,THRESH_TOZERO_INV。

(2)adaptiveThreshold(源Mat对象,目标Mat对象, int 最大值, 方法, 类型, int 区域大小,double C)//这个函数更加实用,上一个函数是很僵硬的按照阈值来分割,这样很可能会丢失轮廓,这个函数是动态转换,也就是说根据方法在一个区域内算出该区域的阈值,再根据类型判断应该赋什么值,计算方法有两种,一种是均值,就是区域内的像素均值减去C得到该区域的阈值,还有一种是高斯方法,就是按照二维正态分布求出区域的加权平均值,再减去C,得到区域阈值。两个方法叫做CV_ADAPTIVE_THRESH_MEAN_C , CV_ADAPTIVE_THRESH_GAUSSIAN_C 。

注意,二值图只能从灰度图转换而来,所以图像要先转换成灰度图。

转换成二值图后,用开操作和闭操作就能把不重要的小部分给去掉了。

演示代码:

#include<opencv2\opencv.hpp>
#include<iostream>
#include<math.h>
#include<algorithm>

using namespace std;
using namespace cv;

int main()
{
	Mat src, dst;
	src = imread("1.png", 1);
	if (src.empty())
	{
		printf("cannot load!!\n");
		return -1;
	}
	namedWindow("原图");
	imshow("原图", src);
	Mat graySrc;
	cvtColor(src, graySrc, CV_BGR2GRAY);
	namedWindow("灰度图");
	imshow("灰度图", graySrc);
	Mat binSrc;
	adaptiveThreshold(graySrc, binSrc, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15,5);
	namedWindow("二值图");
	imshow("二值图", binSrc);
	Mat kernel;
	kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
	morphologyEx(binSrc, dst, CV_MOP_CLOSE, kernel);
	morphologyEx(dst, dst, CV_MOP_OPEN, kernel);
	namedWindow("final result");
	imshow("final result", dst);

	waitKey(0);
	return 0;
}

演示效果:











猜你喜欢

转载自blog.csdn.net/ZouCharming/article/details/70215940