opencv 图像 抠图 算法_摄影领域的OpenCV教程之“蓝幕抠图”

本文介绍了如何使用OpenCV的HSV色彩空间进行蓝幕抠图。通过将RGB转换为HSV,我们可以更准确地选择蓝色区域,即使颜色有所偏差也能有效抠图。文中提供了一个小程序示例,展示如何实现这一过程,并展示了抠图和合成图像的效果,适用于视频实时抠图和背景替换场景。
摘要由CSDN通过智能技术生成

玩opencv时候,肯定会接触色彩空间。最常用的是RGB色彩空间,用0~255表示每个通道。

摄影投效里有个技术,叫做蓝幕,也有绿幕。后期把蓝色区域扣掉,然后换成别的背景。

在上图中,细心的小伙伴会发现,实际这个蓝色并不一定是纯蓝(0,0,255)

有脑洞大的小朋友想到了一个方法,只提取蓝色通道,然后把值接近255的都扣掉。

但是有个问题,这样会扣到高光区域(RGB三个值都很高的区域)

另外,如果这个蓝色偏亮偏暗或偏绿,或者摄像机有偏色,用(0,0,255)这个参数当特征来匹配是很困难的事。

这儿我给大家推荐一个好用的色彩空间,叫HSV色彩空间。

H是个色相参数,用0到360度表示了颜色。

S是个色彩鲜艳度的参数,越大颜色越鲜艳,越小颜色越灰。S有个通俗的名字,叫饱和度。

V是个亮度参数,越小越黑

RGB到HSV色彩空间的转换代码如下:

float rgb2h(int B, int G, int R)

{

float H;

int max = max(max(R, G), B);

int min = min(min(R, G), B);

if (R == max)

H = (G - B)*60.0 / (max - min);

if (G == max)

H = 120+(B - R)*60.0 / (max - min);

if (B == max)

H = 240+(R - G)*60.0 / (max - min);

if (H < 0)H = H + 360;

return H;

}

我们先找一张色彩分布的图来试验一下抠图

蓝色附近的区域就是H在240度附近。下面我们写个小程序把240度正负50度的区域抠掉。

void mytest()

{

Mat frame_t = imread("a3.jpg", CV_LOAD_IMAGE_UNCHANGED);

int WW, HH;//图像宽度和高度 单位:像素

HH = frame_t.rows;WW = frame_t.cols;int row2, col2;//循环时候计数第几行和第几列的

for (row2 = 0; row2 < HH; row2++)

{

for (col2 = 0; col2 < WW; col2++)

{

if (fabsf(rgb2h(frame_t.at(row2, col2)[0], frame_t.at(row2, col2)[1], frame_t.at(row2, col2)[2]) - cut)<5)

{

frame_t.at(row2, col2)[0] = 0;

frame_t.at(row2, col2)[1] = 0;

frame_t.at(row2, col2)[2] = 0;

}

}

}

imshow("hsvcut", frame_t);

}

运行效果如图

在上图中,我们发现这个算法可以准确地扣出蓝色区域,而且即使蓝色亮一点暗一点或是灰一点鲜艳一点,也没有影响。

接下来,我们找两个图片来抠图和合成图像。

首先是蓝幕原图

然后是背景

我们来写一下抠除蓝色部分以后与背景叠加的代码

Mat frame_orig;//采集的原始图像

frame_orig = imread("my2.jpg", CV_LOAD_IMAGE_UNCHANGED);

Mat frame_back;//采集的原始图像

frame_back = imread("my1.jpg", CV_LOAD_IMAGE_UNCHANGED);

imshow("orig", frame_orig);

imshow("back", frame_back);

Mat frame_c;//测试图像

frame_c = frame_orig;

int W, H;//图像宽度和高度 单位:像素

H = frame_orig.rows;

W = frame_orig.cols;

int row, col;//循环时候计数第几行和第几列的

for (row = 0; row < H; row++)

{

for (col = 0; col < W; col++)

{

if (fabsf(rgb2h(frame_orig.at(row, col)[0], frame_orig.at(row, col)[1], frame_orig.at(row, col)[2])-cut)

{

frame_c.at(row, col)[0] = frame_back.at(row, col)[0];

frame_c.at(row, col)[1] = frame_back.at(row, col)[1];

frame_c.at(row, col)[2] = frame_back.at(row, col)[2];

}

}

}

imshow("MyPic", frame_c);

合成以后的图像见下图右下。

接下来,我们再换个图片做一次。为了让图片增加些戏剧效果,我找来了一个热气球的蓝幕原图和一段树枝的背景。

蓝幕原图

背景

最后合成的图像见下图右上。

这种基于OpenCV的蓝幕抠图算法可以自动地对每一帧图像进行处理和合成,特别适合用于视频的实时抠图,也许可以用在自动换背景等应用上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值