opencv实战案例之视频绿幕背景替换

视频绿幕替换

将视频中绿幕背景替换为其它图片,新闻报道中常用


处理方法

  • GMM或者KMeans方法太慢,视频容易卡顿
  • 基于色彩处理方法
    • RGB到HSV色彩空间,颜色过滤获取掩膜,速度快

在这里插入图片描述


HSV空间各种颜色分布范围

在这里插入图片描述


代码

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace  std;
using namespace cv;

Mat frame,hsv,mask,dst;
Mat bkimg;
Mat replace_and_blend(Mat &frame,Mat &mask);
int main(void)
{
    bkimg = imread("/work/opencv_pic/lijing.jpg");
    if(bkimg.empty())
    {
        cout << "back img is empty"<< endl;
        return -1;
    }
    namedWindow("原始视频",0);
    resizeWindow("原始视频",640,360);
    moveWindow("原始视频",50,20);

    namedWindow("效果视频",0);
    resizeWindow("效果视频",640,360);
    moveWindow("效果视频",2000,20);

    namedWindow("背景图片",0);
    resizeWindow("背景图片",640,360);
    moveWindow("背景图片",300,800);

    imshow("背景图片",bkimg);

    VideoCapture cap;
    if(!cap.open("/work/opencv_video/绿屏抠像花瓣雨素材.mp4"))
    {
        cout<<"open video fail" <<endl;
        return -1;
    }
    while(true)
    {
        cap>>frame;
        if(frame.empty())
        {
            cout << "frame is empty"<<endl;
            break;
        }

        imshow("原始视频",frame);
        cvtColor(frame,hsv,COLOR_BGR2HSV);
        //颜色选择
        inRange(hsv,Scalar(35,43,46),Scalar(77,255,255),mask);

        //图形学处理 平滑mask;
        Mat kernel = getStructuringElement(MORPH_RECT,Size(3,3));
        morphologyEx(mask,mask,MORPH_OPEN,kernel);
        //高斯处理 边缘更平滑 效果更好看
        GaussianBlur(mask,mask,Size(3,3),0,0);
       
        dst = replace_and_blend(frame,mask);
        imshow("效果视频",dst);
        if(waitKey(1)>0)
            break;
    }
    destroyAllWindows();
    return 0;
}

Mat replace_and_blend(Mat &frame,Mat &mask)
{
    Mat result = Mat::zeros(frame.size(),frame.type());
    int h = frame.rows;
    int w = frame.cols;
    int m = 0;
    double wt = 0;

    int b=0,g=0,r=0;
    int b1=0,g1=0,r1=0;
    int b2=0,g2=0,r2=0;

    for(int row=0;row <h;row++)
    {
        uchar *current = frame.ptr<uchar>(row);
        uchar *bgrow = bkimg.ptr<uchar>(row);
        uchar *maskrow = mask.ptr<uchar>(row);
        uchar *targetrow = result.ptr<uchar>(row);

        for(int col=0;col<w;col++)
        {
            m = *maskrow++;
            if(m == 255)   //如果是背景 替换为背景数据
            {
                *targetrow++ = *bgrow++;
                *targetrow++ = *bgrow++;
                *targetrow++ = *bgrow++;
                current += 3;
            }else if(m == 0) //如果是前景 保留原来数据
            {
                *targetrow++ = *current++;
                *targetrow++ = *current++;
                *targetrow++ = *current++;
                bgrow += 3;
            }else //由于形态学平滑造成的过渡区 颜色采用加权均衡化
            {
                b1 = *bgrow++;
                g1 = *bgrow++;
                r1 = *bgrow++;

                b2 = *current++;
                g2 = *current++;
                r2 = *current++;

                wt = m/255.0;

                b = b1*wt + b2*(1-wt);
                g = g1*wt + g2*(1-wt);
                r = b1*wt + r2*(1-wt);

                *targetrow++ = b;
                *targetrow++ = g;
                *targetrow++ = r;

            }
        }
    }
        return result;  //返回结果
}


效果

在这里插入图片描述


  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值