#include <stdio.h> #include <float.h> #include <cstdlib> #include <string>
#include <opencv2/highgui.hpp> #include "opencv2/imgproc.hpp" #include <iostream> #include <fstream>
//using 5x5 window #define FILTER_WINDOW_Y 5 #define FILTER_WINDOW_X 5 #define FILTER_WINDOW_SIZE 25 #define FILTER_WINDOW_MEDIAN_SIZE (25/2) #define PIXEL_RANGE_MAX 256
void median_filter( cv::Mat &src, size_t row, unsigned char *pdst) { unsigned char *pcurdst = pdst+FILTER_WINDOW_X/2; unsigned char histogram[PIXEL_RANGE_MAX]; memset(histogram, 0, sizeof(histogram));
for(int i = row-FILTER_WINDOW_Y/2; i <= row+FILTER_WINDOW_Y/2; i++) { unsigned char *pRow = src.ptr<unsigned char>(i); for(int j = 0; j < FILTER_WINDOW_X; j++) { histogram[*(pRow+j)] +=1; } } int index = 0; int count = 0; for(index = 0, count = 0; index < PIXEL_RANGE_MAX;) { count+= histogram[index]; ++index; if(count > FILTER_WINDOW_MEDIAN_SIZE) { break; } } *pcurdst = index; ++pcurdst; //printf("\n %s:%d, index %d, count %d\n", __FILE__, __LINE__, index, count);
for(int col = 1; col < src.cols-FILTER_WINDOW_Y+1; col++, pcurdst++) { for(int i = row-FILTER_WINDOW_Y/2; i <= row+FILTER_WINDOW_Y/2; i++) { unsigned char *pRow = src.ptr<unsigned char>(i); histogram[*(pRow+col-1)] -=1; histogram[*(pRow+col+4)] +=1; if(*(pRow+col-1) < index) --count; if(*(pRow+col+4) < index) ++count; } int tmp = 0; for(int i = 0; i < PIXEL_RANGE_MAX;++i) { tmp += histogram[i]; } //printf("\n index %d, count %d, %d\n", index, count, tmp);
while(1) { if(count < FILTER_WINDOW_MEDIAN_SIZE) { count += histogram[index]; if(index < (PIXEL_RANGE_MAX-1)) ++index; else break; if(count > FILTER_WINDOW_MEDIAN_SIZE) break; } if(count > FILTER_WINDOW_MEDIAN_SIZE) { count -= histogram[index-1]; if(index > 0) --index; else break; if(count < FILTER_WINDOW_MEDIAN_SIZE) break; } if(count == FILTER_WINDOW_MEDIAN_SIZE) break; }
*pcurdst = index; }
return; }
int main(int argc, char* argv[]) { int w = 0, h = 0; std::string fileName = argv[1]; int iter = 1; if(argc > 2) iter = atoi(argv[2]);
cv::Mat src = cv::imread(fileName, CV_LOAD_IMAGE_GRAYSCALE); cv::Mat dst ; dst = src.clone();
printf("%d,%d,%d\n", src.rows, src.cols, src.channels()); imwrite("src.bmp", src); for(int i = FILTER_WINDOW_Y/2; i < src.rows-FILTER_WINDOW_Y/2; i++) { unsigned char *pdst = dst.ptr<unsigned char>(i); median_filter( src, i, pdst); }
imwrite("dst.bmp", dst);
return 0; }