解魔方机器人[四]-建立模型(上)

我们已经得到了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模型的详细描述,可以参见这里

交给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

这一节确实有一些难理解,先多看看上面表格里排序的例子,再去试着理解程序会更好一些。

发表评论

电子邮件地址不会被公开。 必填项已用*标注