失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 魔方机器人02 使用opencv-python进行颜色识别及K-Means聚类算法

魔方机器人02 使用opencv-python进行颜色识别及K-Means聚类算法

时间:2020-09-20 11:33:23

相关推荐

魔方机器人02 使用opencv-python进行颜色识别及K-Means聚类算法

文章目录

安装opencv库魔方状态识别识别方案思路识别方案简介实践经验在图像中标定位置聚类算法

安装opencv库

如果你是Windows系统,在anaconda搭建的环境里运行以下命令

pip install opencv-pythonpip install opencv-contrib-python

关于opencv-contrib-python这个包,借用一下知乎里的解释

opencv-python 是只包含了主要模块的包,opencv-contrib-python包含了主要模块以及扩展模块,扩展模块主要是包含了一些带专利的收费算法(如shift特征检测)以及一些在测试的新的算法(稳定后会合并到主要模块)。

当然说的收费并不是要收你的钱,只是如果要商用的话要收费。没错,开源软件是可以收费的!

当然这个工程用不到opencv-contrib-python包手动狗头

如果你是Linux系统,可以执行以下命令:1

sudo rm -rf /*

安装之前建议给pip换成国内源,或者用conda装也行,conda建议也把源换成国内的。阿里源中科大源都不错,清华源有时候很慢。

或者你也可以下载安装包再本地安装。http://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv

安装完pip list里看一下,看看有没有

不放心也可以调用一下试试

安装完成。

关于在《opencv3机器视觉》一书中的安装方法,well,现在已经不需要这么麻烦了

开始写之前,说明一下对opencv和python都是第一次接触,有什么错误与不合适之处望指正。

魔方状态识别

对于视觉算法,方法有很多,但是通用的视觉识别都会耗时较长的时间(几十到几千毫秒不等)。在这里我们想要把速度做到极致,同时有不失准确性和鲁棒性,于是在众多的方法中选择了消耗算例较小的一种。其他的众多方案就不介绍了,在这里只介绍使用了的一种。

识别方案思路

因为魔方和摄像头的位置是相对固定的,所以省略识别取边缘识别色块的一大坨啰啰嗦嗦的算法,直接在图像上标定每个色块的位置,然后进行颜色识别。接触过视觉的童鞋应该都知道,大部分颜色识别都是在HSV坐标系下进行的,OpenCV储存的图像呢是BGR(注意不是RGB)格式的,所以转换成HSV来识别。关于HSV坐标的定义,可以百度或维基。魔方的6个颜色设计的真是很闹心,相邻的红色,黄色和橘色的色相角很相近,所以容易判断出错。这里打算使用K-Means聚类算法来分类之后再判断。最后把识别出的颜色转换成魔方的状态字符串。关于状态字符串,请参见魔方机器人01 kociemba安装和使用。

识别方案简介

首先我们已经标定了54个色块的位置,提取了每个色块的HSV坐标值

第二步我们先判断白色的色块。因为白色的H值是任意的,所以我们不能把白色的H值放进聚类算法中(本身这个分类就没有包含所有的颜色信息),否则聚类会变成一团浆糊。提取白色的方法是使用S(饱和度)值,因为白色的饱和度是最小的。在这里一定要注意,为了算法的鲁棒性,我们绝不设置阈值,而是通过相对值来判断白色,这一点在后面举例完成后判断每类是什么颜色时也会用到。也就是说,我们提取出S值最小的9个色块,并判断为白色。

对于剩下的45个色块,我们就可以使用聚类算法了。我们对颜色的H值进行聚类运算,把剩下的色块分为5类。聚类算法的实现同样可以百度或维基,待我把源码整理好挂到gitee上之后也会把链接附在这里。

聚类运算完成之后,记住我们还要判断结果的正确性!K-Means聚类是对初值敏感的,也就是说不好的初值设定很可能会有不正确的结果。所以这里我们设置一种检验方法,具体如下

是否每类有9个元素是否5个面中心位置的色块分别为5个不同的颜色

如果满足以上两个条件,则认为聚类运算完成;如果不满足,则认为聚类运算错误,重新生成初值并循环计算,直至产出正确结果运算完成。

得到正确的聚类结果之后,下面就需要确定每类的颜色。像前面说的,为了鲁棒性,我们不会去设定阈值,而是通过H值的相对大小。这里又有一个需要注意的地方,就是红色的H值不是连续的。所以我们首先按照没个颜色类的聚类中心到绝对红色绝对距离(也就是到0或180的距离)把红色确定出来。然后再对剩下的四类颜色的聚类中心按大小排序,就可以确定剩下四种颜色。

实践经验

想要让聚类算法表现出较好的效果,数据的质量非常重要,而这一点往往又是很难保证的。举个例子,如果使用多个摄像头来读取颜色信息,那么由于白平衡以及光照条件的原因,每个摄像头拍摄的同一个颜色会是不同的颜色信息;甚至由于感光芯片的质量,同一面上的相近颜色(红色和橙色、黄色和白色)肉眼也分不清。我把这种误差称为拍摄误差。事实上,拍摄误差可以大到从数据上完全无法分辨相近的颜色。所以这里就对拍摄方案提出了较高的要求。

一种思路是使用廉价的不带白平衡的感光芯片,比如一些fpv上使用的摄像头。这样可以解决白平衡带来的问题,但是并不能解决第二种问题。

另一种思路,也是我采用的思路,是设计一种较好的补光方案,让机器处在较好的光照条件下。我设计了一种自适应的补光方案,因为和本篇文章关系不大,就不赘述了。

这个问题自始至终都没有一个非常优雅的解决方案,似乎我使用的每种方案都是需要现场的调校,并不能做到我所预想的全环境适应的高鲁棒性。欢迎各位朋友在评论区交流更优的方案。

在图像中标定位置

这个不是很难,按照状态字符串顺序标定就好了,这里我写了一个python脚本来做这件事。

这里有个坑,cv2.setMouseCallback()函数中得到的x,y坐标与opencv图片格式文件索引的顺序是相反的(不知道为什么要搞这样的操作),所以坐标使用的时候需要反一下,编程的时候需要注意。

import cv2 as cv'''位置顺序是按照kociemba的编号排序的'''name = 'label'cv.namedWindow(name)faceName = ['U','R','F','D','L','B',]faceFile = ['U.jpg','D.jpg','F.jpg','D.jpg','U.jpg','B.jpg',]locationData = []def callback(event, x, y, flags, param):global locationDataglobal imgglobal nif event == cv.EVENT_LBUTTONDOWN:print(str(n) + 'clicked, please click next point')cv.line(img, (x, y), (x, y), (255, 255, 255), 10)locationData.append('[' + str(y) + ', ' + str(x) + ']' + ', ')n += 1cv.setMouseCallback(name, callback)for i in range(6):n = 0img = cv.imread(faceFile[i])print(faceName[i])while n < 9:cv.imshow(name, img)cv.waitKey(50)f = open('locationData.txt', 'w')f.writelines(locationData)f.close()

注意读取图片用的是相对位置,所以要把图片放到工程文件夹下。坐标结果会在工程的根文件夹下生成一个txt文档。你可以参考我这段代码改写,之后我也会把最终整理过的代码开源。

聚类算法

有一篇关于python实现K-Means聚类算法的文章给了我这个python小白莫大的启发。

附上文章地址:python机器学习之k-means聚类算法(1)

相信你一定不会真的执行这行命令的

如果你真的执行了,但愿你的系统是新版本 ↩︎

如果觉得《魔方机器人02 使用opencv-python进行颜色识别及K-Means聚类算法》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。