使用 opencv 将物理棋盘上的棋子定位到矩阵

问题描述 投票:0回答:0

好吧,我要做的是;使用网络摄像头拍照并从该照片中提取棋盘上棋子的位置并将它们写在矩阵或列表上,这无关紧要,因为之后我只需要验证棋子的移动完成。

我浏览了一些教程和文档,但我迷路了,我能得到的最好的线索是this answer,但我什至无法获得网格: It can possibly be because of the board itself, or even the fish eye effect of the web camera I'm using has.

这是有问题的代码:

import cv2
import numpy as np


def main():
    im = cv2.imread('opencv_frame_0.png')
    #im = cv2.resize(im, (640, 480))  
    #edge = cv2.imread('edge.png', 0)
    edge = cv2.Canny(im, 60, 160, apertureSize=3)
    lines = cv2.HoughLines(edge, 1, np.pi/180, 100, 100, 50)
    for rho, theta in lines[0]:
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))
        cv2.line(im, (x1, y1), (x2, y2), (0, 0, 255), 2)
        # TODO: filter the lines by color and line distance

    cv2.imshow('image', im)
    cv2.imshow('edge', edge)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

无论如何,即使我能弄清楚为什么

cv2.HoughLines
没有做我想做的事,我也不知道如何处理这个问题,获取棋盘上棋子的坐标,哪些空间是空的,哪些空间有一块

This is the original image of the ones showed above.

A better photo using my smartphone, I put some letters on the pieces thinking it could help in some way, but no new ideas.

此外,我期望得到的矩阵与 chess python 库文档中所示的一样

r . b q k b . r
p p p p . Q p p
. . n . . n . .
. . . . p . . .
. . B . P . . .
. . . . . . . .
P P P P . P P P
R N B . K . N R

更新

好吧,所以,根据@stateMachine 的建议,我改为颜色检测。我现在拥有的是,使用这张图片:

我在

cv2.goodFeaturesToTrack
的帮助下检测每个角落,这是输出:

现在,我要做的是获取棋盘上每个方格的中点坐标。而且,因为cv2给出的蓝色点(如上图所示)没有顺序,我不能直接使用其中的4个,只找到中间点,例如:

[[254, 606], [387, 465], [519, 187], [314, 262], [172, 132], [315, 329], [179, 405], [523, 395], [246, 334], [112, 475], [519, 256], [383, 327], [382, 193], [392, 534], [596, 531], [461, 601], [238, 130], [175, 198], [452, 327], [458, 533], [525, 461], [181, 471], [40, 339], [594, 460], [381, 260], [175, 336], [43, 477], [448, 191], [454, 394], [173, 264], [518, 118], [521, 323], [245, 262], [387, 396], [245, 404], [251, 540], [42, 408], [182, 543], [36, 204], [45, 614], [590, 322], [453, 258], [45, 545], [456, 466], [307, 125], [109, 338], [600, 597], [321, 537], [592, 392], [111, 545], [106, 203], [392, 603], [107, 266], [242, 198], [38, 269], [446,  53], [585, 185], [588, 253], [114, 610], [531, 599], [99, 65], [108, 407], [309, 55], [377, 54], [33, 135], [380, 122], [30, 67], [530, 530], [449, 123], [169, 64],  [182, 608], [584, 117], [250, 472], [317, 400], [313, 193], [236, 62], [103, 132], [589, 47], [515, 51], [319, 466], [321, 604]]

所以,我目前的做法是找到左上角、右角和左下角和右下角的坐标,然后划分距离,这样我就可以相交线并找到更多的点:

现在,我的问题是;如果相机不是正对着上方,中间的点并不是真的在中间,原因是因为视角有些方块比其他方块大,所以划分不可靠。

我现在需要做的是找到上面显示的列表中属于同一个正方形的 4 个点,并找到它们之间的中间点,而不是仅仅使用板的 4 个角进行除法。

用于查找角点的代码(只有蓝点的图像): ''' 导入cv2 将 numpy 导入为 np

定义主要(): frame = cv2.imread("chessboard.jpg")

cv2.namedWindow("Frame", cv2.WINDOW_NORMAL)

corners = []

corners = find_chessboard(frame)

print(corners)

cv2.waitKey(0)
cv2.destroyAllWindows()
return True

def find_chessboard(框架): img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

corners = cv2.goodFeaturesToTrack(img, 81, 0.01, 10)
corners = np.int0(corners)

corners_coordinates = [[]]*len(corners)

i = 0
for corner in corners:
    x, y = corner.ravel()
    corners_coordinates[i] = [x, y]
    i = i+1

    cv2.circle(frame, (x, y), 5, (255, 0, 0), -1)
cv2.imshow("Frame", frame)

return corners_coordinates

如果name是“main”:

main()

'''

python opencv position chess
© www.soinside.com 2019 - 2024. All rights reserved.