本帖最后由 tobot 于 2022-4-1 23:16 编辑
我们知道,三原色(红绿蓝)混合能形成其他的颜色,这并不是说物理上其他颜色的光是由三原色的光混合形成的,而是人的眼睛会欺骗自己大脑,尽管每种单色光都有自己独特的光谱,比如黄光(中心波长:570纳米,波长范围:597至577纳米),单色光波长都是介于红色和绿色之间,但通过调配红色光与绿色光的比例混合后发出的光,在人的感官里它就是黄光,实际使用中,可以用RGB作为颜色的度量,准确定位了RGB分量,那么给人感官上的颜色也就固定下来。 Rohm的BH1749NUC通过I2C读取颜色,分别对RGB进行采样,对采样数值合并后可读取并重现当前颜色。从datesheet的文档中,用示意图画出了该器件检测蓝、绿、红、红外的灵敏度。 图一、检测分量 根据数据手册,可以看到分别从I2C中的0x50、0x52、0x54位置分别读取红、绿、蓝三色分量(红外和绿2可以暂时不考虑),读取值为16位(0~65535)。也就是说我们可以通过BH1749NUC直接读取一个物体(光源或反光)的数值,而且理论上这个数值应该比我们通常使用每种原色只有8位的RGB更加精确,但在实际使用的时候,会发现如果用该模块测试LED灯珠,虽然光源固定,但调整距离或角度后,每次读取的数值有较大差别。这其实也很好理解,在距离光源的不同距离或朝向光源的角度不同,虽然同种颜色的光,但进入传感器的“光”数量是不同的,RGB分量中的“光强”带来检测的结果也是不同的,所以单纯将结果转换成RGB可能较为困难。同时,我们很难采集到“纯净”的某个单一分量的数值,采集单一原色的同时,不可避免在其它通道采集到不为0的某个值,可能很小,但不是0;尝试用红色的激光器直接照射在传感器上,也会发现有个位数的蓝、绿采样结果。 图二、RGB颜色模型
除了RGB,我们一般还会使用HSV模型来表示颜色,这个模型就是按色彩、深浅、明暗来描述的。百度百科的原话:“HSV对用户来说是一种直观的颜色模型。我们可以从一种纯色彩开始,即指定色彩角H,并让V=S=1,然后我们可以通过向其中加入黑色和白色来得到我们需要的颜色。增加黑色可以减小V而S不变,同样增加白色可以减小S而V不变。例如,要得到深蓝色,V=0.4 S=1 H=240度。要得到淡蓝色,V=1 S=0.4 H=240度。”
图三、HSV颜色模型 在这个模型中,我们可以简单使用H来度量颜色,从上面可以看到H表示颜色,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°;它们的补色是:黄色为60°,青色为180°,品红为300°。而圆锥内部从顶到底的圆心则是从黑到白的变化。 之前某个项目中,曾经设计一个将声音映射为颜色的小玩意,可以根据输入的音阶,发出不同色光,从高音7到低音1,一共设计了21阶,正好沿着HSV圆锥底旋转一周。 这次,为了配合BH1749NUC器件,做了一些修改,将21阶音简化为常用的8阶光,再将光的颜色再还原成音乐。 使用RosBot Baseboard做主控,配上BH1749NUC和一个无源Buzzer模块,连接如下:
图四、主控与模块 实现了从一个RGB中读取颜色并转换成音乐的功能。 图五、效果展示 其中关键代码如下: int getHSV(unsigned short color[]){ int H; if (color[0]>color[1] and color[0]>color[2]){ unsigned short minv=min(color[1],color[2]); H=(color[1]-color[2])*60/(color[0]-minv); }else if(color[1]>color[0] and color[1]>color[2]){ unsigned short minv=min(color[0],color[2]); H=120+(color[2]-color[0])*60/(color[1]-minv); }else if(color[2]>color[0] and color[2]>color[1]){ unsigned short minv=min(color[1],color[0]); H=240+(color[0]-color[1])*60/(color[2]-minv); } Serial.println(H); return H; }
|