一、概念
中值滤波中值滤波的实现原理是把数字图像中一点的值用该点的一个区域的各个点的值的中值代替。我们将一个点的特定长度或形状的邻域称为窗口,那么对于二维图像的中值滤波,一般采用33或55的窗口进行滤波,中值滤波和均值滤波有所区别,是一种非线性滤波。
二、opencv medianBlur()函数
函数原型:
CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
参数说明:
src : 输入1、3、4通道图像;当ksize为3或5时,图像深度应为
CV_8U, CV_16U,或CV_32F,对于较大的滤波核,它只能是CV_8U。
dst : 输出图像,大小和类型与src相同。
ksize : l滤波核大小,它必须是奇数且大于1,例如:3,5,7…
三、c++实现中值滤波
//中值滤波
void myMedianBlur(cv::Mat &src, cv::Mat &dst, int kSize)
{
//图像边界扩充
int hh = (kSize - 1) / 2;
int hw = (kSize - 1) / 2;
cv::Mat Newsrc;
cv::copyMakeBorder(src, Newsrc, hh, hh, hw, hw, cv::BORDER_REFLECT_101);//以边缘为轴,对称
dst = cv::Mat::zeros(src.rows, src.cols, src.type());
//遍历图像
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
double valueSum = 0.0;
#define SIZE 256
int iVec[SIZE];
for (int k = 0; k < hh*2+1; k++)
{
for (int z = 0; z < hw*2+1; z++)
{
int srcValue = (int)Newsrc.at<uchar>(i + k, j + z);
valueSum += srcValue;
iVec[z+k] = srcValue;
}
}
//排序
int iSize = hh*2+1 + hw*2+1;
for(int h = 0; h < iSize;h++)
{
for(int w = 1; w < iSize - h; w++)
{
int temp = iVec[w-1];
if(iVec[w-1]>iVec[w])
{
iVec[w-1] = iVec[w];
iVec[w] = temp;
}
}
}
int iValue = iSize % 2 == 0 ? (iVec[iSize/2]+iVec[iSize/2-1])/2 : iVec[iSize/2];
dst.at<uchar>(i, j) = (uchar)iValue;
}
}
}
四、自己实现中值滤波和opencv中值滤波对比
cv::Mat src;
src = cv::imread("D:\\QtProject\\Opencv_Example\\median\\mreut.png", cv::IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "Cannot load image" << endl;
return;
}
cv::imshow("src", src);
cv::Mat medianDst;
cv::medianBlur(src, medianDst,7);
cv::imshow("medianDst", medianDst);
cv::Mat myMedianDst;
myMedianBlur(src, myMedianDst,7);
cv::imshow("myMedianDst", myMedianDst);