赞
踩
把图像转为灰度图像的像素网格以及 x 和 y 的函数来处理以后,我们还需要学会如何利用这些信息,例如如何用图像信息来分离特定区域。
计算机图形和视频广泛应用了颜色阈值这门技术,比如蓝幕。使用蓝幕时,我们需要识别并替换大片蓝色区域,构建虚拟的背景图就是通过蓝幕进行(比如我们要将下图的蓝色背景换成跑车本该在的跑道上)。
能够理解颜色阈值的基本原理并将代码用于实际的案例是本文的目标,下面将详细介绍如何利用Python实现颜色阈值的选取与蓝幕替换,本节的原理和代码结合的十分紧密,所以就不像以往那样拆成原理+代码两个部分讲解了。
本文数据代码可以在后台回复「蓝幕阈值」获取
在正式开始讲解颜色阈值前,我们先从现实生活场景入手,借以更好的理解蓝幕的概念和颜色阈值的使用。
什么是蓝幕?和常见的电影特效绿幕有什么不同?
下图解释截自百度知道
所以,蓝幕其实就是一种处理图片/视频背景的工具,至于具体该怎么用还得结合颜色阈值。
阈值又叫临界值,是指一个效应能够产生的最低值或最高值。所以颜色阈值要求我们首先得定义要被分离的颜色的上下限,也就是蓝色的上下限,在上下限范围内的颜色都会被识别出来(因为我们将要用这个上下限来选出包含颜色范围的蓝幕区域,然后将该区域删除)
我们希望实现的效果如上图,检测出所有的蓝色区域并把它删掉,只留下跑车的轮廓,转换成灰度图像只是为了让轮廓更明显。
# 定义的颜色下限涉及红、绿和蓝色三者,所以会是一个三维数组
lower_blue = np.array([50, 0, 0])
upper_blue = np.array([150, 255, 255])
# 并不是一开始就能够调出这么完美的两个矩阵数据,会经过一定数量的尝试
这里先插入一段代码展示颜色阈值的python设置。上一章我们提到了彩色图像会被解析为具有宽高和深的三维立方体。深是指颜色通道的数量:大多数彩色图像可以仅通过三种颜色组合来表示,即红绿蓝(red,green,blue;组合起来便是我们经常见到的 rgb),所以在设置颜色阈值的上下限时我们需要给出两个三维数组。
我们的目的是替换掉图片中的蓝幕部分,即挖出我们感兴趣的图像部分(跑车),有两种做法可以达到目的:
1. 我只知道自己不想要的:从图像的四个角开始往里缩小搜索圈,
只要检测到蓝色,我就舍弃,直到“一检测到跑车边缘的那一刻”就停止。
2. 我只知道自己想要的:从跑车本身开始,往四周开始发散与保留,
发散并保留到到“一检测跑车外的蓝色边缘”就停止。
# 定义的颜色下限涉及红、绿和蓝色三者,所以会是一个三维数组
lower_blue = np.array([50, 0, 0])
upper_blue = np.array([150, 255, 255])
# 并不是一开始就能够调出这么完美的两个矩阵数据,
## 会经过一定数量的尝试
代码中颜色阈值上下限的设置这里,我们采用了第二种方法,因为车身有红色,所以第一维的 R 我们设置成了下界 50,上界 150。最终会一检测到跑车外的蓝色边缘就停止。
函数 cv2.inRange(待处理的蓝幕图片, 下限, 上限) 会把设置好的颜色阈值上下限用起来,并返回处理好的图像。
概括来说,掩膜就是用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。
**掩膜会把我们感兴趣的部分分离出来以便进行操作。**定义掩膜时,函数会确认各图像像素的颜色值是否在颜色阈值的范围内。如果在,那掩膜就会把像素显示出来。如果不在,掩膜就会遮住像素。
原理为:两张像素一模一样的图片堆叠在一起,上面那张保留我们感兴趣的部分,下面那张背景图会抠除我们感兴趣的部分。这样一重叠,两张图片的镂空部分和实心部分刚好互补。对应我们本章的实例:
如果将上图(即掩膜)作为上层图片的话,这并不是我们希望呈现的最终结果,虽然蓝幕是没了,汽车轮廓也被识别出来了,但也因此失去了颜色。我们希望实现的效果是,将彩色图片中的汽车抠出来,放到跑道上。这时候就要将刚创建的黑白掩膜与原图对应起来。
具体做法为(三种表达方式,选择好理解的即可):提取原图像与掩膜白色区域重叠的部分(跑车周边/蓝幕),或者说是与掩膜非黑区域重叠的部分(还是跑车周边/蓝幕)。又或者说,我们要选择的那部分图像是掩膜不等于0的区域(因为掩膜黑色区域的像素值大小为0)
因为我们希望跑车回到属于自己的跑道上,即把跑车的彩色掩膜印在公路上,所以公路图片会被放在底层。如果不能保证两张图片的像素一样(通俗理解成长宽不一一对等),就极有可能出现牛头不对马嘴的情况,比如跑车掩膜被印到了天上。
所以我们还需要处理下层图片,把公路图片的像素裁剪到和跑车像素一样。因为公路图片的像素比跑车要大得多,裁剪后势必会损失部分图像,所以在选择裁剪的部分时可以多观察坐标
堆叠上下层图片时,是否直接将彩色掩膜图片与处理后的公路图片堆叠就行?
错误做法:直接堆叠
正确做法:处理下层图片(背景图片)后再堆叠
这涉及后续章节的关于彩色干扰的问题。粗略概括可解释为,任意彩色图片叠加纯黑图片后都不会受到干扰,纯黑图片会被自然覆盖掉。而彩色图片之间的相互堆叠则会互相干扰。
这样一来,解决办法就显而易见了:将底层背景图定位出跑车掩膜的位置范围,并将其颜色设置为全黑(跑车掩膜为0的地方设置成0,因为黑色是全0)。
在这里插入图片描述
然后再一堆叠,大功告成!
总结一下本文的内容:
结合流程的小结如下:
美中不足的是,还是能看出堆叠好的图像的跑车有小部分还是识别得不全面,这是因为使用检测蓝幕这种方法是有前提的:场景光线好且蓝幕的颜色十分连贯。
从原图跑车车窗就可以看出,这张图片在拍摄时是处在阳光下,所以车身的不同部位的光照强度不同。至于该如何完整地检测出处于不同光线下的物体,下一章的颜色空间见~
本文数据代码可以在后台回复「蓝幕阈值」获取
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。