魔方机器人视觉 您所在的位置:网站首页 机器人识别不了的字 魔方机器人视觉

魔方机器人视觉

2024-07-17 00:50| 来源: 网络整理| 查看: 265

    大家好,我是松鼠,好久不见啦,今天跟大家分享一下魔方机器人的视觉部分——opencv颜色识别。

        先给自己叠个甲,因为这些知识都是自学的,所以本文只算是抛砖引玉,做的不够好的地方可以一起交流~

Vol.1

什么是魔方机器人?

    相信大家都见过魔方吧?大家可以把魔方打乱,然后再把它扭回六个面。而魔方机器人就是可以把打乱的魔方进行复原的机器人。

Vol.2

什么是视觉?

    机器视觉本质上是让机器人能感受到世界的信息,就像人用眼睛去看东西,机器也需要用摄像头去看东西,然后把信息转化为机器人需要做出的应答。

    魔方机器人的视觉就是通过对颜色的识别,让机器人按照算法对魔方实现控制,使魔方在最短的步数之内复原。

♬..~ ♫. ♪..

    话不多说,我们进入正题,我用的是opencv来识别颜色,接下来,我一定让有着一定基础的你有所收获!

    首先我们举个例子,这是我从网上找到的一张魔方机器人摄像头拍摄到的图片。

    很明显,这个视角看魔方很不直观,对于笨笨的机器人来说,这样的图片需要做一些处理才能让它识别。

    我们可以通过透视变换来处理图像(简而言之就是把图片看魔方的视角变为正视):

# 透视变换 width,height = 300,300 #设定图片大小 pts1 = np.float32([[25,68],[203,19],[32,309],[186,400]]) #划分第一张图的四个点 pts2 = np.float32([[210,20],[370,72],[196,400],[363,318]]) #划分第二张图的四个点 pts3 = np.float32([[0,0],[width,0],[0,height],[width,height]]) #转化为第一张图片 pts4 = np.float32([[0,0],[width,0],[0,height],[width,height]]) #转化为第二张图片 matrix1 = cv2.getPerspectiveTransform(pts1,pts3) imgOutput1 = cv2.warpPerspective(img,matrix1,(width,height)) #第一张图透视变换 matrix2 = cv2.getPerspectiveTransform(pts2,pts4) imgOutput2 = cv2.warpPerspective(img,matrix2,(width,height)) #第二张图透视变换

    透视变化以后:

    OK,现在我们得到了两张图片:

    那么现在,我这里有两个方案去识别颜色:

        1 通过边缘检测来识别魔方的格子(通过检测边缘,找出四边形即为魔方格子,检测格子颜色)

        2 通过分割的手段来识别(把一张图片分割成九个部分,识别每个部分的颜色占比)

♬..♩~ ♫. ♪..

    通过实践发现,因为图片太模糊了,边缘检测的方法只能检测出少数几个格子。

    很明显,效果不是很好,所以我在下面主要介绍分割的方法。

pic1 = imgOutput1[0:100,0:100] pic2 = imgOutput1[0:100,100:200] pic3 = imgOutput1[0:100,200:300] ... #以此类推

    因为我们已经设置了图片为(300,300),我们可以直接通过循环的方式分割9个格子:

for i in range(3):    for j in range(3):        y_start = i*width//3        y_end = (i+1)*width//3        x_start = j * width // 3        x_end = (j + 1) * width // 3        pic = imgOutput1[y_start:y_end,x_start:x_end]

    这样会方便很多~

    然后格子就会单独成一张图片啦!

    效果如下:

(这是我通过cv2.imwrite保存得来的,有兴趣的朋友自己试试)

♬..♩~ ♫. ♪..

    看到这里,你已经离识别成功不远啦~

    接下来,我们的流程是:

    1、先找出魔方各个颜色的HSV范围(这一点是基础)

    2、把图片转为HSV格式

    3、利用cv2.inRange函数设阈值,去除背景部分

    4、利用cv2.countNonZero函数计算阈值内的比例,即颜色比例,超过某个值则判断为某个颜色

    5、逻辑判断,判断颜色

    我认为最让人头疼的就是问题就是:某个颜色的HSV值范围如何确定?

    我这里是通过鼠标点击图片的事件去获取该点的HSV值,然后制定大概的范围作为某种颜色的HSV识别范围。

    主要代码如下:

def getpos(event,x,y,flags,param):    if event==cv2.EVENT_LBUTTONDOWN: #定义一个鼠标左键按下去的事件        print(HSV[y,x]) cv2.setMouseCallback("imageHSV",getpos)#返回HSV值

​​​​   话不多说上代码:

for i in range(3):    for j in range(3):        y_start = i*width//3        y_end = (i+1)*width//3        x_start = j * width // 3        x_end = (j + 1) * width // 3        pic = imgOutput1[y_start:y_end,x_start:x_end]        hsv = cv2.cvtColor(pic,cv2.COLOR_BGR2HSV)        mask_red = cv2.inRange(hsv,red_min,red_max)        red_bili = cv2.countNonZero(mask_red)/(pic.size/3)        mask_yellow = cv2.inRange(hsv, yellow_min, yellow_max)        yellow_bili = cv2.countNonZero(mask_yellow) / (pic.size / 3)        mask_blue = cv2.inRange(hsv, blue_min, blue_max)        blue_bili = cv2.countNonZero(mask_blue) / (pic.size / 3)        mask_white = cv2.inRange(hsv, white_min, white_max)        white_bili = cv2.countNonZero(mask_white) / (pic.size / 3)        mask_orange = cv2.inRange(hsv, orange_min, orange_max)        orange_bili = cv2.countNonZero(mask_orange) / (pic.size / 3)        mask_green = cv2.inRange(hsv, green_min, green_max)        green_bili = cv2.countNonZero(mask_green) / (pic.size / 3)        if red_bili >= 0.4:            print("第一张图第"+str(3*i+j+1)+"个格子:红")        if yellow_bili >= 0.4:            print("第一张图第"+str(3*i+j+1)+"个格子:黄")        if blue_bili >= 0.4:            print("第一张图第"+str(3*i+j+1)+"个格子:蓝")        if white_bili >= 0.4:            print("第一张图第"+str(3*i+j+1)+"个格子:白")        if orange_bili >= 0.3:            print("第一张图第"+str(3*i+j+1)+"个格子:橙")        if green_bili >= 0.4:            print("第一张图第" + str(3 * i + j + 1) + "个格子:绿")

    效果如下:

总代码:

import cv2 import numpy as np img = cv2.imread('./cube.png') width,height = 300,300 #设定图片大小 yellow_min = np.array([30,40,150]) yellow_max = np.array([60,80,190]) red_min = np.array([3,240,90]) red_max = np.array([15,255,120]) blue_min = np.array([95,220,90]) blue_max = np.array([115,255,160]) white_min = np.array([110,9,160]) white_max = np.array([125,45,190]) orange_min = np.array([6,205,235]) orange_max = np.array([10,225,255]) green_min = np.array([80,240,100]) green_max = np.array([85,255,120]) pts1 = np.float32([[25,68],[203,19],[32,309],[186,400]]) #划分第一张图的四个点 pts2 = np.float32([[210,20],[370,72],[196,400],[363,318]]) #划分第二张图的四个点 pts3 = np.float32([[0,0],[width,0],[0,height],[width,height]]) #转化为第一张图片 pts4 = np.float32([[0,0],[width,0],[0,height],[width,height]]) #转化为第二张图片 # 透视变换 matrix1 = cv2.getPerspectiveTransform(pts1,pts3) imgOutput1 = cv2.warpPerspective(img,matrix1,(width,height)) #第一张图透视变换 matrix2 = cv2.getPerspectiveTransform(pts2,pts4) imgOutput2 = cv2.warpPerspective(img,matrix2,(width,height)) #第二张图透视变换 # cv2.imshow("原图",img) cv2.imshow("Output1",imgOutput1) cv2.imshow("Output2",imgOutput2) cv2.imwrite("./photos/Output1.png",imgOutput1) cv2.imwrite("./photos/Output2.png",imgOutput2) for i in range(3):    for j in range(3):        y_start = i*width//3        y_end = (i+1)*width//3        x_start = j * width // 3        x_end = (j + 1) * width // 3        pic = imgOutput1[y_start:y_end,x_start:x_end]        hsv = cv2.cvtColor(pic,cv2.COLOR_BGR2HSV)        mask_red = cv2.inRange(hsv,red_min,red_max)        red_bili = cv2.countNonZero(mask_red)/(pic.size/3)        mask_yellow = cv2.inRange(hsv, yellow_min, yellow_max)        yellow_bili = cv2.countNonZero(mask_yellow) / (pic.size / 3)        mask_blue = cv2.inRange(hsv, blue_min, blue_max)        blue_bili = cv2.countNonZero(mask_blue) / (pic.size / 3)        mask_white = cv2.inRange(hsv, white_min, white_max)        white_bili = cv2.countNonZero(mask_white) / (pic.size / 3)        mask_orange = cv2.inRange(hsv, orange_min, orange_max)        orange_bili = cv2.countNonZero(mask_orange) / (pic.size / 3)        mask_green = cv2.inRange(hsv, green_min, green_max)        green_bili = cv2.countNonZero(mask_green) / (pic.size / 3)        if red_bili >= 0.4:            print("第一张图第"+str(3*i+j+1)+"个格子:红")        if yellow_bili >= 0.4:            print("第一张图第"+str(3*i+j+1)+"个格子:黄")        if blue_bili >= 0.4:            print("第一张图第"+str(3*i+j+1)+"个格子:蓝")        if white_bili >= 0.4:            print("第一张图第"+str(3*i+j+1)+"个格子:白")        if orange_bili >= 0.3:            print("第一张图第"+str(3*i+j+1)+"个格子:橙")        if green_bili >= 0.4:            print("第一张图第" + str(3 * i + j + 1) + "个格子:绿") for i in range(3):    for j in range(3):        y_start = i*width//3        y_end = (i+1)*width//3        x_start = j * width // 3        x_end = (j + 1) * width // 3        pic = imgOutput2[y_start:y_end,x_start:x_end]        hsv = cv2.cvtColor(pic,cv2.COLOR_BGR2HSV)        mask_red = cv2.inRange(hsv,red_min,red_max)        red_bili = cv2.countNonZero(mask_red)/(pic.size/3)        mask_yellow = cv2.inRange(hsv, yellow_min, yellow_max)        yellow_bili = cv2.countNonZero(mask_yellow) / (pic.size / 3)        mask_blue = cv2.inRange(hsv, blue_min, blue_max)        blue_bili = cv2.countNonZero(mask_blue) / (pic.size / 3)        mask_white = cv2.inRange(hsv, white_min, white_max)        white_bili = cv2.countNonZero(mask_white) / (pic.size / 3)        mask_orange = cv2.inRange(hsv, orange_min, orange_max)        orange_bili = cv2.countNonZero(mask_orange) / (pic.size / 3)        mask_green = cv2.inRange(hsv, green_min, green_max)        green_bili = cv2.countNonZero(mask_green) / (pic.size / 3)        if red_bili >= 0.4:            print("第二张图第"+str(3*i+j+1)+"个格子:红")        if yellow_bili >= 0.4:            print("第二张图第"+str(3*i+j+1)+"个格子:黄")        if blue_bili >= 0.4:            print("第二张图第"+str(3*i+j+1)+"个格子:蓝")        if white_bili >= 0.4:            print("第二张图第"+str(3*i+j+1)+"个格子:白")        if orange_bili >= 0.3:            print("第二张图第"+str(3*i+j+1)+"个格子:橙")        if green_bili >= 0.4:            print("第二张图第" + str(3 * i + j + 1) + "个格子:绿") cv2.waitKey(0) cv2.destroyAllWindows()

最终效果:

开源!opencv魔方机器人视觉教程

    每一个格子都能准确识别出来,我们的视觉部分就差不多完成了,剩下的就是电控+机械部分啦~

♬..♩~ ♫. ♪..

    因为篇幅太长了,很多细节我没有细说,有空我会单独把透视变化和HSV阈值的确定和大家分享的,还有需要源文件的朋友可以在公众号【松鼠小铺子】回复“颜色识别”就可以获取啦~

来咯来咯~

有帮助的话点个赞吧~



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有