魔方机器人中的视觉处理
魔方机器人的图像识别
魔方机器人还原流程
首先利用opencv对魔方的六个面进行颜色提取,获得六个面的色块分布,将六个面的环境提取到一个矩阵中。获得还原步骤,这里给出star数较高的一个还原库,基本能实现20步之内的还原。
https://github.com/hkociemba/RubiksCube-TwophaseSolver
本文的演示demo放在了GitHub上,可以自行运行一下,需要环境配置在readme中
添加链接描述
魔方机器人的图像识别
这里对一个较为理想的魔方一面图案进行演示,排除掉光照干扰与矩阵拼接等步骤。
首先对采集的图案进行形态学处理,获得魔方的每个色块的位置与色块大小等参数,然后提取色块中的颜色信息,获得魔方的颜色矩阵。
图案的形态学处理
形态学处理基本流程就是进行图像二值化,二值化之后寻找图案中的包含的多边形,在对包含多边形中的四边形进行判断,首先判断是否是一个正方形,然后判断正方形的面积是否符合魔方色块的大小。
读取魔方图片进行二值化处理
#首先加载图片,进行二值化处理
img = cv2.imread("cube.png") #加载魔方图案
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #转化为灰度图案
ret, img_binary = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY) #图片的二值化
寻找所有的封闭多边形
#寻找所有封闭多边形
contours, hierarchy = cv2.findContours(img_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #其中contours就是所有的封闭多边形列表
寻找的结果如图,其中绿色的线条就是封边多边形的边
进行魔方的矩形匹配
final_contours = [] #建立一个空列表存放匹配成功的色块,如果寻找到九个色块则认为匹配成功
for contour in contours:
#进行多边形拟合
perimeter = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.1 * perimeter, True)
#计算边的数量为4的多边形
if len (approx) == 4:
area = cv2.contourArea(contour)#获取多边形面积
(x, y, w, h) = cv2.boundingRect(approx)#获取拟合多边形的长款
# Find aspect ratio of boundary rectangle around the countours.
ratio = w / float(h)#计算长宽比
# Check if contour is close to a square.
if ratio >= 0.8 and ratio <= 1.2 and area / (w * h) > 0.9 and ((w * h)/(img.shape[0]*img.shape[1]))<0.1: #长宽比接近1并对大小进行限制
final_contours.append([[x, y], [x, y+h] , [x+w, y+h], [x+w, y]])
if len(final_contours) >= 9: #判断色块的数量
print("get it!")
寻找到色块如下图
读取色块的颜色
这里对读取进行简化,代码中是直接读取色块中心点的位置,在实际中为了程序的鲁棒性可能要求所有色块的均值。并且这里没有对顺序进行处理,仅仅是演示读取的方法。
读取色块的rgb值
首先设立一个黄色的rgb范围,因为演示中的图片颜色不是正黄,所以rgb值设置的比较宽泛
#比较宽泛的黄色的rgb范围是(200,200,0)到(255,255,0)
y_low = (200,200,0)
y_high = (255,255,0)
然后读取色块中心点的rgb值,注意我们设置的顺序是r-g-b,但是cv直接索引的数据是b-g-r,需要注意一下这个顺序。
import numpy as np
cube_color_martix = np.zeros(9) #建立一个魔方单面颜色矩阵
for i in range(len(final_contours)):
(b, g, r) = img[int((final_contours[i][0][0]+final_contours[i][2][0])/2), int((final_contours[i][0][1]+final_contours[i][2][1])/2)] #读取每个色块中心点的颜色参数
if (r, g, b)>y_low and (b, g, r)<y_high: #判断是否是黄色范围
cube_color_martix[i] = 1
cube_color_martix = cube_color_martix.reshape(3, 3)
参考链接
https://blog.csdn.net/weixin_42488182/article/details/103451877
https://github.com/kkoomen/qbr