OpenCV实现Gabor滤波(2)
2014-04-26 15:24
1221 查看
对上一版的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/7876361 Mat 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);
else
kernel_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);
else
kernel_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 kernel
normalize(kernel, kernel, 0, 1, CV_MINMAX);
printf("U%dV%d\n", U, V);
if(V == VStart)
colMat = kernel;
else
vconcat(colMat, kernel, colMat);
}
if(U == UStart)
totalMat = colMat;
else
hconcat(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 filter
double 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 filter2D
Point archor(-1,-1);
int ddepth = CV_64F;//CV_64F
double delta = 0;
// filter image with gabor bank
Mat 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 kernel
normalize(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 file
if(! 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滤波代码都出自这位仁兄。
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/7876361 Mat 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);
else
kernel_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);
else
kernel_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 kernel
normalize(kernel, kernel, 0, 1, CV_MINMAX);
printf("U%dV%d\n", U, V);
if(V == VStart)
colMat = kernel;
else
vconcat(colMat, kernel, colMat);
}
if(U == UStart)
totalMat = colMat;
else
hconcat(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 filter
double 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 filter2D
Point archor(-1,-1);
int ddepth = CV_64F;//CV_64F
double delta = 0;
// filter image with gabor bank
Mat 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 kernel
normalize(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 file
if(! 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滤波代码都出自这位仁兄。
相关文章推荐
- python 借助opencv实现Gabor滤波特征提取
- Gabor滤波简介与Opencv中的实现及参数变化实验
- OpenCV实现Gabor滤波
- Gabor滤波小结的OpenCV实现
- Gabor滤波简介和实现(Matlab,OpenCV)
- python 借助opencv实现Gabor滤波特征提取
- 引导图滤波(Guided Image Filtering)原理以及OpenCV实现
- 双边滤波--OpenCV实现
- 基于OpenCV库的Gabor滤波器的实现
- Gabor滤波简介和实现
- Gabor变换的opencv实现
- 方框滤波,高斯滤波,中值滤波,双边滤波,opencv实现
- 基于OPENCV的视频中值滤波原理及实现
- OpenCV导向滤波(引导滤波)实现(Guided Filter)代码,以及使用颜色先验算法去雾
- opencv 同态滤波实现 homofilter
- OpenCV导向滤波(引导滤波)实现(Guided Filter)代码,以及使用颜色先验算法去雾
- openCV学习笔记(五):滤波的实现
- opencv实现图像邻域均值滤波、中值滤波、高斯滤波
- gabor 滤波的c++实现与该类得使用简介
- opencv 实现导向滤波