阅读过我的上一篇博客后,都知道应该如何在canny处理后提取到我们的手指轮廓,剔除背景轮廓了,还没看的点这里上一篇博客
然后我们要做的事情很简单,就是拟合手指的中线,并且旋转我们原来的图像以待进一步的处理。
中线的获得:
我拟合中线的办法就是采取手指每一对上下(两侧)轮廓的平均值,然后将这个中间位置的坐标记录下来。
import cv2 as cv
import numpy as np
import math
import my_algorithm as my
clahe_test=cv.imread('clahe_test.bmp',0)
test_edges=cv.Canny(clahe_test,90,150)
finger_edges=my.get_edges(test_edges)
finger_center=my.get_centerline(finger_edges)
show=cv.add(finger_edges,finger_center)
cv.imshow('show',show)
cv.imshow('finger_edges',finger_edges)
cv.imshow('finger_center',finger_center)
cv.waitKey(0)
cv.destroyAllWindows()
这是效果图
这里用到了我自己写的方法,get_edges和get_centertline,两个方法都类似,可以参考上一篇博客。上一篇没有写到get_centerline这个方法,我这里贴一下
def get_centerline(img): # img : single channel img which has been processed by get_edges
rows,cols=img.shape
coord=[]
for i in range(cols):
temp_index=np.argwhere(img[:,i]==255)
temp_index=temp_index.tolist()
center_position=round((temp_index[0][0]+temp_index[1][0])/2)
temp_index.clear()
coord.append([center_position,i])
#print(coord)
points=np.array(coord)
#return points
result_img=np.zeros((rows,cols),dtype="uint8")
for j in coord:
result_img[j[0],j[1]]=255
return result_img
实际使用的时候需要把 #return points 前的#删除 ,这样函数返回的就是一组可以用于直线拟合的坐标了
图片的旋转:
得到了中线后,我们可以开始将这一系列点放入cv.fitline()之中进行拟合了,需要了解有关fitline()的简单使用,可以点击我的这篇博客。
finger_edges=my.get_edges(test_edges)
points=my.get_centerline(finger_edges)
line =cv.fitLine(points,cv.DIST_L2,0,0.01,0.01)
line_test=cv.line(finger_edges,(line[2]-1000*line[1]/line[0],line[2]-1000),(line[2]+1000*line[1]/line[0],line[2]+1000),255)
拟合后:
然后对图片的旋转直接采用opencv中自带的方法就可以了,简单贴一下代码
rows,cols=clahe_test.shape
angle = math.atan(line[1]/line[0])*180/math.pi
angle= 90-angle if angle>0 else -90-angle
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),angle,1)
dst = cv.warpAffine(clahe_test,M,(cols,rows))
cv.imshow("show",dst)
效果:
可以看到after_rotation的右上角出现了一点点缝隙,而这正是往直线倾斜方向的相反方向进行的旋转说明旋转成功了。
点个赞哦亲~