中值滤波器呢,我就不用过多介绍了,其实是很简单的,就是对像选取窗口里的像素值排序后取中值,可有效的抑制椒盐噪音。之前一直都是调用OpenCV的 库函数,今天想着练一下c++代码的基本功就尝试了下,按照自己的思路,最终也是实现了,效果还可以。不废话了,直接贴代码:
#include<iostream>
#include<opencv2/opencv.hpp>
#include <vector>
#include<functional>
using namespace std;
using namespace cv;
/* 中值滤波器实现 */
void MedianFlitering(Mat &src, Mat &dst, int k)
{
Mat im,m1, m2, m3, m4, m5, m6, B, G, R;
vector <Mat> channels;
split(src, channels);
B = channels.at(0);
G = channels.at(1);
R = channels.at(2);//通道分离
int a = src.rows;
int b = src.cols; //获得行和列
for (int i = k/2; i < a - k/2; i++)//遍历图像,注意要把边框部分去除了
{
for (int j = k/2; j < b - k/2; j++)
{
m1 = B(Rect(j - k/2, i - k/2, k, k)).clone();//选取k*k窗口中的B通道
m2 = G(Rect(j - k / 2, i - k / 2, k, k)).clone();//选取k*k窗口G通道
m3 = R(Rect(j - k / 2, i - k / 2, k, k)).clone();//选取k*k窗口R通道
m1 = m1.reshape(1, 1);
m2 = m2.reshape(1, 1);
m3 = m3.reshape(1, 1); //像素值将其变为一行
cv::sort(m1, m4, 0);
cv::sort(m2, m5, 0);
cv::sort(m3, m6, 0);//对其排序
int p0 = m4.at<uchar>(0, k*k/2+1);
int p1 = m5.at<uchar>(0, k*k / 2 + 1);
int p2 = m6.at<uchar>(0, k*k / 2 + 1);//选取各通道的像素中值点
dst.at<Vec3b>(i - k/2, j - k/2)[0] = p0;
dst.at<Vec3b>(i - k/2, j - k/2) [1]= p1;
dst.at<Vec3b>(i - k/2, j - k/2) [2]= p2;//对其进行重赋值
}
}
imshow("Annie", dst);
waitKey(0);
}
int main()
{
Mat img, im1,im2;
img = imread("c:\\users\\xa\\desktop\\img.jpg");
//cvtColor(img, gray, COLOR_RGB2GRAY);//转为灰度图
imshow("原始图像", img);
waitKey(0);
medianBlur(img, im1, 5);
imshow("opencv中值滤波", im1);
waitKey(0);
im2 = img.clone();
MedianFlitering(img, im2,5);
}
加了噪音的原始图像:
opencv滤波后的图像(5*5):
自己实现的中值滤波后效果图(5*5)。
原理其实不难,主要是如何将其变为现实。看似简单的一个问题实际上也踩了不少坑,因此加油吧,少年!