【图像处理】基于OpenCV底层实现的滤波

image processing 系列

  1. 【图像处理】直方图匹配
  2. 【图像处理】图片旋转

高斯滤波

高斯滤波器介绍: wikipedia。高斯滤波器的未知数(或者说函数输入)有两个:(1)滤波器核半径;(2)σ(正态分布的标准偏差)。在连续二维空间中,这个函数长这样:
【图像处理】基于OpenCV底层实现的滤波_第1张图片
除了函数中心是极大值,周围都是围绕中心对称的。
这样有一个好处,因为滤波器实质上是 卷积(convolution)操作,卷积操作需要将核函数围绕 中心翻转之后,在与对应矩阵中各个数相乘(注意:此时 不是矩阵相乘,只是函数核中每个数字单独的相乘,不涉及整体相乘求和)。而高斯函数的对称的,所以函数核翻不翻转都一样结果。

首先,我们需要根据核半径(代码中slab = 2*r + 1)、σ(sigma)求出高斯核函数矩阵:
// get Gaussian Kernel Function
void ycGaussianKernel(float* kernel, int sigma, int slab)
{
	int index;
	float dx2, dy2;
	float sum = 0;
	for(int i=0; i
这样可以得到高斯滤波函数为:
// Gaussian filter
Mat filterGaussian(cv::Mat img, const float sigma, const int slab)
{
	cvtColor(img, img, CV_BGR2GRAY);
	Mat retMat = Mat::zeros(img.rows, img.cols, CV_8UC1);
	for(int i=0; i(i, j) = img.at(i, j);

	// 一维数组模拟二维数组
	float* kernel = new float[slab * slab];
	int* xLocation = new int[slab];
	int* yLocation = new int[slab];
	ycGaussianKernel(kernel, sigma, slab);
	float sum;
	int index;

	// 对于边缘,这里采取直接舍弃不计算的方法。因此,循环起点是 slab/2
	for(int i= slab/2; i(xLocation[fi], yLocation[fj]);
				}
			}
			retMat.at(i ,j) = sum;
		}
	}

	return retMat;
}

均值滤波

这个没啥好说的,就是函数核内所有像素点求和之后平均,平均值即为核中心上的像素值。需要输入滤波核半径。
// Mean filter: 均值滤波器
Mat filterMean(cv::Mat img, const int slab)
{
	cvtColor(img, img, CV_BGR2GRAY);
	Mat retMat = Mat::zeros(img.rows, img.cols, CV_8UC1);
	for(int i=0; i(i, j) = img.at(i, j);

	int* xLocation = new int[slab];
	int* yLocation = new int[slab];
	float sum;
	int index;

	for(int i= slab/2; i(xLocation[fi], yLocation[fj]);
				}
			}
			retMat.at(i ,j) = sum/(slab * slab);
		}
	}

	return retMat;
}

中值滤波

中值滤波跟均值滤波听起来很像,但不是一回事。中值滤波是将滤波核内各个像素由从小到大顺序排列,然后取序列中值作为核中心像素的值。需要输入滤波核半径,并且对于现有的像素序列排序。排序函数我是用快排(quickSort)写的,见 这里。滤波器代码:
// Median filter: 中值滤波器
Mat filterMedian(cv::Mat img, const int slab)
{
	cvtColor(img, img, CV_BGR2GRAY);
	Mat retMat = Mat::zeros(img.rows, img.cols, CV_8UC1);
	for(int i=0; i(i, j) = img.at(i, j);

	int* xLocation	= new int[slab];
	int* yLocation	= new int[slab];
	int* tmpArr		= new int[slab * slab];
	float sum;
	int index;

	for(int i= slab/2; i(xLocation[fi], yLocation[fj]);
				}

			quickSort(tmpArr, 0, slab*slab - 1);
			retMat.at(i ,j) = tmpArr[slab * slab / 2];
		}
	}

	return retMat;
}

滤波效果

原图为lena图,即: 【图像处理】基于OpenCV底层实现的滤波_第2张图片

对于高斯滤波,当sigma = 3,核函数为 3*3(slab = 3,核半径为 1)时,结果为: 【图像处理】基于OpenCV底层实现的滤波_第3张图片
对于均值滤波,当核函数为 5*5(slab = 5,核半径为 2)时,结果为: 【图像处理】基于OpenCV底层实现的滤波_第4张图片
对于中值滤波,当核函数为 7*7(slab = 7,核半径为 3)时,结果为: 【图像处理】基于OpenCV底层实现的滤波_第5张图片

你可能感兴趣的:(Image,Processing)