《在纹线方向上进行平滑滤波,在纹线的垂直方向上进行锐化滤波》 --Gabor增强的具体实践

《在纹线方向上进行平滑滤波,在纹线的垂直方向上进行锐化滤波》

--Gabor增强的具体实践

  一、问题提出

一般认为“Gabor小波感受野模拟线性滤波器,能对图像进行较好的智能收敛,从而智能增强图像。Gabor小波是智能收敛增强的物理模型”

那么,问题是在实际过程中,如何实现“Gabor小波的智能收敛”,达到“智能增强效果”?

二、解题思路

使用工具,能够简单地得到Gabor增强的核;而对于想要增强效果的物体,首先要得到它的梯度数据,并且按照“在纹线方向上进行平滑滤波,在垂直方向上进行锐化滤波”的方式,按照不同方向选择不同Gabor增强核的方法进行图像增强。这样就能够得到“智能增强”。

三、问题关键

1、实现不同方向不同尺度的Gabor增强核,这个可以直接通过函数得到。在实际过程中,使用核心要经过量化的过程,否则将无法使用;

2、得到原始图片的梯度数据。而这里的梯度数据,可以用方向场的方式保存下来;

3、使用量化的Gabor核,依据梯度数据,对原始图像进行增强。

四、解析过程

             1、Gabor核的生成(只描述数学结果,不做推导)

Gabor函数是由高斯函数和三角(傅里叶)函数构成的,周期振荡函数。

我们常见的一维Gabor函数为(基于正定傅里叶公式和高斯变换在实轴上投影):

同时,二维的Gabor函数为:

那么,根据矩阵定义 :

全部带回Gabor函数二维表达式,得到

2、固定方向的Gabor增强,就是用构建好的卷积核去做卷积。这样可以对核主要方向上体现出增强效果,对于垂直方向上,体现小波振荡效果。

(图片为核心、原始图片和效果)

从结果图片可以看到,在竖直方向上的纹理大多得到了一定的增强;但是在水平方向结果就非常差。

(核心生成函数)

// ks  核的大小

// sig σ:高斯函数的标准差

// th  θ:Gabor核函数的方向

// lm  λ:正弦函数波长;

// ps  ψ:相位偏移

// 本例中宽高比为1,也就是原始定义中的γ=1,这样得到的Gabor核的宽高是一致的

cv::Mat mkKernel(int ks, double sig, double th, double lm, double ps)

{

int hks = (ks-1)/2;

double theta = th*CV_PI/180;

double psi = ps*CV_PI/180;

double del = 2.0/(ks-1);

double lmbd = lm;

double sigma = sig/ks;

double x_theta;

double y_theta;

cv::Mat kernel(ks,ks, CV_32F);

for (int y=-hks; y<=hks; y++)

{

for (int x=-hks; x<=hks; x++)

{

x_theta = x*del*cos(theta)+y*del*sin(theta);

y_theta = -x*del*sin(theta)+y*del*cos(theta);

kernel.at<float>(hks+y,hks+x) = (float)exp(-0.5*(pow(x_theta,2)+pow(y_theta,2))/pow(sigma,2))* cos(2*CV_PI*x_theta/lmbd + psi);

}

}

return kernel;

}

这个函数基本上是依据wikipad上面对于Gabor的定义编写的。注意里面的γ=1,这是没有实际说明的。但是这样得到的结果存在一个最主要的问题就是“只能对一个方向进行滤波”,而且考虑到之后可能会在原始图像的不同像素上面使用不同的核进行滤波,所以要采用其他的计算方式。

“为了加速度,将Gabor函数做成模板,用模板来拟合Gabor函数”(为什么,没找到依据)

3、判定得到原始图片的方向场;

这是另一个问题,所谓方向场指的主要图像数据和法线之间的夹角。具体运算可以参考《精通visual c++指纹模式识别系统算法及实现》110页附近。

4、依据方向场,在不同方向选择不同的Gabor核,对原始图像进行增强。

利用Gabor小波函数,可以在方向场上对图像进行增强,以弥补图像中纹线的断裂等不足,在垂直的方向上,进行振荡增强。

int  g_DDSite[12][7][2] = {

-3, 0,  -2, 0,  -1, 0,   0, 0,   1, 0,   2, 0,   3, 0,

-3,-1,  -2,-1,  -1, 0,   0, 0,   1, 0,   2, 1,   3, 1,

-3,-2,  -2,-1,  -1,-1,   0, 0,   1, 1,   2, 1,   3, 2,

-3,-3,  -2,-2,  -1,-1,   0, 0,   1, 1,   2, 2,   3, 3,

-2,-3,  -1,-2,  -1,-1,   0, 0,   1, 1,   1, 2,   2, 3,

-1,-3,  -1,-2,   0,-1,   0, 0,   0, 1,   1, 2,   1, 3,

0,-3,   0,-2,   0,-1,   0, 0,   0, 1,   0, 2,   0, 3,

-1, 3,  -1, 2,   0, 1,   0, 0,   0,-1,   1,-2,   1,-3,

-2, 3,  -1, 2,  -1, 1,   0, 0,   1,-1,   1,-2,   2,-3,

-3, 3,  -2, 2,  -1, 1,   0, 0,   1,-1,   2,-2,   3,-3,

-3, 2,  -2, 1,  -1, 1,   0, 0,   1,-1,   2,-1,   3,-2,

-3, 1,  -2, 1,  -1, 0,   0, 0,   1, 0,   2,-1,   3,-1

};

//将 173- 8 = 165分为11等分

int DDIndex(int angle)

{

/////////////////////////////////////////////////////////////////////////

//    angle: [in] 角度 (0 - 180)

/////////////////////////////////////////////////////////////////////////

if(angle >= 173 || angle < 8)

{

return 0;

}

else

{

return ((angle-8)/15 + 1);

}

}

//org是方向场 dst是输入输出结果

void orientEnhance(Mat org,Mat& dst)

{

int x, y;

int i;

int d = 0;

int sum = 0;

// 纹线方向上进行平滑滤波的平滑滤波器

int Hw[7] = {1, 1, 1, 1, 1, 1, 1};

// 纹线方向的垂直方向上进行锐化滤波的锐化滤波器

int Vw[7] = {-3, -1, 3, 9, 3, -1, -3};

int hsum = 0;

int vsum = 0;

int temp = 0;

int IMGW = org.cols;

int IMGH = org.rows;

BYTE  *lpSrc = NULL;

BYTE  *lpDir = NULL;

BYTE *g_lpOrient = org.ptr<uchar>(0);

BYTE *g_lpOrgFinger = dst.ptr<uchar>(0);

BYTE *g_lpTemp = dst.ptr<uchar>(0);

//BYTE *g_lpTemp = new BYTE[IMGW * IMGH];

// 纹线方向上进行平滑滤波

temp = 0;

for(y = 0; y < IMGH; y++)

{

for(x = 0; x < IMGW; x++)

{

lpDir = g_lpOrient + temp + x;

lpSrc = g_lpOrgFinger + temp + x;

// 纹线方向的索引

// 找到划分的等分

d = DDIndex(*lpDir); //求的方向

sum = 0;

hsum = 0;

for(i = 0; i < 7; i++)

{

//x对应0 y对应1

if(y+g_DDSite[d][i][1] < 0 || y+g_DDSite[d][i][1] >= IMGH ||

x+g_DDSite[d][i][0] < 0 || x+g_DDSite[d][i][0] >= IMGW)

{

continue;

}

sum += Hw[i]*(*(lpSrc + g_DDSite[d][i][1]*IMGW + g_DDSite[d][i][0]));

hsum += Hw[i];

}

if(hsum != 0)

{

*(g_lpTemp + temp + x) = (BYTE)(sum/hsum);

}

else

{

*(g_lpTemp + temp + x) = 255;

}

}

temp += IMGW;

}

// 纹线方向的垂直方向上进行锐化滤波

temp = 0;

for(y = 0; y < IMGH; y++)

{

for(x = 0; x < IMGW; x++)

{

lpDir = g_lpOrient + temp + x;

lpSrc = g_lpTemp + temp + x;

// 纹线方向的垂直方向的索引

// 横过来计算

d = (DDIndex(*lpDir)+6) % 12;

sum = 0;

vsum = 0;

for(i = 0; i < 7; i++)

{

if(y+g_DDSite[d][i][1] < 0 || y+g_DDSite[d][i][1] >= IMGH ||

x+g_DDSite[d][i][0] < 0 || x+g_DDSite[d][i][0] >= IMGW)

{

continue;

}

sum += Vw[i]*(*(lpSrc + g_DDSite[d][i][1]*IMGW + g_DDSite[d][i][0]));

vsum += Vw[i];

}

if(vsum > 0)

{

sum /= vsum;

if(sum > 255)

{

*(g_lpOrgFinger + temp + x) = 255;

}

else if(sum < 0)

{

*(g_lpOrgFinger + temp + x) = 0;

}

else

{

*(g_lpOrgFinger + temp + x) = (BYTE)sum;

}

}

else

{

*(g_lpOrgFinger + temp + x) = 255;

}

}

temp += IMGW;

}

}

结果

但是,图像的大小应该是有限制的,如果图像过大,现在选择的参数就应该不正确,得到类似下面的结果

如果想在其它图像上使用,关键是要得到和本例中同样的方向场

所以,如果用在其它地方,首先是要把图像的尺度缩放正确,可以得到以下结果

自然指纹

血管

五、结果小结

1、善用资源。很多实现,在wikipad上面就已经有很好的结果了,略加修改就可以得到目的;

2、不断读书,书本中有很多灵感;多动笔墨,在书写中思考;

3、攻坚克难,一定要把经典吃透,能够获得的远远比表面的问题多得多。

感谢阅读至此,如果需要继续交流请Email [email protected]

来自为知笔记(Wiz)

时间: 2024-10-11 17:26:37

《在纹线方向上进行平滑滤波,在纹线的垂直方向上进行锐化滤波》 --Gabor增强的具体实践的相关文章

HTML-移动端如何使用css让百分比布局的弹窗水平和垂直方向上居中

pc端让一个弹窗水平和垂直方向居中,在知道弹窗宽高的情况下很好计算,只需要用如下css即可: #date{ width: 300px; height: 300px; position: absolute; top: 50%; left: 50%; margin-left: -150px; margin-top: -150px; } 但是到了移动端,如果写百分比布局的话,高度不好确定,所以弹窗居中就会变得困难,今天遇到这个问题,百度了一下,看到这位朋友的资料,(http://www.shejida

2020年的线上教育相较于传统线下教育的优点

线上教育相较于传统线下教育的优点 首先,祝愿我们能早日战胜病毒.天佑中华,我们炎黄子孙是不可战胜的,武汉加油!中国加油! 最近,因为冠状病毒疫情,很多地区的学校都发布的在线开课.线上教育的方案,很多家长会对线上教育的方式方法产生疑问,我今天便分享一些线上教育的知识给大家,帮助家长学生了解线上教育. 线上教育即远程教育,是基于互联网技术的发展衍生的一种教育方式.相较于传统的教育方式,我觉得主要有以下几个优点. 一,线上教育打破了时间空间的限制,让学生随时随地都能学习. 只要你有网络和设备(手机.电

自定义UILabel设置垂直方向的居上,居中,居下

IOS系统框架中UILabel的属性textAlignment只调整水平方向的居中,居左,居右,而没有垂直方向的调整.所以要自定义一个继承自UILabel的类,在类的实现文件中进行文字的重绘,达到垂直方向的位置调整. 新建一个类文件,继承自UILabel,头文件如下: #import <UIKit/UIKit.h> typedef NS_ENUM(NSInteger,VerticalAlignment){ VerticalAlignmentTop, VerticalAlignmentMiddl

C#下如何用NPlot绘制期货股票K线图(2):读取数据文件让K线图自动更新

[内容介绍]上一篇介绍了K线图的基本绘制方法,但很不完善,本篇增加了它直接读取数据的功能,这对于金融市场的数据量大且又需要动态刷新功能的实现很重要. [实现方法] 1.需要一个数据文件,这里用的是直接读取由另一个CTP程序从上期交易所接收的期货合约RB1609所写的行情文件日线数据rb1609_d1.txt 文件格式如下: 日期 时间 开盘 最高 最低 收盘 成交量 持仓量 20160810 0.100000 2555.00 2606.00 2540.00 2563.00 3114 6858 2

【OpenCV】邻域滤波:方框、高斯、中值、双边滤波

原文:http://blog.csdn.net/xiaowei_cqu/article/details/7785365 邻域滤波(卷积) 邻域算子值利用给定像素周围像素的值决定此像素的最终输出.如图左边图像与中间图像卷积禅城右边图像.目标图像中绿色的像素由原图像中蓝色标记的像素计算得到. 通用线性邻域滤波是一种常用的邻域算子,输入像素加权得到输出像素: 其中权重核   为“滤波系数”.上面的式子可以简记为: [方框滤波] 最简单的线性滤波是移动平均或方框滤波,用 窗口中的像素值平均后输出,核函数

javascript和css实现垂直方向自适应的三角提示菜单

这是一个比较简单实用的菜单,最重要的是他不需要引用jQuery库.菜单在垂直方向上能做到自适应,当主菜单靠近顶部,子菜单将会在下面,当主菜单靠近底部,子菜单在上面.运用Modernizr的触摸检测功能,我们可以让子菜单的响应在pc上是hover,而在触摸设备上是点击.例子中还示范了如何在宽度比较窄的情况下如何调整布局.分享一个最好用的UI前端框架! html代码: .代码 <ul id="cbp-tm-menu" class="cbp-tm-menu">

水平和垂直方向都居中

水平和垂直方向都居中:我们可以在水平上用text-align:center;竖直方向上是vertical-align: middle;但是这个只能用在特定的元素上: 父元素:display:table;子元素:display: table-cell; 例子:父元素: display: table; width: 100%; margin-bottom: 13px; overflow: hidden !important; 子元素: display: table-cell; margin-bott

触发bfc解决父子元素嵌套垂直方向margin塌陷问题

首先看一下问题案例 .wrapper{ width: 100px; height: 100px; background-color: aqua; margin-top: 100px; margin-left: 100px; } .inner{ width: 50px; height: 50px; margin-top: 100px; margin-left: 50px; background-color:black; } <div class="wrapper"> <

敲敲黑板 | 文字垂直方向对齐这样设置!

大家好! 关于文本段落的对齐方式,Word共提供了五种:左对齐.居中对齐.右对齐.两端对齐和分散对齐,平时常用的文本段落对齐方式是两端对齐.原因嘛,大家可以去这篇推送中第1部分中去看. 这里有朋友提问了,达人君,你老是抓住水平这个方向不放,说起来没完了啊?那文本在垂直(上下)方向上可以调整吗? 其实嘛,关于段落的对齐,个人感觉可以大体上从这几个角度去理解: 1.段落整体在水平方向上的对齐,也就是上面所提到的五种对齐方式,这种五种对齐方式其实是相对于左右页边距来说的: 2.段落整体在垂直方向上的对