OpenCV-Python——一个搞笑的小程序,实现抖音戴墨镜效果
发布日期:2021-06-29 01:52:15 浏览次数:2 分类:技术文章

本文共 12885 字,大约阅读时间需要 42 分钟。

转自:github地址:

目录


简介

在github看到的一个搞笑的小程序分享给大家,github地址:

效果如下:

摄像头实时运行

代码如下:

其中的人脸识别数据可以在此下载:

解压后与程序放在同一文件夹下即可。

程序运行后按q退出,按d加墨镜。

#!/usr/bin/env python# -*- coding: utf-8 -*-# @Time    : 2019/3/16 10:10# @Author  : tomoncle# @Site    : https://github.com/tomoncle/face-detection-induction-course# @File    : input_video_stream_paste_mask.py# @Software: PyCharmimport cv2import numpy as npfrom PIL import Imagefrom imutils import face_utils, resizefrom time import sleeptry:    from dlib import get_frontal_face_detector, shape_predictorexcept ImportError:    raiseclass DynamicStreamMaskService(object):    """    动态黏贴面具服务    """    def __init__(self, saved=False):        self.saved = saved  # 是否保存图片        self.listener = True  # 启动参数        self.video_capture = cv2.VideoCapture(0)  # 调用本地摄像头        self.doing = False  # 是否进行面部面具        self.speed = 0.4  # 面具移动速度        self.detector = get_frontal_face_detector()  # 面部识别器        self.predictor = shape_predictor("shape_predictor_68_face_landmarks.dat")  # 面部分析器        self.fps = 4  # 面具存在时间基础时间        self.animation_time = 0  # 动画周期初始值        self.duration = self.fps * 4  # 动画周期最大值        self.fixed_time = 4  # 画图之后,停留时间        self.max_width = 500  # 图像大小        self.deal, self.text, self.cigarette = None, None, None  # 面具对象    def read_data(self):        """        从摄像头获取视频流,并转换为一帧一帧的图像        :return: 返回一帧一帧的图像信息        """        _, data = self.video_capture.read()        return data    def save_data(self, draw_img):        """        保存图片到本地        :param draw_img:        :return:        """        if not self.saved:            return        draw_img.save("images\\%05d.png" % self.animation_time)    def init_mask(self):        """        加载面具        :return:        """        self.console("加载面具...")        self.deal, self.text, self.cigarette = (            Image.open(x) for x in ["images\\deals.png", "images\\text.png", "images\\cigarette.png"]        )    def get_glasses_info(self, face_shape, face_width):        """        获取当前面部的眼镜信息        :param face_shape:        :param face_width:        :return:        """        left_eye = face_shape[36:42]        right_eye = face_shape[42:48]        left_eye_center = left_eye.mean(axis=0).astype("int")        right_eye_center = right_eye.mean(axis=0).astype("int")        y = left_eye_center[1] - right_eye_center[1]        x = left_eye_center[0] - right_eye_center[0]        eye_angle = np.rad2deg(np.arctan2(y, x))        deal = self.deal.resize(            (face_width, int(face_width * self.deal.size[1] / self.deal.size[0])),            resample=Image.LANCZOS)        deal = deal.rotate(eye_angle, expand=True)        deal = deal.transpose(Image.FLIP_TOP_BOTTOM)        left_eye_x = left_eye[0, 0] - face_width // 4        left_eye_y = left_eye[0, 1] - face_width // 6        return {"image": deal, "pos": (left_eye_x, left_eye_y)}    def get_cigarette_info(self, face_shape, face_width):        """        获取当前面部的烟卷信息        :param face_shape:        :param face_width:        :return:        """        mouth = face_shape[49:68]        mouth_center = mouth.mean(axis=0).astype("int")        cigarette = self.cigarette.resize(            (face_width, int(face_width * self.cigarette.size[1] / self.cigarette.size[0])),            resample=Image.LANCZOS)        x = mouth[0, 0] - face_width + int(16 * face_width / self.cigarette.size[0])        y = mouth_center[1]        return {"image": cigarette, "pos": (x, y)}    def orientation(self, rects, img_gray):        """        人脸定位        :return:        """        faces = []        for rect in rects:            face = {}            face_shades_width = rect.right() - rect.left()            predictor_shape = self.predictor(img_gray, rect)            face_shape = face_utils.shape_to_np(predictor_shape)            face['cigarette'] = self.get_cigarette_info(face_shape, face_shades_width)            face['glasses'] = self.get_glasses_info(face_shape, face_shades_width)            faces.append(face)        return faces    def start(self):        """        启动程序        :return:        """        self.console("程序启动成功.")        self.init_mask()        while self.listener:            frame = self.read_data()            frame = resize(frame, width=self.max_width)            img_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)            rects = self.detector(img_gray, 0)            faces = self.orientation(rects, img_gray)            draw_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))            if self.doing:                self.drawing(draw_img, faces)                self.animation_time += self.speed                self.save_data(draw_img)                if self.animation_time > self.duration:                    self.doing = False                    self.animation_time = 0                else:                    frame = cv2.cvtColor(np.asarray(draw_img), cv2.COLOR_RGB2BGR)            cv2.imshow("hello mask", frame)            self.listener_keys()    def listener_keys(self):        """        设置键盘监听事件        :return:        """        key = cv2.waitKey(1) & 0xFF        if key == ord("q"):            self.listener = False            self.console("程序退出")            sleep(1)            self.exit()        if key == ord("d"):            self.doing = not self.doing    def exit(self):        """        程序退出        :return:        """        self.video_capture.release()        cv2.destroyAllWindows()    def drawing(self, draw_img, faces):        """        画图        :param draw_img:        :param faces:        :return:        """        for face in faces:            if self.animation_time < self.duration - self.fixed_time:                current_x = int(face["glasses"]["pos"][0])                current_y = int(face["glasses"]["pos"][1] * self.animation_time / (self.duration - self.fixed_time))                draw_img.paste(face["glasses"]["image"], (current_x, current_y), face["glasses"]["image"])                cigarette_x = int(face["cigarette"]["pos"][0])                cigarette_y = int(face["cigarette"]["pos"][1] * self.animation_time / (self.duration - self.fixed_time))                draw_img.paste(face["cigarette"]["image"], (cigarette_x, cigarette_y),                               face["cigarette"]["image"])            else:                draw_img.paste(face["glasses"]["image"], face["glasses"]["pos"], face["glasses"]["image"])                draw_img.paste(face["cigarette"]["image"], face["cigarette"]["pos"], face["cigarette"]["image"])                draw_img.paste(self.text, (75, draw_img.height // 2 + 128), self.text)    @classmethod    def console(cls, s):        print("{} !".format(s))if __name__ == '__main__':    ms = DynamicStreamMaskService()    ms.start()

图片生成gif动图

#!/usr/bin/env python# -*- coding: utf-8 -*-# @Time    : 2019/3/13 14:47# @Author  : tomoncle# @Site    : https://github.com/tomoncle/face-detection-induction-course# @File    : input_static_pic_to_gif2.py# 参考信息:https://www.makeartwithpython.com/blog/deal-with-it-generator-face-recognition/# 描述:#       程序从命令行参数获取图片信息,然后,它将使用Dlib中的人脸检测算法来查看是否有人脸存在。#       如果有,它将为每个人脸创建一个结束位置,眼镜和烟卷会移动到那里结束。##       然后我们需要缩放和旋转我们的眼镜以适合每个人的脸。#       我们将使用从Dlib的68点模型返回的点集来找到眼睛的中心,并为它们之间的空间旋转。##       在我们找到眼镜的最终位置和旋转后,我们可以为gif制作动画,眼镜从屏幕顶部进入。#       我们将使用MoviePy和一个自定义的FaceDetect工具类绘制它。##       同理烟卷也是这样。##       应用程序的体系结构非常简单。我们首先接收图片,然后将其转换为灰度NumPy数组。#       假如没有人脸,程序会自己退出,如果存在,我们就可以将检测到的人脸信息传递到人脸方向预测模型中。##       通过返回的脸部方向,我们可以选择眼睛,缩放和旋转我们的眼镜框架以适合人的面部大小。##       当然这个程序不仅仅只针对于一张人脸,可以检测多个人脸信息。##       最后,通过获取的人脸列表,我们可以使用MoviePy创建一个绘图,然后生成我们的动画gif。import moviepy.editor as mpyimport numpy as npfrom PIL import Imagefrom imutils import face_utilstry:    from dlib import get_frontal_face_detector, shape_predictorexcept ImportError:    raiseclass FaceDetect(object):    def __init__(self, img_src, gif_path=None):        self.gif_max_width = 500        self.duration = 4        self.image = self.load(img_src).convert('RGBA')        self.img_gray = None        self.rects = None        self.deal = None        self.text = None        self.cigarette = None        if not self.validate:            print("没有检测到人脸,程序退出.")            exit(1)        self.init_mask()        self.make_gif(gif_path=gif_path)    @property    def validate(self):        """        验证是否存在人脸,如果不存在返回False        :return:        """        if self.image.size[0] > self.gif_max_width:            scaled_height = int(self.gif_max_width * self.image.size[1] / self.image.size[0])            self.image.thumbnail((self.gif_max_width, scaled_height))        self.img_gray = np.array(self.image.convert('L'))        self.rects = self.detector(self.img_gray, 0)        return len(self.rects) > 0    @classmethod    def load(cls, img_src):        """        加载图片转为Image对象        :param img_src:        :return:        """        return Image.open(img_src)    @property    def detector(self):        """        检测是否有人脸        :return:        """        return get_frontal_face_detector()    @property    def predictor(self):        """        预测我们的面部方向        :return:        """        return shape_predictor('shape_predictor_68_face_landmarks.dat')    def init_mask(self):        """        加载面具        :return:        """        self.deal, self.text, self.cigarette = (            self.load(x) for x in ["images\\deals.png", "images\\text.png", "images\\cigarette.png"]        )    def get_glasses_info(self, face_shape, face_width):        """        获取当前面部的眼镜信息        :param face_shape:        :param face_width:        :return:        """        left_eye = face_shape[36:42]        right_eye = face_shape[42:48]        left_eye_center = left_eye.mean(axis=0).astype("int")        right_eye_center = right_eye.mean(axis=0).astype("int")        y = left_eye_center[1] - right_eye_center[1]        x = left_eye_center[0] - right_eye_center[0]        eye_angle = np.rad2deg(np.arctan2(y, x))        deal = self.deal.resize(            (face_width, int(face_width * self.deal.size[1] / self.deal.size[0])),            resample=Image.LANCZOS)        deal = deal.rotate(eye_angle, expand=True)        deal = deal.transpose(Image.FLIP_TOP_BOTTOM)        left_eye_x = left_eye[0, 0] - face_width // 4        left_eye_y = left_eye[0, 1] - face_width // 6        return {"image": deal, "pos": (left_eye_x, left_eye_y)}    def get_cigarette_info(self, face_shape, face_width):        """        获取当前面部的烟卷信息        :param face_shape:        :param face_width:        :return:        """        mouth = face_shape[49:68]        mouth_center = mouth.mean(axis=0).astype("int")        cigarette = self.cigarette.resize(            (face_width, int(face_width * self.cigarette.size[1] / self.cigarette.size[0])),            resample=Image.LANCZOS)        x = mouth[0, 0] - face_width + int(16 * face_width / self.cigarette.size[0])        y = mouth_center[1]        return {"image": cigarette, "pos": (x, y)}    def orientation(self):        """        人脸定位        :return:        """        faces = []        for rect in self.rects:            face = {}            face_shades_width = rect.right() - rect.left()            predictor_shape = self.predictor(self.img_gray, rect)            face_shape = face_utils.shape_to_np(predictor_shape)            face['cigarette'] = self.get_cigarette_info(face_shape, face_shades_width)            face['glasses'] = self.get_glasses_info(face_shape, face_shades_width)            faces.append(face)        return faces    def drawing(self, t):        """        动态画图        :param t:        :return:        """        draw_img = self.image.convert('RGBA')        if t == 0:            return np.asarray(draw_img)        for face in self.orientation():            if t <= self.duration - 2:                current_x = int(face["glasses"]["pos"][0])                current_y = int(face["glasses"]["pos"][1] * t / (self.duration - 2))                draw_img.paste(face["glasses"]["image"], (current_x, current_y), face["glasses"]["image"])                cigarette_x = int(face["cigarette"]["pos"][0])                cigarette_y = int(face["cigarette"]["pos"][1] * t / (self.duration - 2))                draw_img.paste(face["cigarette"]["image"], (cigarette_x, cigarette_y), face["cigarette"]["image"])            else:                draw_img.paste(face["glasses"]["image"], face["glasses"]["pos"], face["glasses"]["image"])                draw_img.paste(face["cigarette"]["image"], face["cigarette"]["pos"], face["cigarette"]["image"])                draw_img.paste(self.text, (75, draw_img.height // 2 + 128), self.text)        return np.asarray(draw_img)    def make_gif(self, gif_path=None):        """        :param gif_path: 保存路径        :return:        """        gif_path = gif_path or "deal.gif"        animation = mpy.VideoClip(self.drawing, duration=self.duration)        animation.write_gif(gif_path, fps=self.duration)if __name__ == '__main__':    FaceDetect('timg.jpg')

 

转载地址:https://blog.csdn.net/yukinoai/article/details/89293696 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:OpenCV-Python——小项目1:实现文档扫描
下一篇:OpenCV-Python——官方教程OpenCV-Python Tutorials翻译和例子下载

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月24日 05时12分40秒