基于Dlib的身份证复印件 正反面裁剪
作者:互联网
业务需求:把一些历史的身份证复印件资料,按照正反面截取,并重新命名为 xxxx_FROT.jpg & xxxx_BACK.jpg 存放进一个文件夹中
实现思路:通过人脸识别,找到身份证正面和反面,并进行裁剪
遇到的问题:1 识别出了一个"人脸框",但却不是人脸 2 如何知道是从人脸的上方还是下方进行裁剪(即身份证正面在A4纸的上面还是下面)
对于问题1,我做了一些测试,发现框了一个但框错的情况都是框小了(且非常小),所以取了个身份证框面积大小的经验值,作为是否框对的判断条件;
对于问题2,则基于计算出的身份证框,做两次裁剪:一次在框的上方,一次在框的下方,还是用面积做判断,如果 area(上) <= area(下),则说明脸在上,否则脸在下
PS: 关于人脸检测,可ref我的另外一篇文章:https://www.cnblogs.com/caesar-the-great/p/12750772.html
具体的数据类似于下面这样:
eg1:
eg2:
实现代码:
1 #coding=utf-8 2 #图片检测 - Dlib版本 3 import cv2 4 import dlib 5 import glob 6 7 # 不同情况下的图片存放路径 8 dealedimg = "img/dealedimg/" # 检测到一个人脸,并框正确 9 unhandledimg = "img/unhandledimg/" # 检测不到人脸 10 errorhandledimg = "img/errorhandledimg/" # 检测错误 11 multiFaceimg = "img/multiFaceimg/" # 多张人脸 12 originalimg = "img/originalimg/" 13 14 15 #人脸分类器 16 detector = dlib.get_frontal_face_detector() 17 # 获取人脸检测器 18 predictor = dlib.shape_predictor( 19 "D:\\software\\anaconda3\\Lib\\site-packages\\dlib\\shape_predictor_68_face_landmarks.dat" 20 ) 21 count = 0 22 count1 = 0 23 # 身份证上的常规人脸大小(基于测试数据的经验值) 24 commonFaceArea = 10000 25 # 循环遍历originalimg路径下的所有图片 26 for index, filename in enumerate(glob.glob(originalimg + '*.jpg')): 27 img = cv2.imread(filename) # 读取图片 28 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换灰色 29 # 预测出的脸的集合,第二个参数代表图片的放大倍数 30 dets = detector(gray, 2) 31 faceCounts = len(dets) 32 imgName = filename.split("\\")[1] 33 # 检测到多个人脸 34 if faceCounts > 1: 35 print("------------检测到多个人脸------------") 36 cv2.imwrite(multiFaceimg + imgName, img) 37 continue 38 # 检测不到人脸 39 if faceCounts == 0: 40 count = count + 1 41 print("未检测到人脸。。。。。count = " + count.__str__()) 42 cv2.imwrite(unhandledimg + imgName, img) 43 continue 44 # 检测到一个人脸 45 if faceCounts: 46 # 在图片中标注人脸,并显示 47 left = dets[0].left() 48 top = dets[0].top() 49 right = dets[0].right() 50 bottom = dets[0].bottom() 51 # 人脸框的面积 52 faceArea = (bottom - top) * (right - left) 53 # 人脸框小于经验值,则证明框错 54 if faceArea < commonFaceArea: 55 print("------------框到的矩形不是人脸------------") 56 cv2.imwrite(errorhandledimg + imgName, img) 57 continue 58 # 框到了一个正确的人脸,则裁剪 59 # 提取身份证正面 60 y0 = int(top - 1.5*(bottom - top)) 61 y1 = int(bottom + 1.5*(bottom - top)) 62 x0 = 0 63 # shape[0] 高度 64 orgHeight, orgWidth, channel = img.shape 65 x1 = orgWidth 66 # 裁剪正面,坐标为[y0:y1, x0:x1] 67 cropped = img[y0:y1, x0:x1] 68 imgNameFront = imgName.split(".")[0] + "_FRONT." + imgName.split(".")[1] 69 cv2.imwrite(dealedimg + imgNameFront, cropped) 70 # 基于计算出的身份证框,做两次裁剪:一次在框的上方,一次在框的下方 71 # 如果 area(上) <= area(下),则说明脸在上,否则脸在下 72 areaUp = y0 * (right - left) 73 areaDown = (orgHeight - y1) * (right - left) 74 if areaUp <= areaDown: 75 croppedBack = img[y1:orgHeight, x0:x1] 76 else: 77 croppedBack = img[0:y0, x0:x1] 78 imgNameBack = imgName.split(".")[0] + "_BACK." + imgName.split(".")[1] 79 cv2.imwrite(dealedimg + imgNameBack, croppedBack)View Code
标签:imgName,img,裁剪,cv2,正反面,人脸,身份证,Dlib 来源: https://www.cnblogs.com/caesar-the-great/p/12786314.html