chromakey: opencv 使绿屏视频透明
chromakey: opencv make green screen video transparent
我正在使用以下脚本将原始视频的绿屏替换为背景图像,但结果不是我所期望的,我更改了 u_green 数组参数以及 l_green 但情况只会变得更糟。
最后,我想透明我应该用哪个面具?
如能帮助解决此问题,我将不胜感激。
Python 脚本:
import cv2
import numpy as np
video = cv2.VideoCapture("green.mp4")
image = cv2.imread("bg.jpg")
while True:
ret, frame = video.read()
frame = cv2.resize(frame, (640, 480))
image = cv2.resize(image, (640, 480))
u_green = np.array([104, 153, 70])
l_green = np.array([30, 30, 0])
mask = cv2.inRange(frame, l_green, u_green)
res = cv2.bitwise_and(frame, frame, mask=mask)
f = frame - res
f = np.where(f == 0, f, image)
cv2.imshow("video", frame)
cv2.imshow("mask", f)
if cv2.waitKey(25) == 27:
break
video.release()
cv2.destroyAllWindows()
结果:
更新
源视频:
Link
我尽力使用 HSV 颜色遮盖屏幕 space。还有一些绿色的轮廓,但是我不能再增加颜色边距,除非剪掉一些衣服。
编辑:将代码包装在视频循环中。
编辑 2:我添加了一个 VideoWriter 来保存结果并切换到使用饱和通道,因为它有更好的分离度。
输出视频:
https://drive.google.com/file/d/1GrECFwFy7JQJT6kUGrfLtlXjcfBsr7fP/view?usp=sharing
import cv2
import numpy as np
# open up video
cap = cv2.VideoCapture("video.mp4");
# grab one frame
scale = 0.5;
_, frame = cap.read();
h,w = frame.shape[:2];
h = int(h*scale);
w = int(w*scale);
# videowriter
res = (w, h);
fourcc = cv2.VideoWriter_fourcc(*'XVID');
out = cv2.VideoWriter('test_vid.avi',fourcc, 30.0, res);
# loop
done = False;
while not done:
# get frame
ret, img = cap.read();
if not ret:
done = True;
continue;
# resize
img = cv2.resize(img, res);
# change to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV);
h,s,v = cv2.split(hsv);
# get uniques
unique_colors, counts = np.unique(s, return_counts=True);
# sort through and grab the most abundant unique color
big_color = None;
biggest = -1;
for a in range(len(unique_colors)):
if counts[a] > biggest:
biggest = counts[a];
big_color = int(unique_colors[a]);
# get the color mask
margin = 50;
mask = cv2.inRange(s, big_color - margin, big_color + margin);
# smooth out the mask and invert
kernel = np.ones((3,3), np.uint8);
mask = cv2.dilate(mask, kernel, iterations = 1);
mask = cv2.medianBlur(mask, 5);
mask = cv2.bitwise_not(mask);
# crop out the image
crop = np.zeros_like(img);
crop[mask == 255] = img[mask == 255];
# show
cv2.imshow("Mask", mask);
cv2.imshow("Blank", crop);
cv2.imshow("Image", img);
done = cv2.waitKey(1) == ord('q');
# save
out.write(crop);
# close caps
cap.release();
out.release();
我正在使用以下脚本将原始视频的绿屏替换为背景图像,但结果不是我所期望的,我更改了 u_green 数组参数以及 l_green 但情况只会变得更糟。 最后,我想透明我应该用哪个面具?
如能帮助解决此问题,我将不胜感激。
Python 脚本:
import cv2
import numpy as np
video = cv2.VideoCapture("green.mp4")
image = cv2.imread("bg.jpg")
while True:
ret, frame = video.read()
frame = cv2.resize(frame, (640, 480))
image = cv2.resize(image, (640, 480))
u_green = np.array([104, 153, 70])
l_green = np.array([30, 30, 0])
mask = cv2.inRange(frame, l_green, u_green)
res = cv2.bitwise_and(frame, frame, mask=mask)
f = frame - res
f = np.where(f == 0, f, image)
cv2.imshow("video", frame)
cv2.imshow("mask", f)
if cv2.waitKey(25) == 27:
break
video.release()
cv2.destroyAllWindows()
结果:
更新 源视频: Link
我尽力使用 HSV 颜色遮盖屏幕 space。还有一些绿色的轮廓,但是我不能再增加颜色边距,除非剪掉一些衣服。
编辑:将代码包装在视频循环中。
编辑 2:我添加了一个 VideoWriter 来保存结果并切换到使用饱和通道,因为它有更好的分离度。
输出视频:
https://drive.google.com/file/d/1GrECFwFy7JQJT6kUGrfLtlXjcfBsr7fP/view?usp=sharing
import cv2
import numpy as np
# open up video
cap = cv2.VideoCapture("video.mp4");
# grab one frame
scale = 0.5;
_, frame = cap.read();
h,w = frame.shape[:2];
h = int(h*scale);
w = int(w*scale);
# videowriter
res = (w, h);
fourcc = cv2.VideoWriter_fourcc(*'XVID');
out = cv2.VideoWriter('test_vid.avi',fourcc, 30.0, res);
# loop
done = False;
while not done:
# get frame
ret, img = cap.read();
if not ret:
done = True;
continue;
# resize
img = cv2.resize(img, res);
# change to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV);
h,s,v = cv2.split(hsv);
# get uniques
unique_colors, counts = np.unique(s, return_counts=True);
# sort through and grab the most abundant unique color
big_color = None;
biggest = -1;
for a in range(len(unique_colors)):
if counts[a] > biggest:
biggest = counts[a];
big_color = int(unique_colors[a]);
# get the color mask
margin = 50;
mask = cv2.inRange(s, big_color - margin, big_color + margin);
# smooth out the mask and invert
kernel = np.ones((3,3), np.uint8);
mask = cv2.dilate(mask, kernel, iterations = 1);
mask = cv2.medianBlur(mask, 5);
mask = cv2.bitwise_not(mask);
# crop out the image
crop = np.zeros_like(img);
crop[mask == 255] = img[mask == 255];
# show
cv2.imshow("Mask", mask);
cv2.imshow("Blank", crop);
cv2.imshow("Image", img);
done = cv2.waitKey(1) == ord('q');
# save
out.write(crop);
# close caps
cap.release();
out.release();