使用cv2、np对视频进行抠图、替换背景

对图像处理一窍不通的我,竟然开始搞图像了!!!!话不多说,直接开干!

1、首先对视频逐帧读取图片

2、对读取的图片进行抠图

3、生成mask

4、读取mask、抠图、背景图片进行融合

5、将替换背景后的图片写入视频

代码完成:

1、逐帧读取图片函数

(1)计算视频的总帧数total_frames

(2)通过帧数截取视频图片

(3)使用cv2.imwrite()将帧数对应的图像写入文件夹

def make_frame_img(video_path, output_path):
    """
    从视频文件中抽取帧数图片,保存到指定路径
    参数:
    video_path: 输入视频路径
    output_path: 保存帧图片文件夹
 
    return 无
    """
    # 读取视频文件
    cap = cv2.VideoCapture(video_path)

    # 检查视频是否成功打开  
    if not cap.isOpened():  
        print("无法打开视频文件:", video_path)  
        return
    
    # 获取视频帧率和总帧数
    fps = cap.get(cv2.CAP_PROP_FPS)
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    # 如果没有创建输出文件夹,则创建输出文件夹
    if not os.path.exists(output_path):
        os.makedirs(output_path)

    # 分割视频为照片
    for i in tqdm(range(total_frames)):
        ret, frame = cap.read()
        if ret:
    
        # 保存照片
            filename = f'frame_%04d.jpg' % i
            filepath = os.path.join(output_path, filename)
            cv2.imwrite(filepath, frame)

        else:
            break

2、对图片进行抠图,使用了P3M-Net算法实现对图像的抠图(​​​​​​GitHub - ViTAE-Transformer/P3M-Net: The official repo for [IJCV'23] "Rethinking Portrait Matting with Privacy Preserving"

或者是使用PIL中的Image:

from PIL import Image
from rembg import remove
import cv2

save_path = './image_save_path/' # 图像输出路径

# 先打开要抠图的图片
img = Image.open('./usings_img.jpg)

# 处理
img = remove(img)

# 保存
img = cv2.cvtColor(np.array(img), cv2.COLOR_RGBA2BGR)
cv2.imwrite(save_path , img)

3、4、对图像读取背景图像、创建mask

(1)mask的获取:由于P3M net生成的抠图已经完备,可以直接将foreground_img3个通道的sum>0作为mask,此时mask变为2维,再给mask增加第三维度,即通道数。

(2)背景图像与抠图融合:融合图像= 抠图*mask + 背景图*(1-mask)

(3)将获取的融合图像写入文件。

def change_background(foreground_path, background_path, output_path):
    """
    将扣图与背景图片结合,得到新图片
    参数:
    foreground_path 抠图路径
    background_path 背景图路径
    output_path 输出路径

    返回值:无

    """
    image_files = [f for f in os.listdir(foreground_path) if f.endswith('.png')]
    image_files.sort()

    for i in tqdm(image_files):
        foreground_img = cv2.imread(os.path.join(foreground_path, i))
        background_img = cv2.imread(background_path)

        background_img = cv2.resize(background_img, (720,1280))

        mask = np.sum(foreground_img.astype("int64"), axis=-1) > 0
        mask = np.tile(mask[:, :, None], (1, 1, 3))

        filepath = os.path.join(output_path, f'new_{i}')
        result = foreground_img *mask + background_img *(1-mask)
        cv2.imwrite(filepath, result)

5、图象生成视频

cv2.imread()获取替换背景后的图象,cv2.imwrite()写入视频

def merge_to_video(img_path, output_video_path):
    """
    将图片合成视频
    参数:
    img_path 输入图片路径
    output_video_path 输出视频路径

    return 无
    
    """
    # 传入输入路径中的所有图像
    image_files = [f for f in os.listdir(img_path) if f.endswith(".png")]
    image_files.sort()
    # 获取图像尺寸
    img = cv2.imread(os.path.join(img_path, image_files[0]))
    height, width, _ = img.shape

    # 创建用于写入视频的VideoWriter对象
    video_writer = cv2.VideoWriter(output_video_path, cv2.VideoWriter_fourcc(*"mp4v"), 30, (width, height))

    # 逐个读取图像并将其写入视频
    for image_file in tqdm(image_files):
        img = cv2.imread(os.path.join(img_path, image_file))
        video_writer.write(img) 

    video_writer.release()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值