利用OpenCV实现绿幕视频背景替换
创作时间:
作者:
@小白创作中心
利用OpenCV实现绿幕视频背景替换
引用
1
来源
1.
https://www.zhangshengrong.com/p/w4N7DxxgXr/
本文将详细介绍如何使用OpenCV C++实现绿幕视频背景替换。通过将视频转换为HSV色彩空间,使用inRange函数进行颜色范围筛选,最后通过像素赋值实现背景替换。文章包含完整的代码示例和步骤说明,适合有一定编程基础的读者学习参考。
前言
本文将使用OpenCV C++ 进行绿幕视频背景替换。
一、图像预处理
背景
绿幕视频
首先,我们需要使用resize API将背景图尺寸修改与视频尺寸大小。这样才能进行后续的像素赋值操作。
Mat bg = imread("background.jpg"); //背景图
VideoCapture capture; //读取待处理的绿幕视频
capture.open("5.flv");
if (!capture.isOpened())
{
cout << "Can not open video!" << endl;
system("pause");
return -1;
}
int width = capture.get(CAP_PROP_FRAME_WIDTH);
int height = capture.get(CAP_PROP_FRAME_HEIGHT);
resize(bg, bg, Size(width, height), 1, 1, INTER_CUBIC); //将背景图resize成视频尺寸大小
二、HSV色彩空间转换
1. cvtColor色彩空间转换
cvtColor(frame, HSV, COLOR_BGR2HSV); //将原图转换成HSV色彩空间
2. inRange抠图
经百度查表,我们可以获取绿色HSV颜色分量范围
//绿色HSV颜色分量范围
int hmin = 35, smin = 43, vmin = 46;
int hmax = 77, smax = 255, vmax = 255;
由于我们已经将原图转换为HSV色彩空间,故可以使用inRange API将前景从绿幕中抠出来。inRange将两阈值内的像素置为255(即绿色被置为白色),阈值外的像素置为0(其他颜色被置为黑色)。故由此我们可以将前景抠出来。
//经过inRange API处理,输出一张二值图像,即将前景从绿幕中扣出来啦
inRange(HSV, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), mask);
mask图像,即从绿幕中抠出来的前景图。
三、背景替换
我们通过修改图像像素值达到替换背景目的。通过遍历视频图像像素值,当mask像素值为0时,表示此时图像像素为前景,将绿幕视频当前像素点赋给目标图像dst;当mask像素值为255时,表示此时图像像素为背景,将背景图当前像素点赋给目标图像dst。
Mat Replace_Background(Mat frame, Mat mask, Mat bg)
{
Mat dst = Mat::zeros(frame.size(), frame.type());
for (int i = 0; i < frame.rows; i++)
{
for (int j = 0; j < frame.cols; j++)
{
int p = mask.at<uchar>(i, j); //传入的mask是张二值图,p为当前mask像素值
if (p == 0)
{ //代表mask此时为前景,将绿幕视频中的前景像素赋给dst
dst.at<Vec3b>(i, j) = frame.at<Vec3b>(i, j);
}
else if (p == 255)
{
//代表mask此时为背景,将背景图像素赋给dst
dst.at<Vec3b>(i, j) = bg.at<Vec3b>(i,j);
}
}
}
return dst;
}
最终效果如图所示。
四、源码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat Replace_Background(Mat frame, Mat mask, Mat bg)
{
Mat dst = Mat::zeros(frame.size(), frame.type());
for (int i = 0; i < frame.rows; i++)
{
for (int j = 0; j < frame.cols; j++)
{
int p = mask.at<uchar>(i, j); //传入的mask是张二值图,p为当前mask像素值
if (p == 0)
{ //代表mask此时为前景,将绿幕视频中的前景像素赋给dst
dst.at<Vec3b>(i, j) = frame.at<Vec3b>(i, j);
}
else if (p == 255)
{
//代表mask此时为背景,将背景图像素赋给dst
dst.at<Vec3b>(i, j) = bg.at<Vec3b>(i,j);
}
}
}
return dst;
}
int main()
{
Mat bg = imread("background.jpg"); //背景图
VideoCapture capture; //读取待处理的绿幕视频
capture.open("5.flv");
if (!capture.isOpened())
{
cout << "Can not open video!" << endl;
system("pause");
return -1;
}
int width = capture.get(CAP_PROP_FRAME_WIDTH);
int height = capture.get(CAP_PROP_FRAME_HEIGHT);
resize(bg, bg, Size(width, height), 1, 1, INTER_CUBIC); //将背景图resize成视频尺寸大小
Mat frame, HSV, mask, dst;
//绿色HSV颜色分量范围
int hmin = 35, smin = 43, vmin = 46;
int hmax = 77, smax = 255, vmax = 255;
while (capture.read(frame))
{
cvtColor(frame, HSV, COLOR_BGR2HSV); //将原图转换成HSV色彩空间
//经过inRange API处理,输出一张二值图像,即将前景从绿幕中扣出来啦
inRange(HSV, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), mask);
dst = Replace_Background(frame, mask, bg);
imshow("demo", frame);
//imwrite("frame.jpg", frame);
imshow("mask", mask);
//imwrite("mask.jpg", mask);
imshow("dst", dst);
//imwrite("dst.jpg", dst);
char key = waitKey(10);
if (key == 27)
{
break;
}
}
destroyAllWindows();
capture.release();
system("pause");
return 0;
}
总结
本文使用OpenCV C++进行绿幕视频背景替换,关键步骤有以下几点。
1、将原图转换成HSV色彩空间。
2、使用inRange API将前景从绿幕中抠出来,得到一张二值图。
3、通过像素赋值操作达到背景替换效果。
到此这篇关于利用OpenCV实现绿幕视频背景替换的文章就介绍到这了,更多相关OpenCV绿幕视频背景替换内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
热门推荐
《倚天屠龙记》十大高手排名
民间借贷的法律规定、起诉形式和种类
东城中医医院特聘专家李志红:七种养胃粥品,助你调理脾胃
英国医院将用AI“死亡计算器”预测寿命:明年开始试用,将招募数百名患者
押一付三是什么意思
黄金兑美元的技术分析要点及实际应用
张雪峰:这8大专业你不要选,慎选?还是不选?
Excel单元格格式详解:从基础到进阶的全面指南
多喝碱性水对身体有什么好处
留学圈“四大排名”的优缺点,哪个更靠谱?
新题有没有一些简单好懂的英文书推荐吗?
深圳市大学生就业补贴申请指南
蝙蝠:古人心中的神秘象征
怎样运动能瘦大腿
《了不起的修仙模拟器》轮回者选哪个?高属性轮回者推荐攻略
Redis与DB库(持续化存储)之间的数据双写一致性保证
珠海买房哪个区潜力大?
奶油蘑菇汤
如何实现思维导图简单漂亮?其实并不难
带通信号采样定理与频谱搬移过程详解
全面解析XMP和EXPO内存技术,助你轻松实现性能飞跃
6个要点实现PPT排版对齐
掌握PPT动态效果制作,提升你的演示魅力
被人言语羞辱时,不必翻脸,学会三招回击方式,才是真正的高情商
专家咨询费发票开具与入账指南
动力储能电池大容量 24V200Ah 磷酸铁锂电池:机器人的强大动力源
推动电力系统调节能力显著提升(锐财经)
守护传统医学之火— “守艾人”与艾灸文化的传承与发展
邢台市新增文物点位18处
什么是数据标注,为什么需要数据标注?