使用过qq视频聊天功能的朋友应该都知道它有一个自动为我们加特效的功能,虽然自带中二 ヽ(ー_ー)ノ,但是能够将挂饰精准加到适应的位置,尚且值得我辈学习。废话不多说,直接开正题: 先上一下效果: 大象装入冰箱,分为三个步骤。要在我们的脸上糊一个挂饰,第一步必须找到眼睛,这一步本菜用的是OpenCV的级联分类器CascadeClassifier。 detectMultiScale()方法返回的是一个二维的numpy向量,通俗讲,就是返回一个存放所有识别结果坐标和长宽的列表,这里就是我们眼睛所在位置以及眼睛的大小。为使挂饰糊的稳准狠,我们还需要对这个列表处理一下,算出挂饰的坐标和长宽。 OK,当我们已经把眼睛得位置找到,试问还有什么能够阻挡我们把东西糊在脸上的冲动,接下来我们只需要安安静静的做一个没有感情的糊脸机器,代码如下: PIL的paste()方法可以把一张图片糊在另外一张图片上,very契合我们的需求~但是要注意,我们这里双向操作,一会儿用PIL,一会儿用CV2,为了避免这两个大大之间打架报错,必须要通过numpy大佬中间调停,把两者的格式转换。 完成上面两步,基本就可以实现挂饰糊脸的功能,但…当代码跑起来了,本菜也傻球了…因为通过分类器识别,时而会出现只识别出一只眼睛的情况,当这种情况出现时,根据我们的坐标换算方法,挂饰会变成超级巨无霸,就不是把挂饰糊眼睛上了,真真是直接糊在脸上,么得一丝感情那种。 OK,接下来,就可以开开心心的糊脸了~望大家糊的开心。
python实现qq视频加特效
from PIL import Image import numpy import cv2
一、识别器官(本例以眼睛为例)
这个CascadeClassifier类,及其牛逼而强大,本菜这一步直接用大神训练好的分类器,在视频帧中找到眼睛的位置。如下:old_data = None detector = cv2.CascadeClassifier("haarcascade_lefteye_2splits.xml") cap = cv2.VideoCapture(0) while True: _, frame = cap.read() # 4.png是要糊在眼睛上的挂饰 pendant = Image.open("4.png") frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) rects = detector.detectMultiScale(frame_gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) eye_x, eye_y, eye_w, eye_h = get_rect(rects)
def get_rect(rects): pen_x = 0 pen_y = 0 pen_w = 0 pen_h = 0 for i, (x, y, w, h) in enumerate(rects): # 俩眼睛一般人都是竖直方向位置一直,高度也大概相同 pen_y = y pen_h = h # 挂饰的水平坐标需要时左边那个,宽度的计算为:x2-x1+w2 if not i: pen_x = x pen_w -= x else: if x > pen_x: pen_w += (x + w) else: pen_x = x pen_w = -pen_w - x + w return pen_x, pen_y, pen_w, pen_h
二、挂饰糊脸
为了让挂饰糊的稳准狠,我们这里对参数进行了一次”微”调整。frame = add_pendant(pen_x-int(pen_w*0.25), pen_y-int(pen_h*0.25), frame, pendant)
其次,RGBA格式的A层为图片的透明层。paste()方法的mask参数能给我们要糊上去的挂饰加一层蒙版,把透明层给去掉,否则透明层会被自动识别为黑色,那么我们糊的东西就不再beautiful了。def add_pendant(x, y, frame, pendant): frame = numpy.array(frame) frame_img = Image.fromarray(frame) pendant = pendant.convert('RGBA') frame_img.paste(pendant, (x, y), mask=pendant.split()[3]) frame = numpy.asarray(frame_img) return frame
三、装饰精修
因而,我们还要对挂饰的坐标进行一次修正,如下:pen_x, pen_y, pen_w, pen_h = get_rect(rects) if old_data is not None: pen_x, pen_y, pen_w, pen_h = check_data(pen_x, pen_y, pen_w, pen_h, old_data) try: pendant = pendant.resize((int(pen_w*1.5), int(pen_h*1.5))) except Exception as e: pass frame = add_pendant(pen_x-int(pen_w*0.25), pen_y-int(pen_h*0.25), frame, pendant) old_data = [pen_x, pen_y, pen_w, pen_h]
def check_data(eye_x, eye_y, eye_w, eye_h, old_data): scale_factor = 0.5 if (abs(eye_x - old_data[0]) > scale_factor * old_data[0] or abs(eye_y - old_data[1]) > scale_factor * old_data[1] or abs(eye_w - old_data[2]) >= scale_factor * old_data[2] or abs(eye_h - old_data[3]) >= scale_factor * old_data[3]): return old_data[0], old_data[1], old_data[2], old_data[3] return eye_x, eye_y, eye_w, eye_h
全代码见这里,可以点个星再走哦~
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算