我们已经得到了6×9个RGB值,但这些都代表什么颜色?我们需要的是不同色块对应到6种不同的颜色,因此必须对这54个RGB值进行划分,使他们归到自己的颜色分类中。关于颜色分类其实属于数字图像处理学中的一个重要研究领域,在此仅对比较通用的一种方法进行介绍。 4.1 色彩模型转换色彩模型是描述使用一组值(通常使用3个、4个值或者颜色成分)表示颜色方法的抽象数学模型。例如三原色光模式(RGB) 和印刷四分色模式(CMYK)都是色彩模型。EV3颜色传感器获得的就是RGB模型,可以表示为三维直角坐标颜色系统的一个单位正方体。 在大多数的彩色图形显示设备一般都是使用红、绿、蓝三原色,我们的真实感图形学中的主要的颜色模型也是RGB模型,但是红、绿、蓝颜色模型用起来不太方便,它与直观的颜色概念如色调、饱和度和亮度等没有直接的联系。比如,我们很难从RGB的取值上区分这个颜色属于哪个色域,因此根据不同应用,还有HSV、HSI、CHL、LAB、CMY等其他色彩模型。由于颜色本身并没有发生变化,只是各个色彩模型表示颜色的方法不同,色彩模型之间可以通过固定的公式进行相互转换。 HSV、HSI、LAB都可以很好的将色相以一定规律排列出来。在本项目中,使用HSV模型作为颜色识别的色彩模型。关于HSV模型的详细描述,可以参见http://www.pazhong.net/?p=325 交给OpenCV在程序实现方面,我更建议使用已经投入大量应用的函数库,而不是自己重新写一遍。因为已投入应用的函数库经过了长期的优化,能够保证实现的效率和安全。尽管RGB转HSV的程序实现很简单,只要按照公式直译成程序即可,但我还是使用了OpenCV的cvtColor函数。 在此之前,需要按照OpenCV模块,官方网站给出了比较详细的安装方法。ev3dev基于Debian系统,可以通过apt-get install python-opencv指令进行模块及相关依赖包的安装。 OpenCV为图像处理提供了大量的算法实现函数,在处理魔方色块时,我们可以将6×9个色块理解为一张大小为6×9的图像,每个色块为图像中的一个像素点,然后对这张图像进行RGB到HSV的转换。 对于这个图像与魔方色块的对应表示关系为: - [0,0]表示图像第1行第1列的像素点,对应魔方上为第1个扫描面的第1个扫描色块
- [0,1]表示图像第1行第2列的像素点,对应魔方上为第1个扫描面的第2个扫描色块
- [3,4]表示图像第3行第4列的像素点,对应魔方上为第3个扫描面的第4个扫描色块
OpenCV的程序实现 # 仅为示例,非实际使用程序image_hsv = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2HSV)此时得到的image_hsv为一张大小为6×9的HSV图像,image_hsv[0,0,0]为第1行第1列的H值,image_hsv[0,0,1]为第1行第1列的S值,image_hsv[0,0,2]为第1行第1列的V值。 4.2 色块划分利用HSV色彩空间的性质,通过对所有色块H值的排序,然后再以每9个色块为一组,可以得到每个色块的分组,也就得到了该色块所属的颜色类别。 通过一个简单的例子能帮助更好理解。假设我们有9个色块,一共3种颜色,这9个色块的H值分别如下: 位置 | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | H值 | 22 | 121 | 25 | 186 | 190 | 118 | 24 | 124 | 188 |
接下来我们按这9个色块的H值从小到大排序,排序的同时他们的位置也随着调整: 位置 | [0] | [6] | [2] | [5] | [1] | [7] | [3] | [8] | [4] | H值 | 22 | 24 | 25 | 118 | 121 | 124 | 186 | 188 | 190 |
我们知道一共有3种颜色,按照这个排序,每3个色块归为一组。也就是说位置在[0][6][2]的色块是同一种颜色,[5][1][7]为同一种颜色,[3][8][4]为同一种颜色。 位置排序程序如果理解了以上的划分原理,开始写程序会发现一个问题。与通常的排序不同,这里不是只对位置上的值排序,而是通过位置上值的大小完成对位置的排序。在程序设计过程中,需要额外增加一个变量来记录位置的变换。 - # 按照数组值的大小完成数组位置的排序
- # 输入:l为要排序的数组
- def sort_pos(l):
- # 定义pos数组,与l相同大小,初始化为l的原始位置
- pos = np.arange(len(l))
- for i in range(len(l)-1):
- for j in range(len(l)-i-1):
- # 按照l数组的值的大小进行比对
- if l[j] > l[j+1]:
- # 调整pos的值,即记录l位置的变化
- pos[j], pos[j+1] = pos[j+1], pos[j]
- # 返回排序后位置的变化情况
- return pos
复制代码
这一节确实有一些难理解,先多看看上面表格里排序的例子,再去试着理解程序会更好一些。
|