查看: 1063|回复: 4

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

[复制链接]
  • TA的每日心情
    擦汗
    2019-7-29 00:08
  • 签到天数: 47 天

    [LV.5]常住居民I

    发表于 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, 下载次数: 3)

    该用户从未签到

    发表于 2020-4-19 12:49 | 显示全部楼层
    厉害啊 颜色空间的表达好复杂啊
  • TA的每日心情
    擦汗
    2019-7-29 00:08
  • 签到天数: 47 天

    [LV.5]常住居民I

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

    传说中的线性表出,都是数学游戏
  • TA的每日心情
    擦汗
    2019-7-29 00:08
  • 签到天数: 47 天

    [LV.5]常住居民I

     楼主| 发表于 2020-4-20 12:58 | 显示全部楼层

    大家共同学习!
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    热门推荐

    【花雕动手做】快餐盒盖,极低成本搭建机器人实验平台
    【花雕动手做】快餐盒盖,
    吃完快餐粥,除了粥的味道不错之外,我对个快餐盒的圆盖子产生了兴趣,能否做个极低成
    关于串口通信协议的激光测距模块问题
    关于串口通信协议的激光测
    采用的是60m相位单点红外激光测距模组,模块与arduino mega采用串口相连接。模块为串
    DIY X-Y 平面激光器
    DIY X-Y 平面激光器
    DIY X-Y 平面激光器 总成本不到50元,性能一点不比市面的差. Arduino UNO x1 舵机 x2
    连杆形式的腿机构十一种:盘点机器人行走背后的机械原理
    连杆形式的腿机构十一种:
    机器人概念已经红红火火好多年了,目前确实有不少公司已经研制出了性能非常优越的机器
    【Arduino】108种传感器模块系列实验(21)--激光头传感器模块
    【Arduino】108种传感器模
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表