chromakey:opencv 使绿屏视频透明

问题描述

我正在使用下面的脚本用背景图像替换原始视频的绿屏,但结果不是我所期望的,我已经更改了 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,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()

结果

enter image description here

更新 源视频: Link

解决方法

我尽最大努力使用 HSV 色彩空间屏蔽了屏幕。还有一些绿色的轮廓,但我不能在不剪掉衣服的情况下再增加色边。

编辑:将代码包裹在视频循环中。

编辑 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();