图像腐蚀和膨胀

目标:

         在这个教程中你将学会:

         应用两个最常用的形态学操作:膨胀和腐蚀。为了这个目的,你将使用下面的OpenCV函数:
         erode()

         Dilate()

形态学操作:

         简要的说:就是一系列基于形状的处理图像的操作。形态学操作对输入图像应用一个结构元素并且产生输出图像。

         最基本的形态学操作是:膨胀和腐蚀。他们有很广泛的应用,例如:

         取出噪音;

         分离单个的元素并且把分开的元素在一幅图像中联通;

         找出一幅图像的碰撞或者孔洞。

我们将使用下面这幅图像来简要地解释一下膨胀和腐蚀:

                                                           

腐蚀:

         这个操作是以B为核对图像A进行卷积处理,这个核可以有任意的形状和尺寸,通常是一个方形或圆形。

         核B有一个锚点,通常是核的中心;

         当核B对图像进行扫描的时候,我们计算被B所掩盖的像素的最大值,并且在锚点用最大值取代图像的像素值。正如你所推断,这种最大化操作导致图像中亮的区域增多(因此也叫作腐蚀)。以上述图像为例,对其应用腐蚀操作我们可以得到:

                                                             

背景(亮)腐蚀字母的黑色区域。

膨胀:

         这个操作时腐蚀的姊妹操作。这个操作所做的就是去计算被核所掩盖的像素的最小值。

         当核B在扫描图像的时候,我们计算被核所掩盖的图像像素的最小值,并且在锚点用这个最小值去替换该像素值。

         和腐蚀的例子相似,我们可以将膨胀操作应用到上述的图像中。你可以在下面的结果中看到图像的亮区域(背景),变得更窄了,然而字母的黑色区域变得更大了。

                                                             

代码:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "highgui.h"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

/// Global variables
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(int argc, char** argv)
{
	/// Load an image
	src = imread("F:/Photo/OpenCV_Photo/lena.jpg");

	if (!src.data)
	{
		return -1;
	}

	/// Create windows
	namedWindow("Erosion Demo", CV_WINDOW_AUTOSIZE);
	namedWindow("Dilation Demo", CV_WINDOW_AUTOSIZE);
	cvMoveWindow("Dilation Demo", src.cols, 0);

	/// Create Erosion Trackbar
	createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
		&erosion_elem, max_elem,
		Erosion);

	createTrackbar("Kernel size:\n 2n +1", "Erosion Demo",
		&erosion_size, max_kernel_size,
		Erosion);

	/// Create Dilation Trackbar
	createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
		&dilation_elem, max_elem,
		Dilation);

	createTrackbar("Kernel size:\n 2n +1", "Dilation Demo",
		&dilation_size, max_kernel_size,
		Dilation);

	/// Default start
	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));

	/// Apply the erosion operation
	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));
	/// Apply the dilation operation
	dilate(src, dilation_dst, element);
	imshow("Dilation Demo", dilation_dst);
}

解释:

1、  大多数的代码以应该都知道了,下面让我们来检查这个程序的大概结构:

首先载入一幅图像

创建两个窗口;

         为每一个操作创建一个滑动条;

         每次你移动滑动条,用户函数就会响应,然后更新窗口中显示的图像;

         下面让我们来分析这两个函数:

2、  膨胀:
erode( src, erosion_dst, element );

从上面我们可以看到,膨胀操作erode函数结构三个参数。其中element是我们要进行膨胀操作的核。如果我们没有指定,那么默认的核是一个3X3的矩阵,我们也可以自己指定核。为了我们自己来定义核,我们使用了下面的函数:OpenCV提供了一个函数getStructuringElement,可以获取常用的结构元素的形状:矩形(包括线形)、椭圆(包括圆形)及十字形:MORPH_RECT, MORPH_ELLIPSE, MORPH_CROSS

Matelement = getStructuringElement( erosion_type,

                                     Size(2*erosion_size + 1, 2*erosion_size+1 ),

                                     Point( erosion_size,erosion_size ) );

然后我们只需要指定我们核的大小以及锚点。如果没有指定,那么它就假设在核的中心。

         有了上述这些,我们已经可以去对我们的图像做膨胀操作了。

注意:还有另外一个参数允许你一次性做多次膨胀操作,在这个简单的例子中,就不介绍了,请查看相关资料获得更多详细的介绍。

3、  腐蚀:

腐蚀操作从上面的代码中可以看出,它的实现过程和膨胀的过程非常相似。这里就不多做介绍了。



发布了50 篇原创文章 · 获赞 86 · 访问量 20万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章