现在的位置: 首页 > 综合 > 正文

efficient median filtering及其实现

2013年10月07日 ⁄ 综合 ⁄ 共 1985字 ⁄ 字号 评论关闭

参考:桑卡,《图像处理分析与机器学习》

中值滤波每次都需要对kernel内的像素进行排序,效率较低。kernel每次向右移动时,最左一列消失,同时增加最右一列,所以可以对kernel内的像素建立一个直方图,计算median value以及小于等于median value的像素个数nm。kernel每次更新时,重新计算median value和nm。算法如下:

 

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <cmath>

using namespace cv;
using namespace std;

void MyEfficientMedianFiltering(Mat& src, Mat& dst, int ksize);

int main( int argc, char** argv )
{
  // load image
  char* imageName = "images/Lenna_noise.jpg";

  Mat image;
  image = imread(imageName,1);
  if(!image.data)
  {
	  cout << "No image data" << endl;
	  getchar();
	  return -1;
  }

  // show image
  namedWindow("image", CV_WINDOW_AUTOSIZE);
  imshow("image", image);
  cvtColor( image, image, CV_RGB2GRAY );
  
  Mat dst;
  MyEfficientMedianFiltering(image, dst, 1);
 
  namedWindow("out_image", CV_WINDOW_AUTOSIZE);
  imshow("out_image", dst);
  waitKey(0);

  return 0;
}


void MyEfficientMedianFiltering(Mat& src, Mat& dst, int ksize)
{
	CV_Assert(src.data);
	CV_Assert(src.depth() == CV_8U);

	// create dst image
	dst.create(src.size(), src.type());
	
	for( int i = ksize; i < dst.rows-ksize; ++i )
	{
		uchar* p_dst = dst.ptr<uchar>(i);

		int median = 0;// median value
		int nm = 0;    // number of elements whose value is less than median

		int hist[256] = {0};
		for ( int j = ksize; j < dst.cols-ksize; ++j )
		{
			if( j == ksize )
			{
				//construct histogram
				for( int tmp_i = -ksize; tmp_i <= ksize; tmp_i++ )
				{
					uchar* p_src = src.ptr<uchar>(i+tmp_i);
					for( int tmp_j = -ksize; tmp_j <= ksize; tmp_j++ )
						hist[p_src[j+tmp_j]] += 1;	
				}

				// calculate median and nm
				nm = 0;
				int element_nums = (2*ksize+1)*(2*ksize+1);
				int gray_level = 0;
				for( gray_level = 0; gray_level <= 255; gray_level++ )
				{
					if( hist[gray_level] > 0 )
						nm += hist[gray_level];
					if( nm >= element_nums/2 )
						break;
				}
				median = gray_level;

				p_dst[j] = (uchar)median;
				continue;
			}

			// update histogram
			for( int tmp_i = -ksize; tmp_i <= ksize; tmp_i++ )
			{
				uchar* p_src = src.ptr<uchar>(i+tmp_i);
				hist[p_src[j-ksize-1]] -= 1;
				if( p_src[j-ksize-1] <= median )
					nm --;
				hist[p_src[j+ksize]] += 1;
				if( p_src[j+ksize] <= median )
					nm ++;					
			}

			// calculate new median and nm
			int element_nums = (2*ksize+1)*(2*ksize+1);
			while( nm > element_nums/2 )
			{	
				nm -= hist[median];
				median --;
			}
			while( nm < element_nums/2 )
			{
				median ++;
				nm += hist[median];
			}

			p_dst[j] = (uchar)median;

		}
	}
}

 

抱歉!评论已关闭.