dlib19.9+opencv3.4人脸检测自动加墨镜

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37606112/article/details/79285533

今天我们来验证一下dlib的人脸识别的5点特征点提取效果,并利用这五个点给人脸加上一个墨镜。
5个特征点
dlib提供了人脸5个特征点的提取模板,但在官网的目录下已经打不开了,浏览器中点击时出现一堆乱码,不知是什么原因。我在github上搜索,还好,找到一个利用这5个特征点给人体自动加上一顶圣诞帽的项目,在那里可以找到shape_predictor_5_face_landmarks.dat文件,当然,68个特征点的模板文件也一样无法打开,在csdn上搜索,或者在dlib原来托管的https://sourceforge.net/网站上可以下载,感兴趣的同学可以自行查找。
提取5个特征点的python语句也非常简单,首先建立一个探测器来检测人脸:
detector = dlib.get_frontal_face_detector()
读入图片进行检测:
faces = detector(img,1)
建立提取特征点的函数:
landmark_predictor = dlib.shape_predictor(‘shape_predictor_5_face_landmarks.dat’)
将检测到的人脸方框输入进行提取:
shape = landmark_predictor(img,d)
5个特征点的坐标就包含在shape中,分别用shape.part(0-4)来表示。
5个特征点分别为左右眼角和人中位置。
这里给出实例如下:
这里写图片描述
这里写图片描述
人脸加墨镜
5个特征点只能大概标识出人脸的位置,可以用于在人脸上增加一些有趣的小饰件,比如墨镜之类。
我在网路上进行搜索,奇怪的是,dlib发行了这么久,网路上关于人脸加墨镜的例子也很多,但可以自适应人脸倾斜角度的文章却几乎找不到,问这个问题的帖子倒是很多,本博文给出一个简单的解决方案,供感兴趣的同学参考。
墨镜准备
首先我们要找到一个经过抠图的墨镜,这个墨镜logo的尺寸大有讲究,假如墨镜本身的尺寸为w,h,那么背景的尺寸应该为墨镜尺寸对角线长度的正方形,即sqrt(w**2+h**2)。这样才能根据人脸的角度来旋转墨镜。
墨镜logo的样板如下:
这里写图片描述
旋转
然后我们根据5个特征点中的第0点和第2点来计算人脸的角度。
根据计算出的角度对墨镜logo进行旋转,比如旋转30°效果如下:
这里写图片描述
制作蒙版
分别制作两个互反的正版和负版,分别对墨镜和图片人脸相应区域进行抠图,蒙版的效果如下:
这里写图片描述这里写图片描述
复合
将墨镜和人脸的蒙版效果图叠加,并将叠加后的图片重新赋值给原图片,就实现了自动给人脸加墨镜的效果。
代码

def face5(img):
    landmark_predictor = dlib.shape_predictor('shape_predictor_5_face_landmarks.dat')
    faces = detector(img,1)
    if (len(faces) > 0):
        for k,d in enumerate(faces):
            #draw_rec(img,d)
            shape = landmark_predictor(img,d)
            #特征点全部保存在了shape里面,d是dlib.rectangle(),人脸检测矩形的左上和右下坐标,shape.part(i)是第i个特征点
            #for i in range(5):
               # cv2.circle(img,(shape.part(i).x,shape.part(i).y),2,(255,0,0),-1)
               # cv2.putText(img, '{}'.format(i),(shape.part(i).x,shape.part#(i).y-5),cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 255), 2,cv2.LINE_8, 0)

            #cv2.line(img,(shape.part(0).x,shape.part(0).y),(shape.part(1).x,shape.part(1).y),(0,255,0),1)
            #cv2.line(img,(shape.part(1).x,shape.part(1).y),(shape.part(4).x,shape.part(4).y),(0,255,0),1)
            #cv2.line(img,(shape.part(4).x,shape.part(4).y),(shape.part(3).x,shape.part(3).y),(0,255,0),1)
            #cv2.line(img,(shape.part(3).x,shape.part(3).y),(shape.part(2).x,shape.part(2).y),(0,255,0),1)

            angle=math.atan((shape.part(2).y-shape.part(0).y)/(shape.part(0).x-shape.part(2).x))*180/3.14

            wr=int((shape.part(0).x-shape.part(2).x))
            hr=wr
            w=int(wr*1.8)
            h=w
            glass=cv2.resize(logo,(w,h), interpolation = cv2.INTER_CUBIC)
            glass=cv2.GaussianBlur(glass,(5,5),0)

            rotate = cv2.getRotationMatrix2D((w//2,h//2),angle,1)
            glass = cv2.warpAffine(glass,rotate,(w,h))

            roi=img[(shape.part(2).y-h//2):(shape.part(2).y-h//2+h),(shape.part(2).x-w//5):(shape.part(2).x-w//5+w)]

            gray = cv2.cvtColor(glass,cv2.COLOR_BGR2GRAY)               #logo转化为灰度图
            ret, mask = cv2.threshold(gray, 3, 255, cv2.THRESH_BINARY)  #设定一个阈值扣除背景变为黑白蒙版
            mask_inv = cv2.bitwise_not(mask)                            #把蒙版区域互换的效果
            img_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)   #把背景图中rio区域内不覆盖logo的地方找出来
            #cv2.imshow('mask1',mask)
            #cv2.imwrite('a1.jpg',mask)
            logo_fg = cv2.bitwise_and(glass,glass,mask = mask)          #把背景透明的logo图找出来
            #cv2.imshow('mask2',mask_inv)
            #cv2.imwrite('a2.jpg',mask_inv)
            dst = cv2.add(img_bg,logo_fg)   #两者相加
            img[(shape.part(2).y-h//2):(shape.part(2).y-h//2+h),(shape.part(2).x-w//5):(shape.part(2).x-w//5+w)]=dst

效果
这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述
图片中墨镜位置好像有一点点偏差,这是因为我在制作墨镜logo时,墨镜并未严格处于背景的中心,时间关系,就留着这一点瑕疵吧。。
动态验证
我的电脑实在太过古老,速度太慢,勉强看吧。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/m0_37606112/article/details/79285533