Python OpenCV: Rubik's cube solver color extraction

前端 未结 2 1989
北荒
北荒 2020-12-28 21:16

Description:

I am working on solving rubiks cube using Python & OpenCV. For this purpose I am trying to extract all the colors of the cubies(ind

相关标签:
2条回答
  • 2020-12-28 21:36

    Here's a simple approach:

    • Convert image to HSV format
    • Use color thresholding to detect the squares with cv2.inRange
    • Perform morphological operations and draw squares onto a mask
    • Find contours on mask and sort from top-bottom or bottom-top
    • Take each row of three squares and sort from left-right or right-left

    After converting to HSV format, we perform color thresholding using cv2.inRange() to detect the squares. We draw the detected squares onto a mask

    From here we find contours on the mask and utilize imutils.contours.sort_contours() to sort the contours from top-to-bottom or bottom-to-top. Next we take each row of 3 squares and sort this row from left-to-right or right-to-left. Here's a visualization of the sorting (top-bottom, left) or (bottom-top, right)

    Now that we have the contours sorted, we simply draw the rectangles onto our image. Here's the results

    Left-to-right and top-to-bottom (left), right-to-left and top-to-bottom

    Left-to-right and bottom-to-top (left), right-to-left and bottom-to-top

    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()
    
    0 讨论(0)
  • 2020-12-28 21:38

    Here's the original code and location of the found yellow squares.

    source

    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()
    

    output

    185 307
    185 189
    307 185
    431 55
    
    0 讨论(0)
提交回复
热议问题