《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码

简要原理

详细原理见《数字图像处理》3.8

这里作简要说明:

为了用模糊术语表示“平滑区”,我们考虑中心领域处像素和中心像素的灰度差。

 如下图所示,我们将一个像素8个相邻的像素,各减去这个像素的值,即,di=di-z5

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第1张图片 图1

现我们使用以下规则来判断输出像素是白色还是黑色

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第2张图片

 

其中“0”(ZE),白色(WH),黑色(BL)都是模糊集合,它们的隶属度函数如下:

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第3张图片 图3

     其中,“0”集合(ZE)的隶属度函数为

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第4张图片 式1

示例:

假设现在有如下领域:

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第5张图片

则可计算其领域di值如下(根据图1):

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第6张图片

根据式1计算各di属于“0”集合的隶属度u(di)如下:

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第7张图片

于是d2属于“0”且d4属于“0”的隶属度为min(u(d2),u(d4)) = 0.78;

同理有:

条件1:d2属于“0”且d6属于“0”的隶属度为wh1=0.78

条件2:d6属于“0”且d8属于“0”的隶属度为wh2=0.78

条件3:d8属于“0”且d4属于“0”的隶属度为wh3=0.87

条件4:d4属于“0”且d2属于“0”的隶属度为wh4=0.78

由于前四个条件只需满足一个条件,输出即为“白色”(WH),故现用or语句将前四个条件连接,假设其为条件a

        wh=max(wh1,wh2,wh3,wh4)=0.87

条件b:前四个条件都不满足:

        bl=1-wh=0.13

因为输出灰度属于“白色”的隶属度函数u(v)如下(见图3,WH线):

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第8张图片

于是,条件A:同时满足前四个条件,并且输出灰度为“白色”,的输出为

Q(1)=min(wh,u(v)),如下图:

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第9张图片

同理,条件B:满足条件5,且输出灰度属于“黑色”,的输出为:

Q(2)=min(bl,u(v)),如下图:

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第10张图片

于是,全部输出为条件A或者条件B,即

Q = max(Q(1),Q(2)),如下图:

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第11张图片 图10

最后,我们对输出进行去模糊,即最终输出V0:

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第12张图片 式2

其中,v = 0,1,2.....L-1,即K=L-1

将图10代入式2得

v0=174.405

代码:

VS2013+OpenCV3.0代码如下:

/*
***************************************************************************************************************************************
-----------------------------------------------作者:我三食堂不服----------------------------------------------------------------------
***************************************************************************************************************************************
*/


#include   
#include 
#include 

using namespace std;
using namespace cv;


/*
//模糊集合的边缘检测
//isUnify - 是否标定(仅在位深度为8时有效),false - 梯度值小于0时置0,大于255时置为255,true - 梯度值拉伸到0 ~ 255内
*/
int FuzzyEdge(const Mat &input, Mat &out, bool isUnify = false);




int main(int argc, char** argv)
{
	Mat im_source;				//原图
	Mat im_pro1;				//处理后的图片
	Mat im_pro2;				//处理后的图片

	//载入原图(灰度图方式)
	im_source = imread("3-59_a.tif", IMREAD_GRAYSCALE);

	//图片处理
	FuzzyEdge(im_source, im_pro1);
	FuzzyEdge(im_source, im_pro2, true);

	//创建窗口
	namedWindow("【原图】");
	namedWindow("【处理后1】");
	namedWindow("【处理后2】");

	//显示图片
	imshow("【原图】", im_source);
	imshow("【处理后1】", im_pro1);
	imshow("【处理后2】", im_pro2);

	//保存图片
	imwrite("3-59_b.tif", im_pro1);
	imwrite("3-59_c.tif", im_pro2);

	//等待键盘操作
	cvWaitKey(0);

	return 0;
}



/*
//模糊集合的边缘检测
//isUnify - 是否标定(仅在位深度为8时有效),false - 梯度值小于0时置0,大于255时置为255,true - 梯度值拉伸到0 ~ 255内
*/
int FuzzyEdge(const Mat &input, Mat &out, bool isUnify)
{
	double kernel[4];					// 领域灰度差\隶属度
	double WH[256], BL[256];			// 颜色隶属度函数
	double wh1, wh2, wh3, wh4, wh, bl;	// 各条件对应白色(黑色)隶属度
	double Q, MQ;						// 输出模糊集合的隶属度、隶属度总和
	Mat extend;							// 对输入图像进行拓展
	Mat out_f;							// 输出图像
	uchar* data_extend;					// 拓展的图像像素数据	
	uchar* data_out;					// 输出图片像素数据
	long double data;					// 灰度值
	int h{ input.rows };				// 图片高
	int w{ input.cols };				// 图片宽
	int w2{ w + 2 };					// 拓展图片宽
	int h2{ h + 2 };					// 拓展图片高
	int u, v, i;						// 循环变量

	//参数输入错误
	if (h < 3 || w < 3)
		return 0;

	//拓展图像
	copyMakeBorder(input, extend, 1, 1, 1, 1, BORDER_REFLECT_101);
	data_extend = extend.data;

	//输出图像初始化
	out.release();
	out.create(h, w, input.type());
	out_f.create(h, w, CV_32FC1);
	data_out = out.data;

	//颜色隶属度函数初始化
	for (i = 0; i < 256; i++)
	{
		if (i < 204)
			BL[i] = (204.0 - i) / 204.0;
		else
			BL[i] = 0;

		if (i>51)
			WH[i] = (i - 51.0) / 204.0;
		else
			WH[i] = 0;
	}


	//进行边缘增强
	for (v = 1; v < h2 - 1; v++)
	for (u = 1; u < w2 - 1; u++)
	{
		//计算灰度差(即d2,d4,d6,d8)
		kernel[0] = data_extend[(v - 1)*w2 + u] - data_extend[v*w2 + u];
		kernel[1] = data_extend[(v)*w2 + u - 1] - data_extend[v*w2 + u];
		kernel[2] = data_extend[(v)*w2 + u + 1] - data_extend[v*w2 + u];
		kernel[3] = data_extend[(v + 1)*w2 + u] - data_extend[v*w2 + u];

		//计算d2,d4,d6,d8四个灰度差属于
		//“灰度差为0”集合
		//的隶属度
		for (i = 0; i < 3; i++)
		{
			kernel[i] /= 255;
			kernel[i] = exp(-40 * kernel[i] * kernel[i]);
		}

		//计算各像素属于
		//“di和dj同时为0”集合(i,j=2、4、6、8)
		//的隶属度
		wh1 = min(kernel[0], kernel[1]);
		wh2 = min(kernel[0], kernel[2]);
		wh3 = min(kernel[3], kernel[1]);
		wh4 = min(kernel[3], kernel[2]);

		//计算各像素属于
		//“d2,d4,d6,d8全为0”集合
		//的隶属度
		wh = max(max(wh1, wh2), max(wh3, wh4));

		//计算各像素属于
		//“满足第5个条件”集合
		//的隶属度
		bl = 1 - wh;

		//计算输出灰度(重心)
		data = 0;
		MQ = 0;
		for (i = 0; i < 256; i++)
		{
			Q = max(min(BL[i], bl), min(WH[i], wh));
			data += i*Q;
			MQ += Q;
		}
		data /= MQ;
		out_f.at(v - 1, u - 1) = (float)data;
	}

	//图像格式转换
	if (isUnify)
	{
		double max, min, size, k;
		minMaxIdx(out_f, &min, &max);
		size = max - min;
		k = 255 / size;

		for (v = 0; v < h; v++)
		for (u = 0; u < w; u++)
		{
			data_out[v*w + u] = (uchar)(k*(out_f.at(v, u) - min));
		}
	}
	else
	{
		for (v = 0; v < h; v++)
		for (u = 0; u < w; u++)
		{
			data = out_f.at(v, u);
			if (data < 0)
				data = 0;
			else if (data>255)
				data = 255;

			data_out[v*w + u] = (uchar)data;
		}
	}

	return 0;
}

运行效果:
 

《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第13张图片 原图
《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第14张图片 效果图
《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码_第15张图片 对效果图进行标定的结果

 

你可能感兴趣的:(《数字图像处理》使用模糊集合进行空间滤波(边缘检测\边缘增强)- C++源码)