背景
在乐高ev3 本文分析了颜色传感器的硬件设计,以获取颜色RGB本文将分析如何通过简单的计算来了解被测物体的表面颜色。
RGB到HSV的转换
正如我们上面提到的,乐高的颜色传感器实际上是在检测反射光或环境光的强度。区分不同颜色的关键是主动分时发出三种不同颜色的光,然后判断被测表面对三种颜色的光反射强度,从而判断被测表面的颜色。三种颜色是红色、绿色和蓝色。基本原理是反映物体本身的光线。例如,红色物体,反射红色最多,绿色和蓝色大多被吸收。因此,我们获得的三种颜色反射强度值实际上可以被视为物体表面RGB颜色。 所以,如何根据RGB计算和识别物体对应的三个值的具体颜色是更好的方法RGB色彩空间转向HSV色彩空间,参考RGB到HSV转换的详细说明。我们只需要计算H的颜色值,并根据H的大小来判断物体的颜色。 用角度测量色调H,取值范围为0°~360°,逆时针方向计算红色,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°。其计算方法在参考文献中写得很清楚:
代码实现
对于乐高的颜色识别模块,代码如下(请注意,这是根据乐高色传感器的原理推测的算法,而不是官方算法和代码):
#define MIN_THR 100 #define BLACK_THR 500 #define WHITE_THR 1500 #define MAX_DELTA 200 //首先对RGB排序三色值大小 Sort(colorAmp,sorted_index); ///先处理特殊,无被测对象、黑色、白色 //首先判断是否没有被测对象,RGB三个值都小于设定阈值MIN_THR,说明没有被测对象(或者被测对象太远) if(colorAmp[sorted_index[MAX]] <= MIN_THR) {
return COLOR_NON; } //否则 至少三个值中有一个大于MIN_THR else {
/如果最小值小于或等于黑色阈值 if(colorAmp[sorted_index[MIN]]<=BLACK_THR) {
//最大值和最小值差别不大 判断为黑色 if(colorAmp[sorted_index[MAX]]- colorAmp[sorted_index[MIN]] < MAX_DELTA) return COLOR_BLACK; } //否则,最小值大于黑色阈值 最大值不超过最小值的1.2倍 else if((u32)colorAmp[sorted_index[MAX]span class="token punctuation">]*10 < (u32)colorAmp[sorted_index[MIN]] * 12) {
//RGB最小值小于白色阈值 可能是白色物体但是距离太远,还是判断为没有对象
if(colorAmp[sorted_index[MIN]]<=WHITE_THR) {
return COLOR_NON;
}
//RGB最小值大于白色阈值,并且最大值不超过最小值的1.2倍 判断为白色
else {
return COLOR_WHITE;
}
}
//走到这排除了黑色 白色 以及没有被测物/被测物过远,继续判断其它颜色,采用hsv变换
//三个值至少有一个大于黑色阈值,并且至少有一个数小于白色阈值
if(colorAmp[sorted_index[MAX]]> BLACK_THR && colorAmp[sorted_index[MIN]]<= WHITE_THR
&& colorAmp[sorted_index[MAX]] != colorAmp[sorted_index[MIN]]) {
//计算delta
delta = colorAmp[sorted_index[MAX]] - colorAmp[sorted_index[MIN]];
//计算hsv空间色调H
if(sorted_index[MAX] == LED_RED)
H = ((int)colorAmp[LED_GREEN]-(int)colorAmp[LED_BLUE])*60/delta;
else if(sorted_index[MAX] == LED_GREEN)
H = 120 + ((int)colorAmp[LED_BLUE]-(int)colorAmp[LED_RED])*60/delta;
else
H = 240 + ((int)colorAmp[LED_RED]-(int)colorAmp[LED_GREEN])*60/delta;
if(H<0)
H += 360;
//根据色调H判断颜色
if(H<4 || H>355)
return COLOR_RED;
else if(H>5 && H<28)
return COLOR_ORANGE;
else if(H>33 && H<65)
return COLOR_YELLOW;
else if(H>82&&H<156)
return COLOR_GREEN;
else if(H>200 && H<245)
return COLOR_BLUE;
else if(H>245 && H<315)
return COLOR_VIOLET;
}
}
总的来说,需要先排除黑色、白色和物体距离过远导致反射值很低的情况,这其实就是代表RGB三个值大小接近的情况,这种情况下不适合用HSV空间判断。如果RGB三值相近且都很大,则对应白色;三值相近但是都很小,则对应反射值太低,被测对象太远;三值相近且不算太小,则对应黑色。 排除以上情况后,就可以计算HSV空间的色调H了,由于H值范围已经固定在0-360度,因此算法判断适应性更强。