【测评TCS3472】发现M5Stack官方文档错误-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2655|回复: 4

【测评TCS3472】发现M5Stack官方文档错误

[复制链接]
发表于 2020-4-18 03:18 | 显示全部楼层 |阅读模式
本帖最后由 t3486784401 于 2020-4-18 03:21 编辑

首先感谢 M5Stack 团队这次给试用 TCS3472 颜色识别模块!
在接下来的日子中我会逐步发表测评帖子,记录项目“色控电子琴”的开发历程。

本帖是第 1 篇测评,内容为发现了 M5Stack 官方文档的一处错误。

--------------------------------------------------------------------

【背景】
收到 TCS3472 以后,被 M5Stack 官方做事的细致程度震惊到了,完全是产品级的模块。
运行 Adafruit 的标准库以后,获得了 R/G/B 原始的数据,顺手换算了一下 CIE-1931 色度。

结果一换算不打紧,直接出现了负数坐标,完全跟传说的马蹄区域不搭边。

下图是申请 TCS3472 过程的介绍帖,在 M5Stack 官网的文档中也提及了这个换算公式。
官方文档地址:https://docs.m5stack.com/#/zh_CN/unit/color

IMG1-BUG.png

按照换算公式,知道 R/G/B 以后可以算得 X/Y,并对应到色度图坐标中。
然而实际按照介绍的系数,会算出负数 X/Y,完全摸不着头脑。
典型例子:(r,g,b)= (82,41,56);计算得 (xc,yc)= (-0.68,-1.13)


【分析】
我第一反应是有计算溢出了,但是查了代码都没有任何进展。
甚至在 Adafruit 的 TCS3472 库中,都找到了相同系数的计算代码(但作者写明了 Y 是亮度):

IMG2-AdaFruit.png

然而这并不能打消疑虑,索性去查了 CIE 的各种颜色空间。
查阅资料,发现 CIE1931 包括若干个颜色空间(注意大小写有区别):

CIE-RGB:常见的R/G/B分量,TCS3472输出可认为属于该空间;
CIE-XYZ:即 CIE-1931,马蹄色度图位于该空间 XOY 平面;
CIE-xyY:前两维度 xy 同 CIE-XYZ,第三维度 Y 为亮度,算法系数出现在了:
①Adafruit 的代码中,②M5Stack 官方文档的色度图 y 坐标计算中

显然 M5Stack 误将 CIE-xyY 的 Y(亮度)算法当成了 CIE-XYZ 的纵坐标 Y,
导致 RGB 换算后超出马蹄图坐标。


【验证】
为了彻底搞清楚 M5Stack 官方文档上给的换算矩阵到底什么样,将其算法计为 Run1(附件有M代码);
对照网上下载了 CIE-XYZ 颜色空间的换算代码(下图),该算法计为 Run2(附件有M代码),
IMG3-RGBvsXYZ.png

分别使用 MATLAB 将 R/G/B= 0:20 这样 21*21*21 细分的 CIE-RGB 颜色空间映射成 x,y 坐标,

Run1(Adafruit源码, M5Stack文档):
IMG4A-Run1.png

Run2(下载的 RGB 转 XYZ 矩阵):
IMG4B-Run2.png

显然 Run2 矩阵的结果都落在了马蹄图的区域内,这才是正确的 CIE-RGB 转 CIE-XYZ 矩阵。
附上另一张与马蹄图叠加的结果,虽然我这个 21*21*21 的分辨率不够细腻,但足以说明问题。

IMG5-RGB2XYZ_Compare.png

这里附上运行的 M代码(欢迎指点),以及若干常见换算矩阵:

  1. %% Run1.m %%
  2. clear
  3. idx= 0;
  4. for r= 0:20
  5. for g= 0:20
  6. for b= 0:20
  7.   if(r+g+b>0)
  8.     X = (-0.14282 * r) + (1.54924 * g) + (-0.95641 * b);
  9.     Y = (-0.32466 * r) + (1.57837 * g) + (-0.73191 * b);
  10.     Z = (-0.68202 * r) + (0.77073 * g) + (0.56332 * b);
  11.     idx= idx+1;
  12.     xc(idx) = (X) / (X + Y + Z);
  13.     yc(idx) = (Y) / (X + Y + Z);
  14.   end
  15. end
  16. end
  17. end
  18. plot(xc,yc, '.');
  19. axis equal
  20. axis([0 1 0 1]);
复制代码

  1. %% Run2.m %%
  2. clear
  3. idx= 0;
  4. for r= 0:20
  5. for g= 0:20
  6. for b= 0:20
  7. if(r+g+b>0)
  8.    X = (2.7688 * r) + (1.7517 * g) + (1.1301 * b);
  9.    Y = (1.0000 * r) + (4.5906 * g) + (0.0601 * b);
  10.    Z = (0 * r) + (0.0565 * g) + (5.5942 * b);
  11.    idx= idx+1;
  12.    xc(idx) = (X) / (X + Y + Z);
  13.    yc(idx) = (Y) / (X + Y + Z);
  14. end
  15. end
  16. end
  17. end
  18. plot(xc,yc, '.');
  19. axis equal
  20. axis([0 1 0 1]);
复制代码


IMG6-Others.png

换算矩阵里的 CIE RGB 行就是和 Run2 一样效果,只是每个元素都等比例缩放了。
如果使用归一化坐标将和 Run2 结果一致。


【结论】
M5Stack 团队给大家科普了色度图的概念,这点的确不错。
但很不幸贴错了公式,导致 x,y 根本无法计算进马蹄区域。

正确的 RGB 转 XY 公式应该为(Run2算法,CIE-XYZ):

  1. X = (2.7688 * r) + (1.7517 * g) + (1.1301 * b);
  2. Y = (1.0000 * r) + (4.5906 * g) + (0.0601 * b);
  3. Z = (0 * r) + (0.0565 * g) + (5.5942 * b);
  4. xc = (X) / (X + Y + Z);
  5. yc = (Y) / (X + Y + Z);
复制代码


或者按照上述表格中,选择一种合适的矩阵 M 作为 RGB 左乘因子:XYZ=[M] RGB

另外附上一片介绍颜色空间的文档: 2010--kerr--cie_xyz.pdf (237.04 KB, 下载次数: 8)
这篇文档就提及了颜色空间的选择不是惟一的(即M矩阵不唯一),
同时也提到了 Y 作为亮度出现在第二个维度的情况,但显然并不适用于马蹄图。

--------------------------------------------------------------------

以上,发现了 M5Stack 官方文档中的一点失误,以测评的形式记录之。

祝大家 DIY 愉快,万事如意!
 楼主| 发表于 2020-4-20 12:58 | 显示全部楼层

大家共同学习!
发表于 2020-4-19 12:49 | 显示全部楼层
厉害啊 颜色空间的表达好复杂啊
 楼主| 发表于 2020-4-20 12:57 | 显示全部楼层
auzn 发表于 2020-4-19 12:49
厉害啊 颜色空间的表达好复杂啊

传说中的线性表出,都是数学游戏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-28 09:57 , Processed in 0.087993 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表