今天看到架子上的萝卜头,已经落了很多灰尘。想起萝卜头的攻略还剩几篇迟迟没有写完。前一段时间一直在试验小爱的手机遥控器功能,从今天开始准备陆续把萝卜头的攻略补完,给博客也打扫打扫灰尘。

说起来真是很惭愧,颜色识别在萝卜头制作过程中是花费时间最多的部分。其中还有一段小插曲:

我在淘宝上买的颜色传感器,在NXT上测试时,发现只有用强光照射在魔方表面的时候,传感器才有读数。那时候在网上很难找到相关的资料,不知道是我买了次品,还是设置不当。后来我猜想传感器中心的那个透明小灯泡是光源,就擅自去电子市场买了一个LED小灯,然后把这个500块钱的传感器敲开换上。一通电,嘿,灯居然亮了,然后我就把拆下来的小灯扔到垃圾桶继续测试。结果…..这次传感器彻底废了。接下来是从垃圾桶里翻那个透明的小灯泡,非常悲剧的是那天正好吃了虾和鱼,我把整垃圾桶的虾皮鱼骨摸了两遍,才找到那个透明的小灯泡,把它洗洗干净又换上了。后来才知道,这个灯泡其实是用来读取颜色的,而不是照明的。而我买的那个颜色传感器确实是个次品,必须用灯光照射才能勉强读数。所以你们看到第一版的萝卜头,在悬臂上是带有一个照明灯的。

在此提醒一下朋友们:颜色传感器在普通的光照环境下,应该是有读数的,而且很敏感,读数会不断小幅跳动。如果你买的传感器读数一直是0或者跳动非常大,那么请尽快找奸商退换。另外,在这里感谢一下北京西觅亚公司,他们给我提供了几个测试用的颜色传感器,并且给我换了一个新的。我也因此了解了一些颜色传感器的特性。

好了,进入正题。上一篇介绍了如何在电脑和NXT之间使用蓝牙进行通讯。有了蓝牙,我们就可以把颜色传感器的读数发送给电脑,然后用电脑识别颜色后调用解魔方的算法。

1,从NXT发送颜色数据到电脑

在之前的一篇博客里,我介绍了三个函数:ReadAllSide,ReadOneSide和SendColorToPC。现在蓝牙已经调通,可以改写SendColorToPC函数用来发送数据。其中getRed()和getRawRed()等函数的说明,请参考颜色传感器的API文档

//Send colors to PC

public static void SendColorToPC(int center, int n) throws Exception

{

//get the x,y of n

int y = n % 3;

int x = (n - y) / 3;

//send to PC by bluetooth

byte[] data = new byte[9];

data[0] = (byte)center; //center表示是魔方的某一面

data[1] = (byte)x; //x 表示魔方这一面3*3的色块中,第x行的色块

data[2] = (byte)y; //y 表示魔方这一面3*3的色块中,第y列的色块

data[3] = (byte)color.getRed();

data[4] = (byte)color.getGreen();

data[5] = (byte)color.getBlue();

data[6] = (byte)(color.getRawRed() / 3);

data[7] = (byte)(color.getRawGreen() / 3);

data[8] = (byte)(color.getRawBlue() / 3);

BlueTooth.WriteBytes(data);

}

2,在PC端接受颜色数据

PC程序中的BlueToothDataReceived函数,用来响应接受到蓝牙数据的事件。我们加上下面这段函数:

else if (length == 9)

{

int i = data[0];

int j = data[1];

int k = data[2];

int r = data[3];

int g = data[4];

int b = data[5];

int rawR = data[6];

int rawG = data[7];

int rawB = data[8];

ColorItem newItem = new ColorItem(i, j, k, r, g, b, rawR, rawG, rawB);

colorDistinguish.ColorItems.Add(newItem);

DisplayMessage += newItem.ToString() + "\r\n";

Status = "成功获取数据:" + i + "," + j + "," + k;

}

其中用到了两个类 ColorItem 和 ColorItemDistinguish。这两个类的作用后面再说,总之这里把所有的颜色数据都先保存到一个阵列(Array)里,最后统一识别颜色。

3,解析颜色的方案

细心的朋友可能在API中看到了getColor()函数,我们何必要全部保存颜色后再统一分辨呢,直接读一个分辨一个不是更好?事实证明这个函数基本没什么用,红色和橙色都会解析成红色,而且环境光线变化时影响很大。还有一些朋友建议用HSV颜色模型,这种方案我也试过了,基本上也很难分辨。为什么呢?请看下面一组读数:

Red

[0,1,2]=>RGB=(23,0,0),RawRGB={45,1,8}

[0,2,2]=>RGB=(30,0,0),RawRGB={60,1,5}

[0,2,1]=>RGB=(25,0,0),RawRGB={49,3,12}

[0,2,0]=>RGB=(32,0,0),RawRGB={63,2,6}

[0,1,0]=>RGB=(22,0,0),RawRGB={43,2,11}

[0,0,0]=>RGB=(25,0,0),RawRGB={59,3,3}

[0,0,1]=>RGB=(30,0,0),RawRGB={58,5,17}

[0,0,2]=>RGB=(31,0,0),RawRGB={61,8,17}

[0,1,1]=>RGB=(31,0,0),RawRGB={62,15,22}

Orange

[2,1,2]=>RGB=(28,0,0),RawRGB={55,12,8}

[2,2,1]=>RGB=(30,0,0),RawRGB={57,14,14}

[2,0,1]=>RGB=(32,0,0),RawRGB={62,15,13}

[2,1,0]=>RGB=(32,0,0),RawRGB={63,16,12}

[2,2,2]=>RGB=(42,0,0),RawRGB={83,24,10}

[2,2,0]=>RGB=(41,0,0),RawRGB={82,24,13}

[2,0,0]=>RGB=(41,0,0),RawRGB={80,23,10}

[2,0,2]=>RGB=(39,0,0),RawRGB={76,22,13}

[2,1,1]=>RGB=(41,5,0),RawRGB={81,30,21}

这是在自然光条件下,对红色和橙色的9个色块分别读数的结果。可以看到,它们的Green和Blue分量全部是0,只有红色分量有差别。但是红色的red分量从23~32,橙色的red分量从28~42,它们中间是有重叠的。对于这些读数,HSV完全没用。

有一段时期我几乎已经绝望了,不过终于在最后让我找到了一点区别:红色的RawBlue分量基本上比RawGreen分量稍大,而橙色恰好相反。另外请对比一下[0,0,0]和[2,2,1],它们的RawBlue分量和RawGreen分量是相同的,但是仍然可以找到区别:按公式R+2*RawG-2*RawB计算,橙色的永远比红色大!

也就是说,我们单独取到一组颜色数值时,很难直接知道它是什么颜色,只有对一组数进行排序后,才能区分出不同的颜色。就像刚才这18个数,我们按照R+2*RawG-2*RawB从大到小排序,最终结果的前9个是橙色,后9个就是红色。类似的,我们还可以定义出分辨颜色的判断规则:

1,假设RGB三个值的最小值为Min,按Min从大到小排序,前9个是白色

2,剩下的颜色,按照G分量从大到小排序,前9个是黄色(有意思吧,绿色分量最大的是黄色)

3,剩下的颜色,按照B分量从大到小排序,前9个是蓝色(这个还算靠谱)

4,剩下的颜色,按照R分量从小到大排序,前9个是绿色

5,剩下的颜色,按照R+2*RawG-2*RawB从大到小排序,前9个是橙色

6,剩下的颜色全是红色

当光线从弱到强变化时,这些值基本会成比例的变大,所以这些规则依然有效。

有兴趣的朋友可以查看一组完整的颜色读数,来验证以上这些规则:http://www.diy-robots.com/rubiksolver/readcolors.txt

下一篇继续介绍这种分辨方式的具体代码实现。

python识别魔方色块_解魔方的机器人攻略23 – 识别颜色(上)相关推荐

  1. python识别魔方色块_解魔方机器人教程:识别颜色

    1,从NXT发送颜色数据到电脑 在//Send colors to PC public static void SendColorToPC(int center, int n) throws Exce ...

  2. 魔方机器人需要特制魔方吗_解魔方的机器人攻略18 – 魔方快速算法

    我们的快速魔方算法要隆重登场了,在此缺席感谢一下来自Netherlands的Jaap Scherphuis同学.看前面这个页面的第三名. 魔方表示法 咱们先看一串天书般的字母:UF UR UB UL ...

  3. [Python]不使用kociemba库解魔方

    [Python]不使用kociemba库解魔方 前言 思路 测试效果 部分代码 主程序:Python3.8 关键改动:Java 14.0.1 项目文件 前言 说到魔方,python有个现成的库koci ...

  4. 解魔方算法/Thislethwaite解魔方算法/降群法

    0.前言 主流的魔方解法,从入门的层先法,到进阶的CFOP.桥式乃至盲拧,都是从部分到整体的思路,逐块逐层还原魔方.但是Thislethwaite法不同,Thislethwaite法从整体出发,不断降 ...

  5. 随机森林的特征 是放回抽样么_机器学习超详细实践攻略(10):随机森林算法详解及小白都能看懂的调参指南...

    一.什么是随机森林 前面我们已经介绍了决策树的基本原理和使用.但是决策树有一个很大的缺陷:因为决策树会非常细致地划分样本,如果决策树分得太多细致,会导致其在训练集上出现过拟合,而如果决策树粗略地划分样 ...

  6. 乖离性暗机器人_乖离性百万亚瑟王超级妖 暗机器人攻略详解

    乖离性百万亚瑟王超级妖 暗机器人攻略详解97973-手游网小编为大家分享乖离性百万亚瑟王超级妖 暗机器人攻略详解,详细讲解乖离性百万亚瑟王攻略,希望这篇攻略能帮到大家 本攻略是97973-原创,转载请 ...

  7. 乖离水机器人攻略_乖离性百万亚瑟王超弩风机器人攻略 打法详解

    乖离性百万亚瑟王超弩风机器人攻略,超弩风机器人打法详解,乖离性百万亚瑟王新一期的boss已经全面与广大玩家们见面了,在感受了狗哥这个弱鸡之后是否明天的风机器人能给玩家们带来难度呢?今天让小编我来为大家 ...

  8. Python语言学习之双下划线那些事:python和双下划线使用方法之详细攻略

    Python语言学习之双下划线那些事:python和双下划线使用方法之详细攻略 目录 双下划线介绍 1.关于双下划线的函数或方法或属性 双下划线介绍 1.关于双下划线的函数或方法或属性 __name_ ...

  9. Python语言学习之文件夹那些事:python和文件夹的使用方法之详细攻略

    Python语言学习之文件夹那些事:python和文件夹的使用方法之详细攻略 目录 Python与文件夹那些事 1.创建/删除文件/文件夹 1.创建文件夹

最新文章

  1. linux 失败模式,在Linux中在AP模式下扫描失败(wpa_supplicant)
  2. Part 2 — Making Sense of Smart Contracts
  3. THINKPHP3.2+PHP5.3 配置MEMCACHE
  4. Softmax(假神经网络)与词向量的训练
  5. 小鹏全新中大型SUV谍照曝光,智能驾驶+纯电SUV+睡眠舱?期待值拉满
  6. java 无符号运算_java位运算和无符号运算
  7. nmap 扫描工具 使用方法
  8. MDF /IDF名词解析
  9. 孙鑫-MFC笔记七--文件与注册表
  10. 新建DataTable添加列添加行
  11. 十大排序思维导图(个人理解)
  12. 详细vue脚手架安装教程
  13. 题库APP源码 在线题库源码 题库系统源码
  14. 计算机ROM指什么意思,ROM是什么 刷ROM是什么意思
  15. python禁用路径长度限制有啥影响吗_为什么Windows中存在260个字符的路径长度限制?...
  16. 一款APP从设计稿到切图过程全方位揭秘(IOS版)
  17. python中round函数的精度保留方法---四舍六入五成双
  18. 重启路由器后xshell连接Linux主机出现connect failed问题
  19. 双系统(ubuntu系统与window系统)时间不一致的解决办法
  20. 训练集、验证集和测试集这三个名词的区别

热门文章

  1. 宏碁暗影骑士AN515-55/57/58原厂预装系统oem镜像
  2. Word中怎么批量修改所有表格样式
  3. java des ecb_DES ECB加解密的Java实现
  4. 谷歌浏览器常用快捷键
  5. 《用户至上:用户研究方法与实践(原书第2版)》一2.3 理解产品
  6. [安卓开发] Broadcast 三种广播的使用总结
  7. 计算机配置价格对比,硬件配置、价格对比
  8. ES8新增的常用语法
  9. 秀!如何搭建一个永久运行的个人服务器?
  10. CSS通用样式2——Flex布局