数字图像处理——图像的空间域增强OpenCV 实验二基于一阶或二阶微分的锐化滤波器

图象锐化

建议先查看图像平滑

 

锐化处理的主要目的是突出图像中的细节或者增强被模糊了的细节,这种模糊不是由于错误操作,就是特殊图像获取方法的固有影响。图像均值滤波器可以使图像变模糊,是因为均值处理与积分相类似,因此可以对其进行逆运算(如微分运算)就可以使图像变得清晰。
常常采用基于一阶或二阶微分的锐化滤波器实现图像的锐化处理。

一阶微分

一阶微分是通过梯度法来实现的。对于图像f(i,j),它在点(i,j)处的梯度是一个矢量,定义为:
在这里插入图片描述

利用差分法近似上述公式,得到:
在这里插入图片描述

为了便于编程和提高运算,可进一步简化为:
在这里插入图片描述

利用差分运算时,图像的第一行和第一列的像素的梯度无法求得,一般用后一行或后一列的梯度值近似代替。微分运算可以增强图像高频分量(边缘等细节),但是仅仅微分处理后的图像非常暗,因此既要增强图像边缘,又要保持目标物体的内部灰度不变,常采用给边缘规定一个特定的灰度级的方法来完成梯度锐化处理。公式为:
在这里插入图片描述

La为一指定的灰度值,它将边界的灰度值统一化,这样可以使其边界更加清晰明显。该方法基本上不破坏图像的背景,又可找到边缘,并根据需要增强边缘。

基于二阶微分的锐化滤波器

基于二阶微分的锐化滤波器,即拉普拉斯增强算子。一个二元图像函数f(x, y)的拉普拉斯变换定义为:
在这里插入图片描述

由于拉普拉斯是一种微分算子,它的应用强调图像中灰度的突变及降低灰度慢变化的区域,这将产生一幅把图像中的浅灰色边线和突变点叠加到暗背景中的图像。将原始图像和拉普拉斯图像叠加在一起的简单方法可以保护拉普拉斯锐化处理的效果,同时又能复原背景信息。这种方法可表示为:
在这里插入图片描述
 

OpenCV实现

对去噪后的图像进行锐化,分别采用一阶微分和二阶微分,比较锐化效果。

在这里插入图片描述

一阶微分

罗伯特交叉算子

// 梯度锐化函数
//         -1   1
//  -1
//   1
Mat GradientSharpening(const Mat& src, Mat& dst) {
	if (!src.data) return src;
	for (int i = 0; i < src.rows; ++i)
		for (int j = 0; j < src.cols; ++j) {
			int a, b, c;
			if (i < src.rows - 1 && j < src.cols - 1) {
				
				//罗伯特交叉算子
				a = abs(src.at<Vec3b>(i + 1, j )[0] - src.at<Vec3b>(i, j)[0]) + abs(src.at<Vec3b>(i , j + 1)[0] - src.at<Vec3b>(i, j)[0]);
				b = abs(src.at<Vec3b>(i + 1, j )[1] - src.at<Vec3b>(i, j)[1]) + abs(src.at<Vec3b>(i , j + 1)[1] - src.at<Vec3b>(i, j)[1]);
				c = abs(src.at<Vec3b>(i + 1, j )[2] - src.at<Vec3b>(i, j)[2]) + abs(src.at<Vec3b>(i , j + 1)[2] - src.at<Vec3b>(i, j)[2]);

				//加上原来的颜色值,实现锐化增强
				a = a + src.at<Vec3b>(i, j)[0];
				b = b + src.at<Vec3b>(i, j)[1];
				c = c + src.at<Vec3b>(i, j)[2];
			}
			else {
				//无法处理的直接赋值原来的颜色值
				a = src.at<Vec3b>(i, j)[0];
				b = src.at<Vec3b>(i, j)[1];
				c = src.at<Vec3b>(i, j)[2];
			}
			//颜色值 超过255,为255
			if (a > 255 || b > 255 || b > 255) {
				
				dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
				dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
				dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];
			}
			else {
				dst.at<Vec3b>(i, j)[0] = a;
				dst.at<Vec3b>(i, j)[1] = b;
				dst.at<Vec3b>(i, j)[2] = c;
			}
		}
	return dst;
}

二阶微分

// 拉普拉斯锐化函数
// 0  -1  0
// -1  4  -1
// 0  -1  0
Mat LaplacianSharpening(const Mat& src, Mat& dst) {
	if (!src.data) return src;
	Mat img(src.size(), src.type());
	for (int i = 0; i < src.rows; ++i)
		for (int j = 0; j < src.cols; ++j) {
			int a, b, c;
			if (i > 1 && j > 1 && i < src.rows - 1  && j < src.cols - 1) {
				//5 是因为直接加上了原来的颜色值
				a = abs(4 * src.at<Vec3b>(i, j)[0] - src.at<Vec3b>(i - 1, j)[0] - src.at<Vec3b>(i + 1, j)[0] - src.at<Vec3b>(i, j - 1)[0] - src.at<Vec3b>(i, j + 1)[0] );
				b = abs(4 * src.at<Vec3b>(i, j)[1] - src.at<Vec3b>(i - 1, j)[1] - src.at<Vec3b>(i + 1, j)[1] - src.at<Vec3b>(i, j - 1)[1] - src.at<Vec3b>(i, j + 1)[1] );
				c = abs(4 * src.at<Vec3b>(i, j)[2] - src.at<Vec3b>(i - 1, j)[2] - src.at<Vec3b>(i + 1, j)[2] - src.at<Vec3b>(i, j - 1)[2] - src.at<Vec3b>(i, j + 1)[2] );
			
				a += src.at<Vec3b>(i, j)[0];
				b += src.at<Vec3b>(i, j)[1];
				c += src.at<Vec3b>(i, j)[2];
			}
			else {
				a = src.at<Vec3b>(i, j)[0];
				b = src.at<Vec3b>(i, j)[1];
				c = src.at<Vec3b>(i, j)[2];
			}
			if (a > 255 || b > 255 || b > 255 ) {
				dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
				dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
				dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];
			}
			else {
				dst.at<Vec3b>(i, j)[0] = a;
				dst.at<Vec3b>(i, j)[1] = b;
				dst.at<Vec3b>(i, j)[2] = c;
			}
		}
	return dst;
}

所有代码

包含了前一篇的代码

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;

//2021.4.25
//Solye



//求均值
uchar getAverage(Mat src,int i, int j,int way) {
	uchar newData;
	newData = (
		src.at<Vec3b>(i-1, j)[way] + src.at<Vec3b>(i - 1, j)[way] + src.at<Vec3b>(i - 1, j+1)[way] + 
		src.at<Vec3b>(i, j - 1)[way] +src.at<Vec3b>(i , j)[way] + src.at<Vec3b>(i, j + 1)[way] + 
		src.at<Vec3b>(i + 1, j - 1)[way] + src.at<Vec3b>(i+1, j )[way] + src.at<Vec3b>(i + 1, j+1)[way]
		) / 9;

	return newData;
}


//均值滤波
Mat AverageFilter(const Mat& src, Mat& dst) {
	if (!src.data) return src;
	
	for (int i = 0; i < src.rows; ++i)
		for (int j = 0; j < src.cols; ++j) {

			if (i >= 1 && j >= 1 && i < src.rows - 1 && j < src.cols - 1) {
				dst.at<Vec3b>(i, j)[0] = getAverage(src, i, j, 0);
				dst.at<Vec3b>(i, j)[1] = getAverage(src, i, j, 1);
				dst.at<Vec3b>(i, j)[2] = getAverage(src, i, j, 2);
			}
			else {

				dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
				dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
				dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];
			}
		}
	return dst;
}
//求中值
uchar getMedian(Mat src, int a, int b, int way) {
	uchar newArray[9];
	newArray[0] = src.at<Vec3b>(a - 1, b - 1)[way];
	newArray[1] = src.at<Vec3b>(a - 1, b )[way];
	newArray[2] = src.at<Vec3b>(a - 1, b + 1)[way];
	newArray[3] = src.at<Vec3b>(a , b -1)[way];
	newArray[4] = src.at<Vec3b>(a , b )[way];
	newArray[5] = src.at<Vec3b>(a , b + 1)[way];
	newArray[6] = src.at<Vec3b>(a + 1, b -1)[way];
	newArray[7] = src.at<Vec3b>(a + 1, b)[way];
	newArray[8] = src.at<Vec3b>(a + 1, b+1)[way];
	int len = (int)sizeof(newArray) / sizeof(uchar);
	uchar temp;
	for (int i = 0; i < len - 1; i++)
		for (int j = 0; j < len - 1 - i; j++)
			if (newArray[j] > newArray[j + 1])
			{
				temp = newArray[j];
				newArray[j] = newArray[j + 1];
				newArray[j + 1] = temp;
			}
	

	return  newArray[4];
}

//中值滤波
Mat MedianFilter(const Mat& src, Mat& dst) {
	if (!src.data) return src;
	for (int i = 0; i < src.rows; ++i) {
		for (int j = 0; j < src.cols; ++j) {
			if (i >= 1 && j >= 1 && i < src.rows - 1 && j < src.cols - 1) {
				dst.at<Vec3b>(i, j)[0] = getMedian(src, i, j, 0);
				dst.at<Vec3b>(i, j)[1] = getMedian(src, i, j, 1);
				dst.at<Vec3b>(i, j)[2] = getMedian(src, i, j, 2);
			}
			else {
				dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
				dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
				dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];
			}
		}
	}
	return dst;
}





// 梯度锐化函数
Mat GradientSharpening(const Mat& src, Mat& dst) {
	if (!src.data) return src;
	for (int i = 0; i < src.rows; ++i)
		for (int j = 0; j < src.cols; ++j) {
			int a, b, c;
			if (i < src.rows - 1 && j < src.cols - 1) {
				
				//罗伯特交叉算子
				a = abs(src.at<Vec3b>(i + 1, j )[0] - src.at<Vec3b>(i, j)[0]) + abs(src.at<Vec3b>(i , j + 1)[0] - src.at<Vec3b>(i, j)[0]);
				b = abs(src.at<Vec3b>(i + 1, j )[1] - src.at<Vec3b>(i, j)[1]) + abs(src.at<Vec3b>(i , j + 1)[1] - src.at<Vec3b>(i, j)[1]);
				c = abs(src.at<Vec3b>(i + 1, j )[2] - src.at<Vec3b>(i, j)[2]) + abs(src.at<Vec3b>(i , j + 1)[2] - src.at<Vec3b>(i, j)[2]);

				//加上原来的颜色值,实现锐化增强
				a = a + src.at<Vec3b>(i, j)[0];
				b = b + src.at<Vec3b>(i, j)[1];
				c = c + src.at<Vec3b>(i, j)[2];
			}
			else {
				//无法处理的直接赋值原来的颜色值
				a = src.at<Vec3b>(i, j)[0];
				b = src.at<Vec3b>(i, j)[1];
				c = src.at<Vec3b>(i, j)[2];
			}
			//颜色值 超过255,为255
			if (a > 255 || b > 255 || b > 255) {
				
				dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
				dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
				dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];
			}
			else {
				dst.at<Vec3b>(i, j)[0] = a;
				dst.at<Vec3b>(i, j)[1] = b;
				dst.at<Vec3b>(i, j)[2] = c;
			}
		}
	return dst;
}

// 拉普拉斯锐化函数
// 0  -1  0
// -1  4  -1
// 0  -1  0
Mat LaplacianSharpening(const Mat& src, Mat& dst) {
	if (!src.data) return src;
	Mat img(src.size(), src.type());
	for (int i = 0; i < src.rows; ++i)
		for (int j = 0; j < src.cols; ++j) {
			int a, b, c;
			if (i > 1 && j > 1 && i < src.rows - 1  && j < src.cols - 1) {
				//5 是因为直接加上了原来的颜色值
				a = abs(4 * src.at<Vec3b>(i, j)[0] - src.at<Vec3b>(i - 1, j)[0] - src.at<Vec3b>(i + 1, j)[0] - src.at<Vec3b>(i, j - 1)[0] - src.at<Vec3b>(i, j + 1)[0] );
				b = abs(4 * src.at<Vec3b>(i, j)[1] - src.at<Vec3b>(i - 1, j)[1] - src.at<Vec3b>(i + 1, j)[1] - src.at<Vec3b>(i, j - 1)[1] - src.at<Vec3b>(i, j + 1)[1] );
				c = abs(4 * src.at<Vec3b>(i, j)[2] - src.at<Vec3b>(i - 1, j)[2] - src.at<Vec3b>(i + 1, j)[2] - src.at<Vec3b>(i, j - 1)[2] - src.at<Vec3b>(i, j + 1)[2] );
			
				a += src.at<Vec3b>(i, j)[0];
				b += src.at<Vec3b>(i, j)[1];
				c += src.at<Vec3b>(i, j)[2];
			}
			else {
				a = src.at<Vec3b>(i, j)[0];
				b = src.at<Vec3b>(i, j)[1];
				c = src.at<Vec3b>(i, j)[2];
			}
			if (a > 255 || b > 255 || b > 255 ) {
				dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
				dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];
				dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];
			}
			else {
				dst.at<Vec3b>(i, j)[0] = a;
				dst.at<Vec3b>(i, j)[1] = b;
				dst.at<Vec3b>(i, j)[2] = c;
			}
		}
	return dst;
}

int main()
{
	Mat src = imread("F:/雪野Solye/所有课程/大三下课程/数字图像与艺术分析/img/噪声图像.bmp");
	Mat averageFilter;
	Mat medianFilter;
	Mat gradientSharpening;
	Mat laplacianSharpening;

	averageFilter.create(src.rows, src.cols, src.type());
	medianFilter.create(src.rows, src.cols, src.type());
	gradientSharpening.create(src.rows, src.cols, src.type());
	laplacianSharpening.create(src.rows, src.cols, src.type());

	imshow("原图", src);
	imshow("均值滤波", AverageFilter(src, averageFilter));
	imshow("中值滤波", MedianFilter(src,medianFilter));
	imshow("梯度锐化", GradientSharpening(medianFilter, gradientSharpening));
	imshow("拉普拉斯增强算子锐化", LaplacianSharpening(medianFilter, laplacianSharpening));
	
	return waitKey(0);

}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪野Solye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值