乐高颜色传感器的颜色识别算法

背景

乐高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

int color = COLOR_NON;

//首先对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]]*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判断颜色
		switch(H){
			case 0 ... 4:
			case 355 ... 360:
				color = COLOR_RED;
				break;
			case 6 ... 27:
				color = COLOR_ORANGE;
				break;
			case 34 ... 64:
				color = COLOR_YELLOW;
				break;
			case 83 ... 155:
				color = COLOR_GREEN;
				break;
			case 200 ... 244:
				color = COLOR_BLUE;
				break;
			case 245 ... 314:
				color = COLOR_VIOLET;
				break;
			default:
				color = COLOR_NON;
				break;
		}
		return color;
	}
}

总的来说,需要先排除黑色、白色和物体距离过远导致反射值很低的情况,这其实就是代表RGB三个值大小接近的情况,这种情况下不适合用HSV空间判断。如果RGB三值相近且都很大,则对应白色;三值相近但是都很小,则对应反射值太低,被测对象太远;三值相近且不算太小,则对应黑色。
排除以上情况后,就可以计算HSV空间的色调H了,由于H值范围已经固定在0-360度,因此算法判断适应性更强。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值