OpenCV重写冈萨雷斯——自适应中值滤波器

ⅰ亾dé卋堺 提交于 2020-01-18 08:16:29

自适应中值滤波器

传统中值滤波器处理低概率椒盐噪声退化的图像效果令人满意 但是对于 P = 0.2 的脉冲噪声退化过的图片的处理效果就很令人失望,会丢失很多细节,由此,自适应中值滤波器诞生,与传统不同的是,自适应中值滤波器尝试保留细节。

冈萨雷斯中给出的过程是:
进程A:

A1 = Z<sub>med</sub>  -Z<sub>min</sub>
A2 = Z<sub>med</sub>  -Z<sub>max</sub>
if(A1 > 0  && A2 < 0 )
	goto B
else if ( S < S<sub>max</sub>)
	goto A
else
	return Z<sub>med</sub>

进程B:

B1 = Z<sub>xy</sub>  -Z<sub>min</sub>
B2 = Z<sub>xy</sub>  -Z<sub>max</sub>
if(B1 > 0  && B2 < 0 )
	return Z<sub>xy</sub>
else
	return Z<sub>med</sub>

过程的主要思想就是 如果当前像素点灰度值不是脉冲,则保留,当滤波器扩大到指定最大之后则选取中值为结果,可能该处是边缘。

突发奇想 既然要尽可能多的保留图像原本细节 为什么不把B过程和A过程交换一下逻辑 经过试验结果是差不多的0。0

实验图片

在这里插入图片描述
在这里插入图片描述

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

string st = "E:\\冈萨雷斯OpenCV重写\\DIP3E_CH05_Original_Images\\DIP3E_CH05_Original_Images\\";

//自己尝试
uchar autoMedianFilter(Mat src,int i,int j, int Smax, int Smin,int Snow = -1)
{
	if (Snow == -1){ Snow = Smin; }
	double Zmin;
	double Zmax;
	double Zmed;
	double Zxy;

	double A1;
	double A2;

	double B1;
	double B2;

	Mat dst = src.clone();
	Mat tmp;
	Mat tmp2(Size(pow(Snow,2),1),CV_8UC1);


	tmp = dst(Rect(j-Snow/2, i-Snow/2, Snow, Snow)).clone();
	
	for (int z = 0; z < Snow; z++)
	for (int z1 = 0; z1 < Snow;z1++)
	{
		tmp2.at<uchar>(z*Snow + z1) = tmp.at<uchar>(z, z1);
	}
	cv::sort(tmp2, tmp2, CV_SORT_ASCENDING);

	Zxy = tmp.at<uchar>(Snow / 2, Snow / 2);
	Zmin = tmp2.at<uchar>(0);
	Zmax = tmp2.at<uchar>(Snow*Snow-1);
	Zmed = tmp2.at<uchar>(Snow*Snow / 2 );

	A1 = Zmed - Zmin;
	A2 = Zmed - Zmax;

	B1 = Zxy - Zmin;
	B2 = Zxy - Zmax;
	if (B1 > 0 && B2 < 0)
	{
		return Zxy;
	}
	else
	{
		if (A1>0 && A2 < 0)
		{
			return Zmed;
		}
		else
		{
			Snow += 2;
			if (Snow >= Smax){ return Zmed; }
			else{ return autoMedianFilter(src, i, j, Smax, Smin, Snow); }
		}
		
	}
}
//书中的方法
uchar autoMedianFilter2(Mat src, int i, int j, int Smax, int Smin, int Snow = -1)
{
	if (Snow == -1){ Snow = Smin; }
	double Zmin;
	double Zmax;
	double Zmed;
	double Zxy;

	double A1;
	double A2;

	double B1;
	double B2;

	Mat dst = src.clone();
	Mat tmp;
	Mat tmp2(Size(pow(Snow, 2), 1), CV_8UC1);


	tmp = dst(Rect(j - Snow / 2, i - Snow / 2, Snow, Snow)).clone();

	for (int z = 0; z < Snow; z++)
	for (int z1 = 0; z1 < Snow; z1++)
	{
		tmp2.at<uchar>(z*Snow + z1) = tmp.at<uchar>(z, z1);
	}
	cv::sort(tmp2, tmp2, CV_SORT_ASCENDING);

	Zxy = tmp.at<uchar>(Snow / 2, Snow / 2);
	Zmin = tmp2.at<uchar>(0);
	Zmax = tmp2.at<uchar>(Snow*Snow - 1);
	Zmed = tmp2.at<uchar>(Snow*Snow / 2);

	A1 = Zmed - Zmin;
	A2 = Zmed - Zmax;

	B1 = Zxy - Zmin;
	B2 = Zxy - Zmax;

	if (A1>0 && A2 < 0)
	{
		if (B1 > 0 && B2 < 0)
		{
			return Zxy;
		}
		else
		{
			return Zmed;
		}
	}
	else
	{
		Snow += 2;
		if (Snow >= Smax){ return Zmed;  }
		else{ return autoMedianFilter2(src, i, j, Smax, Smin, Snow); }
	}
}
void main()
{
	Mat srcImage = imread(st + "Fig0514(a)(ckt_saltpep_prob_pt25).tif",0);
	imshow("原图像",srcImage);
	Mat dstImage = srcImage.clone();
	copyMakeBorder(srcImage, dstImage, 7, 7, 7, 7, BORDER_REPLICATE);
	for (int i = 4; i < dstImage.rows-4;i++)
	for (int j = 4; j < dstImage.cols-4; j++)
	{
		//这里要用改变后的图像进行计算 逐步优化,使用初始图片效果不会很理想
		dstImage.at<uchar>(i, j) = autoMedianFilter(dstImage, i, j, 7, 3);
	}
	dstImage = dstImage(Rect(7,7,srcImage.cols,srcImage.rows));
	imshow("自适应中值滤波后1",dstImage);

	copyMakeBorder(srcImage, dstImage, 7, 7, 7, 7, BORDER_REPLICATE);
	for (int i = 4; i < dstImage.rows - 4; i++)
	for (int j = 4; j < dstImage.cols - 4; j++)
	{
		dstImage.at<uchar>(i, j) = autoMedianFilter2(dstImage, i, j, 7, 3);
	}
	dstImage = dstImage(Rect(7, 7, srcImage.cols, srcImage.rows));
	imshow("自适应中值滤波后2", dstImage);
	Mat medianImage = srcImage.clone();
	medianBlur(srcImage, medianImage, 7);
	imshow("中值滤波器7*7",medianImage);
	waitKey(0);
}

加油 坚持
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!