OpenCV实现Gabor滤波(2)

来源:互联网 发布:淘宝免费推广 编辑:程序博客网 时间:2024/05/17 03:42

对上一版的Gabor滤波代码进行了修改:

1) 将filter2D函数的ddepth参数值改为CV_64, 因为输入图像的类型是CV_8U, 而gabor kernel的类型是CV_64, 如果ddepth为默认值-1,计算的结果会有误差(为什么?)。

2) 修改了garbor kernel的参数,包括kernel_size 和 v的范围,都是为了适应不同图像的大小。v 越小,Gabor函数的宽度越小,越能刻画细节信息,适应于较小的图像。按照Mian Zhou的学位论文里的推荐,v的范围选择为-1到3,而kernel_size的确定公式为:

,对应v的kernel_size大小分别为19x19, 25x25, 35x35, 49x49, 69x69. 

我将所有kenel_size统一选为69x69。构建出的gabor bank如下图:



修改过的代码如下:

#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <cmath>#include <iostream>using namespace cv;using namespace std;const double PI = 3.14159265;// ref: http://blog.csdn.net/watkinsong/article/details/7876361Mat getMyGabor(int width, int height, int U, int V, double Kmax, double f,   double sigma, int ktype, const string kernel_name){//CV_ASSERT(width % 2 == 0 && height % 2 == 0);//CV_ASSERT(ktype == CV_32F || ktype == CV_64F);int half_width = width / 2;int half_height = height / 2;double Qu = PI*U/8;double sqsigma = sigma*sigma;double Kv = Kmax/pow(f,V);double postmean = exp(-sqsigma/2);Mat kernel_re(width, height, ktype);Mat kernel_im(width, height, ktype);Mat kernel_mag(width, height, ktype);double tmp1, tmp2, tmp3;for(int j = -half_height; j <= half_height; j++){for(int i = -half_width; i <= half_width; i++){tmp1 = exp(-(Kv*Kv*(j*j+i*i))/(2*sqsigma));tmp2 = cos(Kv*cos(Qu)*i + Kv*sin(Qu)*j) - postmean;tmp3 = sin(Kv*cos(Qu)*i + Kv*sin(Qu)*j);if(ktype == CV_32F)kernel_re.at<float>(j+half_height, i+half_width) = (float)(Kv*Kv*tmp1*tmp2/sqsigma);elsekernel_re.at<double>(j+half_height, i+half_width) = (double)(Kv*Kv*tmp1*tmp2/sqsigma);if(ktype == CV_32F)kernel_im.at<float>(j+half_height, i+half_width) = (float)(Kv*Kv*tmp1*tmp3/sqsigma);elsekernel_im.at<double>(j+half_height, i+half_width) = (double)(Kv*Kv*tmp1*tmp3/sqsigma);}}magnitude(kernel_re, kernel_im, kernel_mag);if(kernel_name.compare("real") == 0)return kernel_re;else if(kernel_name.compare("imag") == 0)return kernel_im;else{printf("Invalid kernel name!\n");return kernel_mag;}}void construct_gabor_bank(){const int kernel_size = 69;double Kmax = PI/2;double f = sqrt(2.0);double sigma = 2*PI;int U = 0;int V = 0;int GaborH = kernel_size;int GaborW = kernel_size;int UStart = 0, UEnd = 8;int VStart = -1, VEnd = 4;Mat kernel;Mat totalMat;for(U = UStart; U < UEnd; U++){Mat colMat;for(V = VStart; V < VEnd; V++){kernel = getMyGabor(GaborW, GaborH, U, V,Kmax, f, sigma, CV_64F, "real");//show gabor kernelnormalize(kernel, kernel, 0, 1, CV_MINMAX);printf("U%dV%d\n", U, V);if(V == VStart)colMat = kernel;elsevconcat(colMat, kernel, colMat);}if(U == UStart)totalMat = colMat;elsehconcat(totalMat, colMat, totalMat);}imshow("gabor bank", totalMat);//normalize(totalMat, totalMat, 0, 255, CV_MINMAX);//totalMat.convertTo(totalMat, CV_8U);//imwrite("gabor_bank.jpg",totalMat);waitKey(0);}Mat gabor_filter(Mat& img, int type){// Ref: Mian Zhou. Thesis. Gabor-Boosting Face Recognition.// https://code.google.com/p/gaborboosting/const int kernel_size = 69; // should be odd// variables for gabor filterdouble Kmax = PI/2;double f = sqrt(2.0);double sigma = 2*PI;int U = 7;int V = 4;int GaborH = kernel_size;int GaborW = kernel_size;int UStart = 0, UEnd = 8;int VStart = -1, VEnd = 4;// Mat kernel_re, kernel_im;Mat dst_re, dst_im, dst_mag;// variables for filter2DPoint archor(-1,-1);int ddepth = CV_64F;//CV_64Fdouble delta = 0;// filter image with gabor bankMat totalMat, totalMat_re, totalMat_im;for(U = UStart; U < UEnd; U++){Mat colMat, colMat_re, colMat_im;for(V = VStart; V < VEnd; V++){kernel_re = getMyGabor(GaborW, GaborH, U, V,Kmax, f, sigma, CV_64F, "real");kernel_im = getMyGabor(GaborW, GaborH, U, V,Kmax, f, sigma, CV_64F, "imag");// normalize kernel ????//normalize(kernel_re, kernel_re, 0, 255, CV_MINMAX);//normalize(kernel_im, kernel_im, 0, 255, CV_MINMAX);// flip kernel// Gabor kernel is symmetric, so do not need flip//flip(kernel_re, kernel_re, -1);//flip(kernel_im, kernel_im, -1);filter2D(img, dst_re, ddepth, kernel_re);filter2D(img, dst_im, ddepth, kernel_im);dst_mag.create(img.rows, img.cols, CV_64FC1);magnitude(Mat_<float>(dst_re),Mat_<float>(dst_im), dst_mag);//show gabor kernelnormalize(dst_mag, dst_mag, 0, 1, CV_MINMAX);normalize(dst_re, dst_re, 0, 1, CV_MINMAX);normalize(dst_im, dst_im, 0, 1, CV_MINMAX);if(V == VStart){colMat = dst_mag;colMat_re = dst_re;colMat_im = dst_im;}else{vconcat(colMat, dst_mag, colMat);vconcat(colMat_re, dst_re, colMat_re);vconcat(colMat_im, dst_im, colMat_im);}}if(U == UStart){totalMat = colMat;totalMat_re = colMat_re;totalMat_im = colMat_im;}else{hconcat(totalMat, colMat, totalMat);hconcat(totalMat_re, colMat_re, totalMat_re);hconcat(totalMat_im, colMat_im, totalMat_im);}}// return switch(type){case 0:return totalMat;case 1:return totalMat_re;case 2:return totalMat_im;default:return totalMat;}}int main( int argc, char** argv ){//construct_gabor_bank();//return 0;if(3 != argc){printf("Usage: %s <image_path> <type>", argv[0]);exit(1);}string image_name(argv[1]);int type = atoi(argv[2]);Mat image;image = imread(image_name, 0); // Read the fileif(! image.data ) // Check for invalid input{cout << "Could not open or find the image" << std::endl ;return -1;}Mat filterd_image = gabor_filter(image, type);imshow("origin image", image);imshow("filtered image", filterd_image);//normalize(filterd_image, filterd_image, 0, 255, CV_MINMAX);//filterd_image.convertTo(filterd_image, CV_8U);//imwrite("filterd_image.jpg",filterd_image);waitKey(0);return 0;}

原图:


滤波结果:


可以与上一篇OpenCV实现Gabor滤波 的结果做对比

参考:Mian Zhou. Thesis. Gabor-Boosting Face Recognition. 从https://code.google.com/p/gaborboosting/source/checkout 可以下载到论文及代码。CSDN上大部分Gabor滤波代码都出自这位仁兄。

2 0
原创粉丝点击