一、静态图片的背景替换
以证件照替换背景颜色为例子(网上找了个证件照,脸已遮住),其中需要注意的是对蒙版做平滑处理,否则毛刺会比较明显。
# coding = utf-8
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
# 载入图像
img = cv.imread('timg.jpg')
rows, cols, channels = img.shape
cv.imshow('img',img)
# 转换hsv,得到轮廓蒙版
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
lower_blue = np.array([78,43,46])
upper_blue = np.array([99,255,255])
mask = cv.inRange(hsv, lower_blue, upper_blue)
# 采用中值滤波平滑边缘
mask = cv.medianBlur(mask, 15)
cv.imshow('Mask', mask)
# 腐蚀膨胀(形态学处理)
erode = cv.erode(mask,None,iterations=1)
dilate = cv.dilate(erode,None,iterations=1)
cv.imshow('dilate',dilate)
# 遍历替换颜色
for i in range(rows):
for j in range(cols):
if dilate[i,j]==255:
img[i,j]=(0,0,255) # 此处替换颜色,为BGR通道
cv.imshow('res', img)
cv.waitKey(0)
cv.destroyAllWindows()
膨胀和腐蚀称为形态运算。通常在二元图像上执行,类似于轮廓检测。膨胀通过向图像中的对象的边缘添加像素,放大亮白区域。腐蚀正好相反:它会删除对象边缘的像素,并缩小对象的大小。
(1)膨胀
要在 OpenCV 中膨胀图像,你可以使用 dilate 函数和三个输入:原始二元图像、确定膨胀大小的内核(均不会导致默认大小)以及进行膨胀的迭代次数(通常为 1)。在下面的示例中,我们用到一个 5x5 内核,它像过滤器一样在图像上移动,如果在 5x5 窗口中,像素周围的任何像素是白色,则使该像素变成白色!
kernel = np.ones((5,5),np.uint8)
dilation = cv2.dilate(image, kernel, iterations = 1)
(2)腐蚀
要腐蚀图像,我们将采用相同的步骤,但是使用 erode 函数。
erosion = cv2.erode(image, kernel, iterations = 1)
(3)开运算
我们通常结合上述两者一起使用以达到期望的结果。一种此类结合运算称为开运算,即先腐蚀后膨胀。有助于降噪,腐蚀先消除噪点(并缩小对象),然后膨胀会再次放大对象,但是之前的腐蚀已经消除噪点!
在 OpenCV 中实现这一点,我们对原图采用函数 morphologyEx,执行想要执行的操作并传入内核。
opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
(4)闭运算
闭运算是开运算的逆向组合,先膨胀后腐蚀,有助于填充对象上的小洞或黑色区域。
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
了解更多
二、视频的背景替换
基于hsv颜色空间的实时背景替换:
# coding = utf-8
import numpy as np
import cv2 as cv
import time
def backReplace(img):
'''
替换视频帧背景
'''
# 转换hsv
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
lower_blue = np.array([0,0,46])
upper_blue = np.array([180,43,220])
mask = cv.inRange(hsv, lower_blue, upper_blue)
# 采用中值滤波平滑边缘
mask = cv.medianBlur(mask, 15)
# 腐蚀膨胀
erode = cv.erode(mask,None,iterations=2)
dilate = cv.dilate(erode,None,iterations=3)
# 遍历替换
for i in range(img.shape[0]):
for j in range(img.shape[1]):
if dilate[i,j]==255:
img[i,j]=(0,0,255) # 此处替换颜色,为BGR通道
return img
def video_save(num_frames, filepath, out_fps):
'''
打开摄像头并保存视频
INPUT -> 捕获总帧数, 视频保存路径, 输出帧率
'''
cap = cv.VideoCapture(0) # VideoCapture(0)表示打开默认的相机
if cap.isOpened() is False: # 确认摄像头是否成功打开
print('Error')
exit(1)
# 获取捕获的分辨率
size = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)),
int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))
# 设置要保存视频的编码,分辨率和帧率
video = cv.VideoWriter(
filepath,
cv.VideoWriter_fourcc('M', 'P', '4', '2'), # 视频编码格式参考:http://www.fourcc.org/codecs.php
out_fps, # 输出文件的帧率
size
)
for i in range(num_frames):
ret, frame = cap.read()
video.write(backReplace(frame))
# time.sleep(interval) 捕获图像的间隔(秒)
# 释放资源并写入视频文件
video.release()
cap.release()
video_save(50, '100000.avi', 24)
附:hsv颜色空间
H: 0-180 S:0-255 V:0-255
网友评论