opencv-python 指静脉的手指轮廓提取实现
由于指静脉由于采集时候手指的不固定,所以同一手指的不同照片可能会有旋转。我们提取手指的轮廓就是为了拟合出手指的中线,从而对手指的图片进行旋转矫正。
在opencv中提供了好几种方法供我们用来提取图片中物体的边界与轮廓。有Sobel算子,拉普拉斯算法等等,但是应用在我的图片上一点都不友好:
中间的是原图,不知道是不是因为我没有对原图进行平滑处理,如果用这两种算子来进行进一步的处理的话,难度巨大。但是在opencv中,还有一种十分友好的边缘检测的方法,他就是cv.Canny()
想了解原理和用法的话这里讲的非常清楚:
接下来展示一下这个函数的效果(网页原因图片被拉伸了)
效果很好,与轮廓无关的部分大大减少。
示例的源码:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
clahe_test=cv.imread('clahe_test.bmp',0)
sobelx = cv.Sobel(clahe_test,cv.CV_64F,1,0,ksize=5)
laplacian = cv.Laplacian(clahe_test,cv.CV_64F)
canny=cv.Canny(clahe_test,90,150)
#finger_edges=get_edges(canny)
cv.imshow("sobelx",sobelx)
cv.imshow("canny ",canny )
cv.imshow("clahe_test",clahe_test)
cv.imshow("laplacian",laplacian)
cv.waitKey(0)
cv.destroyAllWindows()
但是仅仅得到canny的效果还不够,因为我们要的仅仅是手指的轮廓,其他位置的任何轮廓对我们来说都是多余的。所以我另外编写了一个函数用来专门提取我们需要的部分。
观察Canny,我们发现中间部分都是空白,我们要的仅仅只是最靠近中间的部分,所以在函数中,我直接提取了靠近中间的像素点的坐标,然后把一张空白图像的对应坐标改变为白色(255)
以下是函数的源码:
def get_edges(img): # img : single channel img which has been processed by cv.Canny
rows,cols=img.shape
center=rows/2
index=[]
up_index=[]
for i in range(cols):
temp_index=np.argwhere(img[:,i]==255)
temp_index=temp_index.tolist()
for j in temp_index:
if j[0]<center:
up_index.append(center-j[0])
up=len(up_index)-1
up_index.clear()
down = up+1
try:
index.append([temp_index[up][0],i] )
index.append([temp_index[down][0],i])
except IndexError:
index.append(index[-2])
index.append(index[-1])
result_img=np.zeros((rows,cols),dtype="uint8")
for j in index:
result_img[j[0],j[1]]=255 #put the Corresponding coordinate into 255
return result_img
函数的说明:
try的部分的意义是:如果当列的上半部分没有找到灰度值为255的像素点,那么就以最近添加的两个像素点的坐标代替。
因为我在实际中遇到了这种图片:
看第二列,图片的下半部分没有255的值了,程序中down = up+1,而up=len(up_index)-1,他是上面半部分索引值的最后一个,由于下半部分没有255的值了,所以up同时也是temp_index的最后一个,这时候temp_index[down][0]必定会超出边界。但是加入了异常处理就不会有这种顾虑了。
接下来看看效果图:
还行,有了它接下来就可以继续做中线的拟合了
感受:python的一些基础操作还不熟悉,np中的基础操作也记不太清了,但是贵在学习,继续积累
我太难了,有帮助的话,点个赞噢亲
上一篇: 89c51单片机32个心形流水灯
下一篇: arduino流水灯代码