在读了中值滤波这节内容时突然想到是否可以自己实现中值滤波,于是用c++写了一下中值滤波,主要看的是中值滤波的思想。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\core\core.hpp>
/****************************************
pArray[]-需要提取中值的数组
length-数组长度
功能:排序,获取中值
****************************************/
int GetMedianValue(int pArray[], int length)
{
int nMedianValue=0;
//插入排序
for (auto j = 1; j < length; j++)
{
int temp = pArray[j];
int k;
for (k = j; k>0 && pArray[k - 1] >temp; k--)
{
pArray[k] = pArray[k - 1];
}
pArray[k] =temp;
}
//计算中值
//奇数个元素,返回中间元素
if ((length & 1) > 0)
{
nMedianValue = pArray[(length + 1) / 2];
}
//偶数个元素,返回中间两个元素的差值
else
{
nMedianValue = (pArray[length / 2] + pArray[length / 2 + 1]) / 2;
}
return nMedianValue;
}
/****************************************
srcImg-输入图像(灰度图像)
nTempH-模板的高度
nTempW-模板的宽度
nTempMY与nTempMX-中心的坐标
功能:中值滤波
****************************************/
void medianBlur(const cv::Mat srcImg, cv::Mat& resultImg, int nTempH, int nTempW, int nTempMY, int nTempMX)
{
if (srcImg.empty())
{
return;
}
srcImg.copyTo(resultImg);
//邻域像素数组
int* pArray = new int[nTempH*nTempW];
int nValue;
//扫面图像,进行中值滤波
for (int i = nTempMY; i < srcImg.rows - (nTempH - nTempMY) + 1; i++)
{
for (int j = nTempMX; j < resultImg.cols - (nTempW - nTempMX) + 1; j++)
{
for (int k = 0; k < nTempH; k++)
{
for (int l = 0; l < nTempW; l++)
{
pArray[k*nTempW + l] = srcImg.at<uchar>(i + k - nTempMY, j + l - nTempMX);
}
}
//中值排序获取中值
nValue = GetMedianValue(pArray, nTempH*nTempW);
resultImg.at<uchar>(i, j) = nValue;
}
}
delete[]pArray;
}
int main()
{
cv::Mat testImg = cv::imread("test1.jpg");
cv::Mat grayImg;
cv::cvtColor(testImg, grayImg, CV_BGR2GRAY);
cv::imshow("原始图像", grayImg);
cv::Mat resultImg;
medianBlur(grayImg, resultImg, 5, 5, 2, 2);
cv::imshow("my中值滤波", resultImg);
cv::waitKey(0);
return 0;
}
原图:
中值滤波后的图像: