【问题标题】:Chess piece detection On chessboard Opencv棋子检测 On checkboard Opencv
【发布时间】:2023-01-31 01:20:47
【问题描述】:

我正在尝试检测

在我的棋盘上

但是无法让它检测到正确的部分。这件作品是 59x83。它应该被检测到,但没有。 我想我在这里遗漏了什么?

import cv2
import numpy as np

# Load the chess board and chess piece images
img_board = cv2.imread('ccom.png')
img_piece = cv2.imread('bbis.png')

# Convert both images to grayscale
img_board_gray = cv2.cvtColor(img_board, cv2.COLOR_BGR2GRAY)
img_piece_gray = cv2.cvtColor(img_piece, cv2.COLOR_BGR2GRAY)

# Apply morphological operations to extract the chess piece from the board
kernel = np.ones((5, 5), np.uint8)
img_piece_mask = cv2.erode(img_piece_gray, kernel, iterations=1)
img_piece_mask = cv2.dilate(img_piece_mask, kernel, iterations=1)

# Find the matching location on the board
result = cv2.matchTemplate(img_board_gray, img_piece_mask, cv2.TM_SQDIFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

# Draw a rectangle around the matching location
top_left = min_loc
bottom_right = (top_left[0] + img_piece.shape[1], top_left[1] + img_piece.shape[0])
cv2.rectangle(img_board, top_left, bottom_right, (0, 0, 255), 2)

# Show the result
cv2.imshow('Result', img_board)
cv2.waitKey(0)
cv2.destroyAllWindows()

【问题讨论】:

  • 相同颜色的棋子应该只匹配还是两种颜色的棋子都匹配?
  • 只有相同的颜色

标签: python opencv


【解决方案1】:

我尝试了几种设置,并通过实验发现这种设置效果最好:

  1. 忽略棋子颜色进行形状匹配。
  2. 只对匹配的部分进行颜色匹配。

    1- 形状匹配:

    使用与您列出的方法类似的方法,但使用 morphological gradient 来稳定匹配,创建响应映射。对地图进行阈值处理以获取最可能的位置(在我们的示例中为 4,因为未检查颜色)。

    2-配色:

    使用绝对像素差异后跟一个阈值(需要调整),我们可以决定所研究的作品的颜色是否与提供的模板图像匹配。

    import cv2
    import numpy as np
    
    def draw_results(img, rects):
        for r in rects:
            print(r)
            cv2.rectangle(img, (r[0], r[1]), (r[0] + r[2], r[1] + r[3]), (0, 0, 255), 2)
    
    def check_color(img, temp, rect):
        y0, y1, x0, x1 = rect[1], rect[1] + rect[3], rect[0], rect[0] + rect[2]    
        crop = (img[y0 : y1, x0 : x1]).copy()
        diff = cv2.absdiff(temp, crop)
        avg_diff = cv2.mean(diff)[0] / 255        
        return avg_diff < 0.4 # a tricky threshold
    
    def find_template_multiple(img, temp):
        rects = []
        w, h = temp.shape[1], temp.shape[0]
    
        result = cv2.matchTemplate(img, temp, cv2.TM_CCOEFF_NORMED)
        threshold = 0.5 # matching threshold, relatively stable.
        loc = np.where( res >= threshold)
    
        for pt in zip(*loc[::-1]):
            rects.append((pt[0], pt[1], w, h))    
    
        #Perform a simple non-max suppression 
        rects, _ = cv2.groupRectangles(rects, 1, 1)
    
        #Flatten list of list to list of elements
        rects = [r for r in rects]   
    
        return rects
    
    
    # Load the chess board and chess piece images
    img_board = cv2.imread('board.png')
    img_piece = cv2.imread('template.png')
    
    # Convert both images to grayscale
    img_board_gray = cv2.cvtColor(img_board, cv2.COLOR_BGR2GRAY)
    img_piece_gray = cv2.cvtColor(img_piece, cv2.COLOR_BGR2GRAY)
    
    s = 3
    kernel = np.ones((s, s), np.uint8)
    #morphological gradient stabilizes the template matching by focusing on the shape's edges rather than its content.
    img_board_gray_grad = cv2.morphologyEx(img_board_gray, cv2.MORPH_GRADIENT, kernel)
    img_piece_gray_grad = cv2.morphologyEx(img_piece_gray, cv2.MORPH_GRADIENT, kernel)
    
    
    rects = find_template_multiple(img_board_gray_grad, img_piece_gray_grad)
    
    matching_color_list = [check_color(img_board_gray, img_piece_gray, r) for r in rects]
    
    #Keep only matching color rectangles.
    matching_color_rects = [r for (r, is_matching) in zip(rects, matching_color_list) if is_matching]
    
    
    draw_results(img_board, matching_color_rects)
    
    
    # Show the result
    cv2.imshow('Result', img_board)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-18
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 2016-02-28
    • 2022-01-17
    • 1970-01-01
    • 2014-06-04
    相关资源
    最近更新 更多