作为代码界的菜鸟,最近在尝试着用vs实现《数字图像处理与机器视觉》一书中有关图像处理的VC++代码。目前在研究空间域增强,希望自己能够越走越远^_^
本篇是改进后的中值滤波即自适应中值滤波的实现。
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace std;
using namespace cv;
/**************************************************
采用冒泡法对数组进行排序并返回数组元素中值
***************************************************/
int GetMedianValue(int *pAryGray, int nFilterLen)
{
int i, j;
int nMedianValue;
int nTemp;
for (j = 0; j < nFilterLen - 1; j++)
{
for (i = 0; i < nFilterLen - j - 1; i++)
{
if (pAryGray[i]>pAryGray[i + 1])
{
nTemp = pAryGray[i];
pAryGray[i] = pAryGray[i + 1];
pAryGray[i + 1] = nTemp;
}
}
}
if ((nFilterLen & 1) > 0)
{
nMedianValue = pAryGray[(nFilterLen + 1) / 2];
}
else
{
nMedianValue = (pAryGray[nFilterLen / 2] + pAryGray[nFilterLen / 2 + 1]) / 2;
}
return nMedianValue;
}
/********************************************************************************
中值滤波,对突发性噪声如椒盐噪声有较好的抑制效果
nFilterH:滤波器的高度,nFilterW:滤波器的宽度,
nFilterMX:滤波器的中心元素X坐标,nFilterMY:滤波器的中心元素Y坐标
*********************************************************************************/
void MedianFilter(Mat img, Mat &dst, int nFilterH, int nFilterW, int nFilterMY, int nFilterMX)
{
int i, j, k, l;
int nHeight = img.rows;
int nWidth = img.cols;
int *pAryR = new int[nFilterH*nFilterW];
int *pAryG = new int[nFilterH*nFilterW];
int *pAryB = new int[nFilterH*nFilterW];
int ngR, ngG, ngB;
for (i = nFilterMY; i < nHeight - nFilterH + nFilterMY + 1; i++)
{
for (j = nFilterMX; j < nWidth - nFilterW + nFilterMX + 1; j++)
{
for (k = 0; k < nFilterH; k++)
{
for (l = 0; l < nFilterW; l++)
{
ngR = img.at<Vec3b>(i + 1 - nFilterMX, j + 1 - nFilterMY)[0];
pAryR[k*nFilterW + 1] = ngR;
ngG = img.at<Vec3b>(i + 1 - nFilterMX, j + 1 - nFilterMY)[1];
pAryG[k*nFilterW + 1] = ngG;
ngB = img.at<Vec3b>(i + 1 - nFilterMX, j + 1 - nFilterMY)[2];
pAryB[k*nFilterW + 1] = ngB;
}
}
//对中值滤波进行改进,判断当前像素时候是领域的极大或极小值,如果是,将原图像像素值替换为中值,否则不改变原图像的值
//如果只想看中值滤波的效果,可以将下面判断条件省去,直接将源图像像素值替换为中值即可
ngR = GetMedianValue(pAryR, nFilterH*nFilterW);
if (img.at<Vec3b>(i, j)[0] == pAryR[0] || img.at<Vec3b>(i, j)[0] == pAryR[nFilterH*nFilterW - 1])
dst.at<Vec3b>(i, j)[0] = ngR;
else
dst.at<Vec3b>(i, j)[0] = img.at<Vec3b>(i, j)[0];
ngG = GetMedianValue(pAryG, nFilterH*nFilterW);
if (img.at<Vec3b>(i, j)[1] == pAryG[0] || img.at<Vec3b>(i, j)[1] == pAryG[nFilterH*nFilterW - 1])
dst.at<Vec3b>(i, j)[1] = ngG;
else
dst.at<Vec3b>(i, j)[1] = img.at<Vec3b>(i, j)[1];
ngB = GetMedianValue(pAryB, nFilterH*nFilterW);
if (img.at<Vec3b>(i, j)[2] == pAryB[0] || img.at<Vec3b>(i, j)[2] == pAryB[nFilterH*nFilterW - 1])
dst.at<Vec3b>(i, j)[2] = ngB;
else
dst.at<Vec3b>(i, j)[2] = img.at<Vec3b>(i, j)[2];
}
}
delete[]pAryR;
delete[]pAryG;
delete[]pAryB;
}
void main()
{
Mat img = imread("2.jpg");
cvNamedWindow("原图", CV_WINDOW_FREERATIO);
imshow("原图", img);
Mat dst=img.clone();
中值滤波
MedianFilter(img, dst, 7, 7, 1, 1);
cvNamedWindow("中值滤波", CV_WINDOW_FREERATIO);
imshow("中值滤波", dst);
waitKey(0);
}
原图:
结果图:
自适应中值滤波对这个图像的作用不是特别明显,感兴趣的同学可以尝试用其他图片试验中值滤波的效果。,如果只想看中值滤波的效果,可以将中值滤波函数中的判断部分注释掉,直接替换中值即可