一、背景知识
Keying,即抠像,从一幅图像中提取所要的前景,让它与背景分离起来。Key通常只包含一个通道,是一幅黑白图像,通常黑色的区域(0)代表完全透明,而白色区域(1)代表完全不透明,而灰色区域表示着半透明。
本实验用到以下抠像技术:
1.Luma Keying(亮度抠像)
亮度抠像一般用于画面上有明显亮度差异的镜头抠像,是基于lab中的L通道的抠像技术,对于明暗反差很大的图像我们应用这种抠像技术使背景透明。如明亮天空背景下拍摄的画面,就可以利用抠像将天空去除替换成想要的动态天空素材进行再编辑等等。
以上图为例,在Lab (L亮度, ab色度)通道下的各通道图如下:
可以看到L通道背景和人物的差异值很明显,可以用于区分前景和背景。
2.Chroma Keying(色度抠像)
色度抠像又称色度键,是基于RGB模式的抠像技术,其从原理上最接近最初的蓝绿幕技术,即通过前景和背景颜色差异将背景从画面中抠除并替换。
当然这种抠像方法有一个小问题就是前景如果出现背景色也会被抠除,有可能会出现内部零散的点。这可以通过形态学的膨胀、腐蚀操作进行改善。
3.Difference Keying(差值抠像)
差值抠像比较特殊,其原理是通过寻找两段同机位拍摄的画面的差别并将其保留,而将没有差别画面作为背景去除。其基本思想是,先把前景物体和背景一起拍摄下来,然后保持机位不变,去掉前景物体,单独拍摄背景。这样拍摄下来的两个画面相比较,在理想状态下,背景部分是完全相同的,而前景出现的部分则是不同的,这些不同的部分就是需要保留的通道。
事实上这就是之前做过的实验背景相减:
通过如上两张图片得到如下掩膜:
一般这种抠像方式主要用于无法运用蓝/绿幕抠像的场景。
本实验中使用的是Color Difference Keying,名字相似但思想和上面完全不一样,计算的是RGB中三个通道的差异,根据差异程度来判断前景和背景,可应用于绿幕抠图。
4.3D Keying(三维抠像)
三维抠像原理是将图像的色彩区域规整为三维空间显示模式,将RGB三个通道视为三维空间的三个坐标系,颜色的差异程度用空间距离来衡量。
选择哪一种抠像手段要取决于素材,而且素材对前期的拍摄有一些要求,所以在抠像之前先要对素材进行分析。分析它的亮度范围,分析它的色彩,分析它的遮挡关系,分析要提取的范围以及背景等。通常一种抠像手段是很难达到要求的,这时候就需要多种手段并用,达到最终目的。
二、实验内容
采用蓝(绿)幕抠像的方法,提取测试图像或视频中的前景,并与新背景合成。
测试图像或视频可以从bm.avi中截取,下面是部分视频片段(CSDN放不了本地视频资源😡,放下载还收费!):
三、实验过程
1.整体思路
整个实验的流程如下:
①打开视频文件
②提取视频文件的每一帧,进行抠图操作,得到alpha通道的掩膜mask
③通过掩膜将原视频的帧与背景进行融合
④显示前景和背景融合后的帧
⑤读取下一帧,重复②
代码框架如下:
//背景图
background = imread("room_cut.jpg");
//打开视频文件
VideoCapture capture;
capture.open("source3.mp4");
if (!capture.isOpened())
{
cout << "无法打开视频文件!" << endl;
return -1;
}
//命名窗口
namedWindow("输入视频", WINDOW_AUTOSIZE);
namedWindow("输出视频", WINDOW_AUTOSIZE);
while (capture.read(frame))
{
//对每一帧提取的图像进行抠图操作,得到alpha通道的mask
Keying();
//将背景融合
Mat result = replace_and_blend(mask);
//中途退出
char c = waitKey(1);
if (c == 27)
{
break;
}
//imshow("mask", mask);
imshow("输出视频", result);
imshow("输入视频", frame);
}
waitKey(0);
destroyAllWindows();
return 0;
2.Keying(抠图)方法
2.1 Luma Keying
Luma Keying一般针对亮度L通道进行抠图,用于明暗差异大的图片,但也不仅仅适用于亮度差异大的图片,它的思想可以推广至某一通道有较大差异的情况。
输出我们绿幕的图片的G通道如下:
可以看到,由于我们的视频素材是带有绿幕的,图像背景是绿幕所以G值较大,前景G值较小,这导致了前景和背景在G通道的数值差异较大,因此我们使用Luma Keying的思想对图片的G通道进行操作。
计算掩膜mask的公式如下:
上述公式中,表示像素在G通道的值,
、
表示低阈值和高阈值。 同时公式中的
取值在
,后续写出的所有公式都默认
取值在
,但在OpenCV实现时范围是
。
对于上述公式的直观理解是,如果G通道的值在一个高范围之间,说明是背景,
设置为0;其他情况都设置为1。
产生的结果如下: