Положение шахматных фигур на физической доске в матрицу с использованием opencv

Итак, что я пытаюсь сделать, так это; с помощью веб-камеры сделайте снимок и из этого снимка извлеките положение шахматных фигур на доске и запишите их на матрицу или в список, это не имеет большого значения, потому что после этого мне просто нужно проверить движение, которое было сделанный.

Я просмотрел некоторые учебники и документацию, но я потерялся, лучшее, что я мог получить, это этот ответ, но я даже не могу получить сетку: Возможно, это из-за самой платы или даже из-за эффекта рыбьего глаза веб-камеры, которую я использую.

Это код, о котором идет речь:

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 не делает то, что я хочу, я понятия не имею, как решить проблему, получить координаты фигур на доске, какие места пусты, а в каких есть фигура.

Это оригинальное изображение из показанных выше.

Лучшее фото со смартфона, я поставила буквы на кусочки, думала, что это может как-то помочь, но новых идей нет.

Кроме того, матрица, которую я ожидал получить, была похожа на показанную в документации библиотеки 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 угла доски.

Код, используемый для поиска углов (изображение только с синими точками):

import cv2
import numpy as np

def main():
    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(frame):
    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

if __name__ is "__main__":

    main()

Используйте cv2.HoughLinesP вместо cv2.HoughLines

toyota Supra 19.04.2023 02:54

Вам приходится иметь дело с хлипкой шахматной доской ручной работы, как на вашем изображении? Если это так, то нельзя ожидать, что метод, предполагающий, что линии сетки представляют собой чистые прямые линии, будет работать хорошо.

fana 19.04.2023 03:44

Почему изображение искажено? Было бы разумно сначала отменить «рыбий глаз» с помощью калибровки, так будет намного проще работать с плоской доской. После устранения искажений сфотографируйте доску без каких-либо шахматных фигур. Найдите четыре угла доски и соберите прямоугольник. Вы знаете, сколько квадратов составляет одну «ширину доски», и вы можете приблизительно определить расположение каждого квадрата. Затем вы можете проанализировать каждый «квадрат» и определить, присутствует ли фигура. Может подойти простой порог HSV. Теперь будет сложно распознать/классифицировать эти ярлыки, потому что персонажи даже не ориентированы должным образом.

stateMachine 19.04.2023 06:04

Почему бы вам не использовать цветные точки для кодирования каждой части и вместо этого обнаружить это? Что-то вроде Pawns -> ярлык с большой зеленой красивой точкой. Слоны -> красная точка, кони -> синяя точка и т. д.

stateMachine 19.04.2023 06:09

@fana хорошо, у меня нет лучшей / другой шахматной доски, поэтому я пытаюсь работать с ней.

SmartlessName 19.04.2023 17:30

@stateMachine искаженное изображение передается точно так же веб-камерой, которую я использую, поэтому я рассматривал возможность использования вместо этого своего мобильного телефона. Спасибо за подсказку, согласен, что работать с цветными точками будет проще, чем с буквами, если я правильно помню, opencv может давать координаты контуров, поэтому, если я смогу получить их из цветных точек вместо этого, я попробую это позже, правильно сейчас я работаю над оставшейся частью задания. Спасибо!

SmartlessName 19.04.2023 17:36
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
6
98
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хорошо, это сработало, после этого легко найти квадрат, в котором цвета находятся с помощью c2v.findContours, cv2.contourArea() и cv2.moments().

corners = find_chessboard(frame)
corners = sorted(corners, key=lambda k: [k[1], k[0]])
corners2 = []
for i in range(10):
    corners2 = corners2 + sorted(corners[i*9:(i+1)*9], key=lambda k: [k[0]])

Другие вопросы по теме