精通人脸识别10:RGB颜色空间


让我们加载同一个立方体的2个图像。 它将默认以BGR格式加载。 我们可以使用OpenCV函数cvtColor()在不同的颜色空间之间进行转换,如后面所示。

bright = cv::imread('cube1.jpg')

dark = cv::imread('cube8.jpg')

第一张照片是在阳光明媚的室外环境下拍摄的,第二张照片是在正常照明条件下拍摄的。

RGB颜色空间

RGB色彩空间具有以下属性

  • 这是一个加色空间,通过红,绿和蓝色值的线性组合获得颜色。
  • 三个通道通过撞击表面的光量相关联。

让我们把这两幅图像分解成它们的R,G和B分量,并观察它们以获得更多的色彩空间。

如果你看蓝色的通道,可以看到在室内照明条件下,第二张图像中的蓝色和白色的部分看起来相似,但是在第一张图像中有明显的差别。 这种不均匀性使得在这个色彩空间中基于颜色的分割非常困难。 此外,两个图像的值之间存在总体差异。 下面我们总结了与RGB颜色空间相关的固有问题:

  • 显着的感知不均匀性。
  • 色度(颜色相关信息)和亮度(强度相关信息)数据的混合。

LAB色彩空间

Lab色彩空间有三个组件。

1、L - 亮度(强度)。 
2、a-从绿色到品红色的一种颜色成分。 
3、b-颜色分量从蓝色到黄色。

Lab色彩空间与RGB色彩空间大不相同。 在RGB色彩空间中,色彩信息被分成三个通道,但相同的三个通道也编码亮度信息。 另一方面,在Lab色彩空间中,L通道独立于色彩信息,仅对亮度进行编码。 另外两个通道编码颜色。

它具有以下属性。

  • 感知上统一的颜色空间,接近我们如何看待颜色。
  • 独立于设备(捕获或显示)。
  • 在Adobe Photoshop中广泛使用。
  • 通过一个复杂的变换方程与RGB色彩空间相关联。

让我们看看Lab色彩空间中的两个图像分成三个通道。

cv::cvtColor(bright, brightLAB, cv::COLOR_BGR2LAB);

cv::cvtColor(dark, darkLAB, cv::COLOR_BGR2LAB);

  • 从图中可以清楚地看出,照度的变化主要影响L分量。
  • 包含颜色信息的A和B成分没有经历大的变化。
  • 在B分量中,绿色,橙色和红色(它们是A分量的极值)的相应值没有改变,类似地,蓝色和黄色(它们是B分量的极值)的相应值在 一个组件。

YCrCb色彩空间

YCrCb颜色空间是从RGB颜色空间导出的,并具有以下三个组件。

1、Y - 伽马校正后从RGB获得的亮度或亮度(Luma )分量。 
2、Cr = R - Y(的红色成分距离Luma有多远)。 
3、Cb = B - Y(蓝色分量距离Luma的有多远)。

此颜色空间具有以下属性。

  • 将亮度和色度分量分离成不同的通道。
  • 主要用于电视传输的压缩(Cr和Cb组件)。
  • 设备依赖。

下面显示了YCrCb色彩空间中分成两个通道的两幅图像

cv::cvtColor(bright, brightYCB, cv::COLOR_BGR2YCrCb);

cv::cvtColor(dark, darkYCB, cv::COLOR_BGR2YCrCb);

  • 对于照度变化,可以针对强度和颜色分量对LAB进行类似的观察。
  • 与LAB相比,红色和橙色之间的感知差异甚至在户外图像中较小。
  • 所有3个部件中的白色都发生了变化。

HSV色彩空间

HSV色彩空间有以下三个组成部分

1、H - 色调(主波长)。 
2、S - 饱和度(纯度/颜色的阴影)。 
3、V值(强度)。

我们列举一些属性。

  • 最好的事情是,它只使用一个通道来描述颜色(H),使得指定颜色非常直观。
  • 设备依赖。

两幅图像的H,S和V分量如下所示。

cv::cvtColor(bright, brightHSV, cv::COLOR_BGR2HSV);

cv::cvtColor(dark, darkHSV, cv::COLOR_BGR2HSV);

  • 在这两个图像中,H分量非常相似,即使在光照变化下,颜色信息也是完整的。
  • S组件在两幅图像中也非常相似。
  • V分量捕捉到的光线量因此会随着光照的变化而变化。
  • 红色的室外和室内图像的价值之间存在着巨大的差异。 这是因为色调表现为一个圆形,红色是在起始角度。所以,可能需要[300,360]和[0,60]之间的值。

如何使用这些色彩空间进行分割

最简单的方法

现在我们已经对不同的色彩空间有了一些了解,我们先尝试用它们来检测立方体中的绿色。

第1步:获取特定颜色的颜色值

为每个色彩空间查找绿色值的近似范围。 为此,我创建了一个交互式GUI,您可以通过将鼠标悬停在图像上来检查每个像素的所有颜色空间的值,如下所示: 

步骤2:应用阈值进行分割

从图像中提取具有与绿色像素值接近的所有像素。 我们可以为每个色彩空间取+/- 40的范围,并检查结果是怎样的。 我们将使用inRange中的opencv函数查找绿色像素的遮罩,然后使用bitwise_and操作使用遮罩从图像中获取绿色像素。

另外请注意,为了将一个像素转换为另一个色彩空间,我们首先需要将一维数组转换为三维数组。

//C++ code
cv::Vec3b bgrPixel(40, 158, 16);
// Create Mat object from vector since cvtColor accepts a Mat object
Mat3b bgr (bgrPixel);

//Convert pixel values to other color spaces.
Mat3b hsv,ycb,lab;
cvtColor(bgr, ycb, COLOR_BGR2YCrCb);
cvtColor(bgr, hsv, COLOR_BGR2HSV);
cvtColor(bgr, lab, COLOR_BGR2Lab);
//Get back the vector from Mat
Vec3b hsvPixel(hsv.at<Vec3b>(0,0));
Vec3b ycbPixel(ycb.at<Vec3b>(0,0));
Vec3b labPixel(lab.at<Vec3b>(0,0));

int thresh = 40;

cv::Scalar minBGR = cv::Scalar(bgrPixel.val[0] - thresh, bgrPixel.val[1] - thresh, bgrPixel.val[2] - thresh) 
cv::Scalar maxBGR = cv::Scalar(bgrPixel.val[0] + thresh, bgrPixel.val[1] + thresh, bgrPixel.val[2] + thresh)

cv::Mat maskBGR, resultBGR;
cv::inRange(bright, minBGR, maxBGR, maskBGR);
cv::bitwise_and(bright, bright, resultBGR, maskBGR);

cv::Scalar minHSV = cv::Scalar(hsvPixel.val[0] - thresh, hsvPixel.val[1] - thresh, hsvPixel.val[2] - thresh) 
cv::Scalar maxHSV = cv::Scalar(hsvPixel.val[0] + thresh, hsvPixel.val[1] + thresh, hsvPixel.val[2] + thresh)

cv::Mat maskHSV, resultHSV;
cv::inRange(brightHSV, minHSV, maxHSV, maskHSV);
cv::bitwise_and(brightHSV, brightHSV, resultHSV, maskHSV);

cv::Scalar minYCB = cv::Scalar(ycbPixel.val[0] - thresh, ycbPixel.val[1] - thresh, ycbPixel.val[2] - thresh) 
cv::Scalar maxYCB = cv::Scalar(ycbPixel.val[0] + thresh, ycbPixel.val[1] + thresh, ycbPixel.val[2] + thresh)

cv::Mat maskYCB, resultYCB;
cv::inRange(brightYCB, minYCB, maxYCB, maskYCB);
cv::bitwise_and(brightYCB, brightYCB, resultYCB, maskYCB);

cv::Scalar minLAB = cv::Scalar(labPixel.val[0] - thresh, labPixel.val[1] - thresh, labPixel.val[2] - thresh) 
cv::Scalar maxLAB = cv::Scalar(labPixel.val[0] + thresh, labPixel.val[1] + thresh, labPixel.val[2] + thresh)

cv::Mat maskLAB, resultLAB;
cv::inRange(brightLAB, minLAB, maxLAB, maskLAB);
cv::bitwise_and(brightLAB, brightLAB, resultLAB, maskLAB);

cv2::imshow("Result BGR", resultBGR)
cv2::imshow("Result HSV", resultHSV)
cv2::imshow("Result YCB", resultYCB)
cv2::imshow("Output LAB", resultLAB)

所以,RGB和LAB似乎足以检测颜色,我们不需要考虑太多。 让我们看看更多的结果。 

所以,相同的门槛不适用于黑暗的形象。 做相同的实验来检测黄色给出以下结果。 

但为什么结果如此糟糕呢? 这是因为我们猜测了40的门槛。 我做了另一个交互式演示,在这里你可以玩这些值,并试图找到一个适用于所有图像的演示。 看看截图。 但是,那么会出现另一个图像出现的情况,并且不能再次工作。 我们不能盲目地通过试错来取得一些门槛。 我们没有这样做,而是利用色彩空间的力量。

我们需要有一些有条不紊的方法来找到正确的阈值。 

一些数据分析为更好的解决方案

第1步:数据收集

我在变化的照明条件下收集了10个立方体的图像,并分别裁剪每种颜色,以获得6种不同颜色的6个数据集。 你可以看到多少变化的颜色进行视觉。

第2步:计算密度图

检查不同颜色空间中特定颜色的分布,如蓝色或黄色。 密度图或二维直方图给出了一个给定颜色值的变化的想法。 例如,理想情况下,蓝色图像的蓝色通道应始终具有255的值。但实际上,它分布在0到255之间。

我只显示BGR色彩空间的代码。 你需要为所有的颜色空间。

  • 我们将首先加载所有蓝色或黄色的图片。
  • 分离通道,并通过附加每个图像的值为每个通道创建和排列。
  • 使用matplotlib中的直方图绘制二维直方图

可以看出,在相似的照明条件下,所有的地块都非常紧凑。 有一点要注意的是:

  • YCrCb和LAB比其他更紧凑
  • 在HSV中,S方向(颜色纯度)有变化,但H方向变化很小。

当照明变化很大时,我们可以看到:

  • 理想情况下,我们希望使用色彩通道最密集/最密集的色彩空间。
  • RGB的密度图剧烈地爆炸。 这意味着渠道价值的变化是非常高的,固定一个门槛是一个大问题。固定更高的范围将检测与所需颜色(假阳性)相似的颜色,而低范围将不会检测到不同照明下的所需颜色(假阴性)。
  • 在HSV中,由于只有H分量包含有关绝对颜色的信息。因此,与YCrCb(Cr和Cb)和LAB(A和B)中的2个旋钮相比,我可以调整一个旋钮(H)来指定颜色,因此它成为我的第一个色彩空间选择。
  • 比较YCrCb和LAB的图表,在LAB的情况下表现出更高的紧凑性。 所以,下一个最好的选择就是LAB色彩空间。

最终结果

在最后一节中,我将通过从密度图中获取阈值来显示检测蓝色和黄色片段的结果,并以与我们在第二部分中所做的相同的方式将其应用于各个色彩空间。 当我们在HSV,YCrCb和LAB色彩空间工作时,我们不必担心Intensity分量。 我们只需要指定颜色分量的阈值。 图中显示了我用来生成结果的值。

色彩空间的其他有用的应用

  • 通常在灰度图像上进行直方图均衡。 但是,您可以通过将RGB图像转换为YCbCr并仅对Y通道进行直方图均衡来执行彩色图像的均衡。
  • 通过将图像转换为Lab色彩空间,在两幅图像之间进行色彩转换。
  • 智能手机相机应用程序(如Google相机或Instagram)中的许多滤镜都使用这些色彩空间转换来创建那些很酷的效果!

P.S:如果你对解决魔方有兴趣,可以参考这个循序渐进的指南。

精通人脸识别10:RGB颜色空间相关推荐

  1. 从零玩转人脸识别之RGB人脸活体检测

    从零玩转RGB人脸活体检测 前言 作者个人博客: 点击前往 本期教程人脸识别第三方平台为虹软科技,本文章讲解的是人脸识别RGB活体追踪技术,免费的功能很多可以自行搭配,希望在你看完本章课程有所收获. ...

  2. [转]人脸识别中的活体检测

    https://zhuanlan.zhihu.com/p/25401788 早在指纹识别应用中就有针对于活体手指的检测技术,即使机器只对真人活体指纹产生识别反应,对其他一切物质不作识别,用于指纹识别产 ...

  3. 一文为你详解2D与3D人脸识别有什么区别?

    最近业界内刮起了一股"人脸识别安全"的大讨论,小到个人大到超市以及银行,都在使用这个刷脸认证或支付,说它好吧,确实解决了无接触,快速高效等问题,你说它不好吧,也是有原因的,比如最明 ...

  4. 2D与3D人脸识别有什么本质上的区别?

    https://www.zhihu.com/question/324123433/answer/681365180 https://www.zhihu.com/question/324123433/a ...

  5. 2D与3D人脸识别详解

    人脸是人体最重要的生物特征之一,而人脸研究主要集中在人脸识别方面,人脸的表达模型分为2D人脸和3D人脸.2D人脸识别研究的时间相对较长,方法流程也相对成熟,在多个领域都有使用,但由于2D信息存在深度数 ...

  6. 基于Python的视频中的人脸识别系统设计与实现

    目录 一:问题描述 2 二:实现思路 2 2.1 切换点 2 2.1.2 镜头切换点 3 2.1.2 音频切换点. 3 2.2 嘉宾识别 = 人脸识别 & 声纹识别 4 2.2.1 人脸识别 ...

  7. RV1109 人脸识别开发

    RV1109 人脸识别开发 本文档主要介绍了在基于RV1109/RV1126 SOC芯上的人脸识别开发实现的架构设计,开发实现过程,主要用的方式方法!这里主要介绍RV1109上使用SDK里的RKMED ...

  8. 佳能80d有人脸识别吗_3250万像素+10张/秒连拍!佳能90D单反曝光

    中关村在线消息:来自Canon Rumors网站的最新谍报,佳能EOS 90D单反将于下周正式发布,并且新机的外观以及核心参数都已经被曝光了.据悉,这款单反将采用3250万像素的APS-C画幅传感器, ...

  9. 起售价近5500,嘲讽了iPhone X的华为Mate 10却没用上人脸识别

    iPhone X 发布之后不久,华为曾在一则广告中讽刺 iPhone X 的面部识别解锁功能,并写道:"让我们面对现实吧!并不是所有人都适合面部识别.2017.10.16,让我们用全新的 A ...

最新文章

  1. elasticsearch多表关联查询_Mybatis【15】 Mybatis如何实现一对一的情况多表关联查询?...
  2. 在mac上安装 docker
  3. 使用RSClientPrint直接打印本地RDLC报表
  4. [译] Android 上一次编写,随处测试
  5. iOS开发网络篇—网络请求(HTTP协议)小结(转)
  6. __attribute__((always_inline))
  7. 有关凸集的证明例题_第1章引言题解1. 用定义验证下列各集合是凸集: (1) S={(X1 ......
  8. 软件产品质量要求与评价_软件质量模型
  9. JavaScript HTML DOM 1
  10. jQuery知识(转)
  11. WEB标准布局(DIV+CSS)学习笔记(二)--DIV的布局基础
  12. SQL SERVER2000教程-第五章 处理数据 第二节 检索数据
  13. 开源项目:使用CUDA NV12转JPG
  14. 软件工程 教师信息管理系统
  15. 苹果手机语音备忘录在哪_真没想到!苹果手机还自带语音记录,按下这个按钮,语音秒变文字...
  16. 你能编写CMS79F623的EEPROM写入数据20到地址1,并且给出具体代码
  17. matlab 画图基本
  18. 职场人士如何抵御消极心理暗示
  19. 一位ORACLE DBA大牛离职时候的过往总结
  20. 从威客到互联网进化论的五年历程

热门文章

  1. 递归算法(JS实现代码)
  2. 我国最高山峰是珠穆朗玛峰:8848m,我现在有一张足够大的纸张,厚度为:0.01m。请问,我折叠多少次,就可 以保证厚度不低于珠穆朗玛峰的高度?
  3. python语言中有哪些函数_Python语言中的函数
  4. vba文字型的值转换成数值类型
  5. 股市基础知识、内盘和外盘与股票走势
  6. 2020华为云Java笔试题
  7. Anaconda python3.6版本安装
  8. Matlab2020a安装
  9. 从新手到熟练,怎么学好Zbrush?
  10. python中合法的赋值语句y=y+1_关于Python赋值语句,以下选项中不合法的是 _________ 。_学小易找答案...