python恶搞代码打开对方摄像头_用Python获取摄像头并实时控制人脸的实现示例

实现流程

从摄像头获取视频流,并转换为一帧一帧的图像,然后将图像信息传递给opencv这个工具库处理,返回灰度图像(就像你使用本地静态图片一样)

程序启动后,根据监听器信息,使用一个while循环,不断的加载视频图像,然后返回给opencv工具呈现图像信息。

创建一个键盘事件监听,按下"d"键,则开始执行面部匹配,并进行面具加载(这个过程是动态的,你可以随时移动)。

面部匹配使用Dlib中的人脸检测算法来查看是否有人脸存在。如果有,它将为每个人脸创建一个结束位置,眼镜和烟卷会移动到那里结束。

然后我们需要缩放和旋转我们的眼镜以适合每个人的脸。我们将使用从Dlib的68点模型返回的点集来找到眼睛和嘴巴的中心,并为它们之间的空间旋转。

在我们实时获取眼镜和烟卷的最终位置后,眼镜和烟卷从屏幕顶部进入,开始匹配你的眼镜和嘴巴。

假如没有人脸,程序会直接返回你的视频信息,不会有面具移动的效果。

默认一个周期是4秒钟。然后你可以通过"d"键再次检测。

程序退出使用"q"键。

这里我将这个功能抽象成一个面具加载服务,请跟随我的代码一窥究竟吧。

1.导入对应的工具包

from time import sleep

import cv2

import numpy as np

from PIL import Image

from imutils import face_utils, resize

try:

from dlib import get_frontal_face_detector, shape_predictor

except ImportError:

raise

创建面具加载服务类DynamicStreamMaskService及其对应的初始化属性:

class 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.1 # 面具移动速度

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 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 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 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"]

)

上面基本的功能都实现了,我们该实现画图函数了,这个函数原理和之前我写的那篇用AI人脸识别技术实现抖音特效实现是一样的,这里我就不赘述了,可以去github或Python中文社区微信公众号查看。

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)

既然是一个服务类,那该有启动与退出函数吧,最后我们来写一下吧。

简单介绍一下这个start()函数, 启动后根据初始化监听信息,不断监听视频流,并将流信息通过opencv转换成图像展示出来。

并且调用按键监听函数,不断的监听你是否按下"d"键进行面具加载,如果监听成功,则进行图像人脸检测,并移动面具,

并持续一个周期的时间结束,面具此时会根据你的面部移动而移动。最终呈现文章顶部图片的效果.

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 exit(self):

"""

程序退出

:return:

"""

self.video_capture.release()

cv2.destroyAllWindows()

最后,让我们试试:

if __name__ == '__main__':

ms = DynamicStreamMaskService()

ms.start()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/472920.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 992. K 个不同整数的子数组(双指针)

文章目录1. 题目2. 解题1. 题目 给定一个正整数数组 A&#xff0c;如果 A 的某个子数组中不同整数的个数恰好为 K&#xff0c;则称 A 的这个连续、不一定独立的子数组为好子数组。 &#xff08;例如&#xff0c;[1,2,3,1,2] 中有 3 个不同的整数&#xff1a;1&#xff0c;2&a…

压缩可以卸载吗_番禺街坊注意!微信发送高清大文件不压缩,网友:QQ可以卸载了?...

刚上新了表情包的微信又双叒叕出新功能了这次的功能有点实用昨天&#xff0c;腾讯微信团队宣布微信已支持向朋友发送高清视频和图片且不会被压缩微信用户点击对话框右下角的号右滑点击文件在上方选择手机相册就能选择用户想要发送的视频和图片了目前通过「文件」方式发送的内容…

从一个视图控制器切换到另一个视图控制器的几种方式

从一个视图控制器切换到另一个视图控制器的几种方式1,模态(modal)画面的显示方法&#xff1a;例如iphone通讯录管理程序中&#xff0c;追加新的通讯纪录时&#xff0c;就是使用这种模态画面例&#xff1a;点击一个按钮&#xff0c;进入另一个界面- (IBAction)pressAbout:(id)se…

python暂停和恢复_python – 暂停和恢复QThread

我正在尝试暂停QThread并恢复它. 所以,我在QThread中有一个RFID读取循环,我想在阅读器获得RFID代码时暂停无限循环.之后,有一个数据库检查.在检查结束时,我想恢复RFID阅读循环以获取其他代码. MVCE&#xff1a; def main(): global Thread app QtGui.QApplication(sys.argv) m…

date format 精辟讲解

link: http://stackoverflow.com/questions/19533933/nsdateformatter-how-to-convert-wed-23-oct-2013-045615-gmt-to-local-time转载于:https://www.cnblogs.com/ouyangfang/p/4028508.html

python怎么给画布填上颜色_python numpy matplotlib画小方块填充背景色和添加不同色彩的文字...

需要根据不同的数值生成不同色彩的小方块&#xff0c;并标明数值&#xff0c;考虑到各种色彩的方块&#xff0c;如果采用文字采用黑色或者白色总是避免不了和背景色重复&#xff0c;所以把数值转化成rgb(0x11,0xf0,0x3b)类似的值&#xff0c;然后文字采用rgb(255-0x11,255-0xf0…

LeetCode 1755. 最接近目标值的子序列和(状态枚举 + 双指针)

文章目录1. 题目2. 解题1. 题目 给你一个整数数组 nums 和一个目标值 goal 。 你需要从 nums 中选出一个子序列&#xff0c;使子序列元素总和最接近 goal 。 也就是说&#xff0c;如果子序列元素和为 sum &#xff0c;你需要 最小化绝对差 abs(sum - goal) 。 返回 abs(sum …

python简单实践作业答案_python入门实践四:爬取牛客网面试专项练习题及答案

说明:个人练手python用。操作系统&#xff1a;window10 x64IDE&#xff1a;Pycharm 2017.2.2Python版本&#xff1a;3.6.2目标牛客网是一个IT笔试面试的平台&#xff0c;提供了很多题库&#xff0c;今天我们使用python爬取其中的Java专项练习库。步骤1、接口抓取&#xff1a;如…

路由器距离向量算法计算举例_路由器基本原理是什么 路由器基本发展情况介绍【图文】...

PLC路由器原理和ARR路由器基本原理要实现网络中通信节点彼此之间的通信&#xff0c;首先必须给每个节点分配一个唯一的IP地址。路由器应该至少有两个网络端口&#xff0c;分别连接LAN或者WAN子网上&#xff0c;每个端口必须具有一个唯一的IP地址&#xff0c;并且要求与所连接IP…

Git 常用命令整理(持续更新)

#配置 git config --global user.name "Your Name" git config --global user.email "emailexample.com" #注意git config命令的--global参数&#xff0c;用了这个参数&#xff0c;表示这台机器上所有的Git仓库都会使用这个配置&#xff0c;当然也可以对某…

LintCode MySQL 1918. 第二高的球员的身高

文章目录1. 题目2. 解题1. 题目 编写一个 SQL 语句&#xff0c;获取球员 (players) 表中第二高的身高 (height) 表定义: players (球员表) https://www.lintcode.com/problem/1918 2. 解题 if(a,b,c), a true&#xff0c;执行 b&#xff0c; 否则 c -- Write your SQL Que…

matlab多种分配方案_基于MATLAB的水资源优化分配问题动态规划解法

基于MATLAB的水资源优化分配问题动态规划解法摘要&#xff1a;介绍了动态规划的基本原理&#xff0c;针对水资源分配问题进行了动态规划方法分析。针对具体问题采用逆序解法的表格法进行了计算&#xff0c;然后用matlab编制了相应的计算程序进行计算&#xff0c;避免了繁琐的人…

python中使用opencv_如何在Python中使用OpenCV Stitcher类?

你正确使用它,因为某些原因导致进程失败. 结果元组的第一个值是错误代码,0表示成功.这里你得到1,这意味着,根据stitching.hpp,这个过程需要更多的图像. enum Status { OK 0, ERR_NEED_MORE_IMGS 1, ERR_HOMOGRAPHY_EST_FAIL 2, ERR_CAMERA_PARAMS_ADJUST_FAIL 3 }; ERR_NEE…

《高可用MySQL》2 – 单机版MySQL主从配置

这里搭建的主从是最简单的单一主从复制&#xff08;即一个Master和一个slave&#xff0c;没有任何的热机备份和多slave&#xff09;&#xff0c;该主从结构的基本拓扑图如下所示&#xff1a; 建立基本的主从复制可以总结为以下三个基本步骤&#xff1a; 配置master服务器配置sl…

LintCode MySQL 1936. 张三的故事 III

文章目录1. 题目2. 解题1. 题目 记者调查发现&#xff0c;张三所在学校还有一金牌教师&#xff0c;其所带的学生毕业后人均知名学府。 记者对该老师所教的学生的情况产生了好奇。 students 表中记录了学生的姓名以及班级 (class_id)&#xff0c;classes 表中记录了班级的名称以…

语言4位bcd码怎么加加_S7300400如何使用SCL语言调用SFC1(READ_CLK)读取日期和时间?...

系统功能 SFC1 用于读取 CPU 的系统时钟。系统时钟存储在数据类型为DATE_AND_TIME的变量里。通过指针访问系统时钟的单个组成元素。数据类型DATE_AND_TIME所包含的关于年、月、日、时等信息是以 BCD 码的格式存储在 8 个字节里。该数据类型显示的范围是&#xff1a;DT#1990-1-1…

php数据库操作命令精华大全

1、表结构//列信息2、表数据//行信息3、表索引//把列中的行加到索引中&#xff08;一般情况下一个表一定要把id这一列的所有数据都加到主键索引中&#xff09; 2、[dos下]关闭mysql:net stop mysql开启mysql:net start mysql登陆mysql:mysql -uroot -p123 --teec:\mysql.log查看…

python装饰器与闭包_python 装饰器和闭包

装饰器 就是函数 功能是为其他函数添加附加功能 def timer(func): def inner(*args,**kwargs): print("执行装饰器") return func(*args,**kwargs) return inner 使用装饰器 timer def test(l): for i in range(l): print(i) test(100) 函数也可以成为对象 l test .…

LintCode MySQL 1932/1933. 挂科最多的同学 I / II

文章目录1. 题目2. 解题1. 题目 exams 表中存放着同学们的考试记录 请用 SQL 语句&#xff0c;找到挂科数最多的同学所对应的 student_id https://www.lintcode.com/problem/1932 2. 解题 -- Write your SQL Query here -- -- example: SELECT * FROM XX_TABLE WHERE XXX…

python 画三角函数_python,将三角函数绘制成二维数组

看起来a, b, c是常量&#xff0c;z是a和{}之间的np.linspace。在a 1 b 2 c 3 def triangle (z, a a, b b, c c): y np.zeros(z.shape) y[z < a] 0 y[z > c] 0 first_half np.logical_and(a < z, z < b) y[first_half] (z[first_half]-a) / (b-a) second…