程序地带

使用OpenCV进行简单的人像分割与合成


图像合成
实现思路

通过背景建模的方法,对源图像中的动态人物前景进行分割,再将目标图像作为背景,进行合成操作,获得一个可用的合成影像。


实现步骤如下。


使用BackgroundSubtractorMOG2进行背景分割

BackgroundSubtractorMOG2是一个以高斯混合模型为基础的背景前景分割算法,


混合高斯模型


分布概率是K个高斯分布的和,每个高斯分布有属于自己的 (mu) 和 (sigma) 参数,以及对应的权重参数,权重值必须为正数,所有权重的和必须等于1,以确保公式给出数值是合理的概率密度值。换句话说如果我们把该公式对应的输入空间合并起来,结果将等于1。


回到原算法,它的一个特点是它为每一个像素选择一个合适数目的高斯分布。基于高斯模型的期望和标准差来判断混合高斯模型模型中的哪个高斯模型更有可能对应这个像素点,如果不符合就会被判定为前景。


使用人像识别填充面部信息
创建级联分类器
face_cascade = cv2.CascadeClassifier()
face_cascade.load(
"/usr/local/anaconda3/envs/OpenCV/lib/python3.8/site-packages/cv2/data/haarcascade_frontalface_default.xml")

使用OpenCV自带的级联分类器,加载OpenCV的基础人像识别数据。


识别源图像中的人像
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
使用形态学填充分割出来的前景
# 形态学开运算去噪点
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
for i in range(15):
fgmask = cv2.dilate(fgmask, kernel, iterations=1)

通过开操作去掉前景图像数组中的噪点,然后重复进行膨胀,填充前景轮廓。


将人像与目标背景进行合成
def resolve(o_img, mask, faces):
if len(faces) == 0:
return
(x, y, w, h) = faces[0]
rgb_mask_front = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
rgb_mask_front = cv2.bitwise_not(rgb_mask_front)
cv2.circle(rgb_mask_front, (int(x + w / 2), int(y + h / 2)), int((w + h) / 4), (0, 0, 0), thickness=-1)
o_img = cv2.subtract(o_img, rgb_mask_front)
return o_img

将分割出来的部分取反再与源图像进行减操作,相当于用一个Mask从原图中抠出一部分。


再与背景进行加操作


out = resolve(frame, fgmask, faces)
out = cv2.add(out, c_frame)
代码实现
import numpy as np
import cv2
import os
# 经典的测试视频
camera = cv2.VideoCapture("./source/background_test2.avi")
cap = cv2.VideoCapture("./source/camera_test2.avi")
face_cascade = cv2.CascadeClassifier()
face_cascade.load(
os.getcwd()+"/source/haarcascade_frontalface_default.xml")
# 形态学操作需要使用
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
# 创建混合高斯模型用于背景建模
fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows=False)
def resolve(o_img, mask, faces):
if len(faces) == 0:
return
(x, y, w, h) = faces[0]
rgb_mask_front = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
rgb_mask_front = cv2.bitwise_not(rgb_mask_front)
cv2.circle(rgb_mask_front, (int(x + w / 2), int(y + h / 2)), int((w + h) / 4), (0, 0, 0), thickness=-1)
o_img = cv2.subtract(o_img, rgb_mask_front)
return o_img
while True:
ret, frame = cap.read()
c_ret, c_frame = camera.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
fgmask = fgbg.apply(frame)
# 形态学开运算去噪点
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
gray_camera = cv2.cvtColor(c_frame, cv2.COLOR_BGR2GRAY)
for i in range(15):
fgmask = cv2.dilate(fgmask, kernel, iterations=1)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
out = resolve(frame, fgmask, faces)
out = cv2.add(out, c_frame)
cv2.imshow("Result", out)
cv2.imshow("Mask", fgmask)
k = cv2.waitKey(150) & 0xff
if k == 27:
break
out.release()
camera.release()
cap.release()
cv2.destroyAllWindows()

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/tanknee/p/14281641.html

随机推荐

五、剑指 Offer(20~24)

文章目录一、20表示数值的字符串1.算法描述2.算法题解二、21调整数组顺序使奇数位于偶数前面1.算法描述2.算法题解三、22链表中倒数第k个节点1.算法描述2.算法题解四、24反转链表1.算法描述2...

重启试试. 阅读(972)

一个文件_只用一个空格键就能实现文件预览

一个文件_只用一个空格键就能实现文件预览

每次做推送插图的时候总找不到想要的图?每次找文档都想要事先打开预览一下内容?每次找本地视频素材但是不知道视频内容?......那么这篇文章可能对你有很大用处文...

weixin_39571404 阅读(881)

nlp-知识图谱简介

nlp-知识图谱简介

知识图谱介绍目录知识图谱介绍一、知识图谱简介1.1引言1.2什么是知识图谱呢?1.2.1什么是图(Graph)呢?1.2.2什么是Schema呢...

疯子书生z 阅读(875)

USB转TTL串口板使用问题

PC端与下位机无法通信常见的硬件问题:0.TX、RX接反了。1.如果串口板直接插pc的usb口,那极大可能是串口板挂了,需要把串口板断电后,重新...

破洞的手机壳 阅读(981)

在ubuntu下cuda out of mermory解决方法

在ubuntu下cuda out of mermory解决方法

Cudaoutofmemory解决方法因为电脑配置过于渣渣,经常在训练神经网络的时候出现提示:cudaoutofmermroy,大多数的时候就很羡慕别人实验室...

madao10086+ 阅读(496)