【问题标题】:Python OpenCV: Rubik's cube solver color extractionPython OpenCV:魔方解算器颜色提取
【发布时间】:2014-09-15 00:20:45
【问题描述】:

说明:

我正在使用 Python 和 OpenCV 解决魔方问题。为此,我试图提取立方体的所有颜色(单个立方体块),然后应用适当的算法(我设计的,没有问题)。

问题:

假设如果我提取了立方体的所有颜色,我如何定位提取的立方体的位置?我怎么知道它是在上中下层还是角落中边缘?

我做了什么:

这里我刚刚提取了黄色。

颜色提取后:

原图

守则

import numpy as np
import cv2
from cv2 import *

im = cv2.imread('v123.bmp')
im = cv2.bilateralFilter(im,9,75,75)
im = cv2.fastNlMeansDenoisingColored(im,None,10,10,7,21)
hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)   # HSV image


COLOR_MIN = np.array([20, 100, 100],np.uint8)       # HSV color code lower and upper bounds
COLOR_MAX = np.array([30, 255, 255],np.uint8)       # color yellow 

frame_threshed = cv2.inRange(hsv_img, COLOR_MIN, COLOR_MAX)     # Thresholding image
imgray = frame_threshed
ret,thresh = cv2.threshold(frame_threshed,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print type(contours)
for cnt in contours:
    x,y,w,h = cv2.boundingRect(cnt)
    print x,
    print y
    cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("Show",im)
cv2.imwrite("extracted.jpg", im)
cv2.waitKey()
cv2.destroyAllWindows()

请就如何定位小方块的位置提出一些建议。这里发现了 4 个黄色立方体:右上角、中心、右边缘、左下角。我如何识别这些位置,例如:通过为每个位置分配数字(这里:3、4、5、7)

感谢任何帮助/想法 :) 谢谢。

P.S.:OpenCV 新手 :)

【问题讨论】:

  • 哦,对不起!忘记添加代码了。现在我已经编辑了问题
  • 您可以检测其余颜色,并且每个正方形都有一个轮廓。您可以做的是遍历每个轮廓并找到总体最大和最小 (x,y) 点。这会产生一个包含 所有 方格的最小边界框。一旦你这样做了,你就会知道在最小边界框中包含一个 3 x 3 的正方形网格。然后,您可以将此边界框细分为相等的 3 x 3 箱。计算每个轮廓的质心,并检查它属于哪个 bin。

标签: python image opencv image-processing computer-vision


【解决方案1】:

这是一个简单的方法:

  • 将图像转换为 HSV 格式
  • 使用颜色阈值检测带有cv2.inRange() 的正方形
  • 执行morphological operations 并在蒙版上绘制正方形
  • Find contours 在掩码上并从上到下或从下到上排序
  • 取三个正方形的每一行,从左到右或从右到左排序

转换为 HSV 格式后,我们使用cv2.inRange() 执行颜色阈值检测以检测正方形。我们将检测到的方块绘制到掩码上

从这里我们找到面具上的轮廓,并利用imutils.contours.sort_contours()从上到下或从下到上对轮廓进行排序。接下来,我们取每行 3 个正方形,并从左到右或从右到左对这一行进行排序。这是排序的可视化(从上到下,左)或(从下到上,右)

现在我们已经对轮廓进行了排序,我们只需将矩形绘制到我们的图像上。这是结果

从左到右和从上到下(左)、从右到左和从上到下

从左到右和从下到上(左),从右到左和从下到上

import cv2
import numpy as np
from imutils import contours

image = cv2.imread('1.png')
original = image.copy()
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = np.zeros(image.shape, dtype=np.uint8)

colors = {
    'gray': ([76, 0, 41], [179, 255, 70]),        # Gray
    'blue': ([69, 120, 100], [179, 255, 255]),    # Blue
    'yellow': ([21, 110, 117], [45, 255, 255]),   # Yellow
    'orange': ([0, 110, 125], [17, 255, 255])     # Orange
    }

# Color threshold to find the squares
open_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
close_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
for color, (lower, upper) in colors.items():
    lower = np.array(lower, dtype=np.uint8)
    upper = np.array(upper, dtype=np.uint8)
    color_mask = cv2.inRange(image, lower, upper)
    color_mask = cv2.morphologyEx(color_mask, cv2.MORPH_OPEN, open_kernel, iterations=1)
    color_mask = cv2.morphologyEx(color_mask, cv2.MORPH_CLOSE, close_kernel, iterations=5)

    color_mask = cv2.merge([color_mask, color_mask, color_mask])
    mask = cv2.bitwise_or(mask, color_mask)

gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
cnts = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
# Sort all contours from top-to-bottom or bottom-to-top
(cnts, _) = contours.sort_contours(cnts, method="top-to-bottom")

# Take each row of 3 and sort from left-to-right or right-to-left
cube_rows = []
row = []
for (i, c) in enumerate(cnts, 1):
    row.append(c)
    if i % 3 == 0:  
        (cnts, _) = contours.sort_contours(row, method="left-to-right")
        cube_rows.append(cnts)
        row = []

# Draw text
number = 0
for row in cube_rows:
    for c in row:
        x,y,w,h = cv2.boundingRect(c)
        cv2.rectangle(original, (x, y), (x + w, y + h), (36,255,12), 2)

        cv2.putText(original, "#{}".format(number + 1), (x,y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,255), 2)
        number += 1

cv2.imshow('mask', mask)
cv2.imwrite('mask.png', mask)
cv2.imshow('original', original)
cv2.waitKey()

【讨论】:

  • 感谢 @nathancy 的代码,它确实有帮助,但你能解释一下如何识别特定轮廓所属的颜色,比如 1 属于橙色,2 属于蓝色
【解决方案2】:

这是找到的黄色方块的原始代码和位置。

来源

import numpy as np

import sys; sys.path.append('/usr/lib/pyshared/python2.7')

import cv2
from cv2 import *

im = cv2.imread('rubik.png')
im = cv2.bilateralFilter(im,9,75,75)
im = cv2.fastNlMeansDenoisingColored(im,None,10,10,7,21)
hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)   # HSV image


COLOR_MIN = np.array([20, 100, 100],np.uint8)       # HSV color code lower and upper bounds
COLOR_MAX = np.array([30, 255, 255],np.uint8)       # color yellow 

frame_threshed = cv2.inRange(hsv_img, COLOR_MIN, COLOR_MAX)     # Thresholding image
imgray = frame_threshed
ret,thresh = cv2.threshold(frame_threshed,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
# print type(contours)
for cnt in contours:
    x,y,w,h = cv2.boundingRect(cnt)
    print x,y
    cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("Show",im)
cv2.imwrite("extracted.jpg", im)
cv2.waitKey()
cv2.destroyAllWindows()

输出

185 307
185 189
307 185
431 55

【讨论】:

  • 您正在寻找图像中立方体的颜色,当背景中有其他类似颜色的物体时,这是不合适的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 2019-08-26
  • 2020-01-22
  • 1970-01-01
  • 2021-11-27
相关资源
最近更新 更多