天天看点

opencv-python 用Gabor滤波器实现指静脉血管区域二值化纹理特征提取

之前写的都是有关于ROI的区域提取,但是对于提取到的区域我们需要提取它的特征,才可以在后期的特征匹配中排上用场。

这篇文章主要记录我是如何对指静脉图片做二值纹理特征提取的

原理:

一种比较特征提取简单的方法:用Gabor滤波器提取各个方向上的纹理,然后将他们融合在一起,做二值化处理。原理非常简单,但是我进行的过程十分艰辛。首先要了解什么是gabor滤波器,这篇文章可以让你有一个大概的认知。

而在opencv-python中,要获取一个gabor滤波器也很简单。

kern=cv.getGaborKernel(ksize, sigma, theta, lambd, gamma[, psi[, ktype]])
           

一句代码就可以了,看到这长长的参数列表你就应该明白我说的为什么过程会十分艰辛。因为gabor滤波器受到参数影响,所以你可能要花上大量的时间去寻找适合的参数。

这篇博客可以让你对各个参数有一个第一映像,但是这篇博客用的是C++,参数列表可能有点不一样,我按照python的参数列表做了一份明了的总结:

"""
gaborkernel 参数含义:
第一个参数:size 核的大小,一般为奇数
第二个参数:σ表示高斯函数的标准差,标准差越大,波纹起伏就越多
第三参数:θ 表示波纹的角度,弧度制 np.pi/5 这种
第四个参数:λ 表示波长,波长越长越密集
第五个参数:γ 表示椭圆的长短轴比,为1时为圆形
第六个参数:psi 表示相位偏移,-180~180变化,一般取0
第七个参数:类型,在python中一般为ktype=cv.CV_64F或者ktype=cv.CV_32F
"""
           

 实践:

找参数的过程不堪回首,很多很多的组合作用在图片上时得到的结果都是全白,要么就全黑。而且运用在图片上时候,我发现如果 第三个参数为a时可以得到一些纹理,那么这个参数为a+np.pi/2(垂直)时也有效果,但是a需要你去寻找。(参数我找了一下午,只找到了勉强能看的TAT)

fimg = cv.filter2D(ROI,cv.CV_8UC3,kern)
           

cv.filter2D我理解为在图像上运用kern这个核进行滤波处理。官方解释:该函数对图像应用任意线性滤波器。支持就地操作。当光圈部分位于图像外部时,该函数根据指定的边界模式对异常像素值进行插值。cv.CV_8UC3就是前面说的边界模式了

运用:

然后我在正交的两个方向得到了这样两幅图片:

opencv-python 用Gabor滤波器实现指静脉血管区域二值化纹理特征提取

可以看到,纹理方向是垂直的。

下一步:

下一步该如何进行我并不了解,我只是按照我的思路进行。老师的建议是:可以尝试直接把各个方向gabor滤波后图片相加看看。但是要确保gabor参数调节好了

(说的轻巧,这个参数调节实在恶心到我了)

我的方式是,直接采用已有的两张的图片   ——》用threshold进行二值化——》把两张图片用bitwise_or做或运算(相叠加)——》得到最后的图片进行形态学处理(闭运算,腐蚀)

(考虑过在或运算前就做形态学处理,尝试了很多很多不同形状的kernel进行操作,但是效果都不佳,目前最后的效果已经算里面好的了。最后还是决定用简单直接的方法,不搞这些 花里胡哨的。)

最后贴上我的代码(不一定能跑):源代码可以去我的github下载,对应文件为feature_binary.py

def feature_binary(path='0',img=None):  #img 是经过get_ROI处理过的ROI图片
    kern = cv.getGaborKernel((17,17),4,0,10,0.5,0,ktype=cv.CV_64F)
    kern2 = cv.getGaborKernel((17,17),4,np.pi/2,10,0.5,0,ktype=cv.CV_64F)
    if path!='0':
        img=cv.imread(path,0)
    ROI=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    fimg = cv.filter2D(ROI,cv.CV_8UC3,kern)
    fimg2=cv.filter2D(ROI,cv.CV_8UC3,kern2)
    ret,fimg_b=cv.threshold(fimg,230,255,cv.THRESH_BINARY_INV)
    ret,fimg2_b=cv.threshold(fimg2,245,255,cv.THRESH_BINARY_INV)  #分别二值化
    orimg=cv.bitwise_or(fimg_b,fimg2_b)
    result=close_operation(orimg,kernel,kernel)
    result=cv.erode(result,kernel1)
    return result
           

这是效果:

opencv-python 用Gabor滤波器实现指静脉血管区域二值化纹理特征提取

感觉该是血管的地方就是白的,能否作为特征使用我还没有验证。

然后贴一张我调试参数和操作的图做纪念

opencv-python 用Gabor滤波器实现指静脉血管区域二值化纹理特征提取

最后,效果不好也请轻喷,能力有限

继续阅读