#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
uchar sort(uchar n1, uchar n2, uchar n3, uchar n4, uchar n5, uchar n6, uchar n7, uchar n8, uchar n9)
{
uchar arr[9];
arr[0] = n1;
arr[1] = n2;
arr[2] = n3;
arr[3] = n4;
arr[4] = n5;
arr[5] = n6;
arr[6] = n7;
arr[7] = n8;
arr[8] = n9;
//希尔排序,缩减增量
for (int div = 9 / 2; div >= 1; div = div / 2)//定增量div,并不断减小
{
for (int i = 0; i<div; ++i)//分组成div组
{
for (int j = i; j<9 - div; j += div)//对每组进行插入排序
for (int k = j; k<9; k += div)
if (arr[j]>arr[k])
swap(arr[j], arr[k]);//交换两个数的值
}
}
return arr[4];
}
void salt(Mat &src, int n)
{
if (!src.data) return;
for (int k = 0; k < n; k++)
{
int i = rand() % src.rows;
int j = rand() % src.cols;
if (src.channels() == 1)
{
src.at<uchar>(i, j) = 255;
}
else if (src.channels() == 3)
{
src.at<Vec3b>(i, j) = 255;
}
}
}
void myMedian(const Mat src, Mat &dst)
{
if (!src.data) return;
Mat _dst(src.size(), src.type());
for(int i=0;i<src.rows;++i)
for (int j = 0; j < src.cols; ++j)
{
if ((i - 1) >= 0 && (j - 1) >= 0 && (i + 1)<src.rows && (j + 1) < src.cols)
{
_dst.at<Vec3b>(i, j)[0] = sort(src.at<Vec3b>(i, j)[0], src.at<Vec3b>(i + 1, j + 1)[0],
src.at<Vec3b>(i + 1, j)[0], src.at<Vec3b>(i, j + 1)[0], src.at<Vec3b>(i + 1, j - 1)[0],
src.at<Vec3b>(i - 1, j + 1)[0], src.at<Vec3b>(i - 1, j)[0], src.at<Vec3b>(i, j - 1)[0],
src.at<Vec3b>(i - 1, j - 1)[0]);
_dst.at<Vec3b>(i, j)[1] = sort(src.at<Vec3b>(i, j)[1], src.at<Vec3b>(i + 1, j + 1)[1],
src.at<Vec3b>(i + 1, j)[1], src.at<Vec3b>(i, j + 1)[1], src.at<Vec3b>(i + 1, j - 1)[1],
src.at<Vec3b>(i - 1, j + 1)[1], src.at<Vec3b>(i - 1, j)[1], src.at<Vec3b>(i, j - 1)[1],
src.at<Vec3b>(i - 1, j - 1)[1]);
_dst.at<Vec3b>(i, j)[2] = sort(src.at<Vec3b>(i, j)[2], src.at<Vec3b>(i + 1, j + 1)[2],
src.at<Vec3b>(i + 1, j)[2], src.at<Vec3b>(i, j + 1)[2], src.at<Vec3b>(i + 1, j - 1)[2],
src.at<Vec3b>(i - 1, j + 1)[2], src.at<Vec3b>(i - 1, j)[2], src.at<Vec3b>(i, j - 1)[2],
src.at<Vec3b>(i - 1, j - 1)[2]);
}
}
_dst.copyTo(dst);
}
void main()
{
Mat image = imread("D:/2015project/medianlvbo/1.jpg");
Mat salt_image;
image.copyTo(salt_image);
salt(salt_image, 3000);
Mat image1, image2;
myMedian(salt_image, image1);
medianBlur(salt_image, image2, 3);
imshow("原图", image);
imshow("椒盐化", salt_image);
imshow("自定义中值滤波", image1);
imshow("opencv自带中值滤波", image2);
waitKey(0);
}
中值滤波能有效抑制椒盐噪声