import cv2
import numpy as np
def scan_frame(cell_board, color_database, templates_edges):
"""
Принимает изображение доски, базу цветов и шаблоны контуров.
Возвращает матрицу фигур и FEN.
"""
# 1. Приводим входящее изображение к фиксированному размеру 400x400
board = cv2.resize(cell_board, (400, 400))
board_matrix = []
for row in range(8):
row_pieces = []
for col in range(8):
# 2. Вырезаем клетку 50x50
cell = board[row*50:(row+1)*50, col*50:(col+1)*50]
gray_cell = cv2.cvtColor(cell, cv2.COLOR_BGR2GRAY)
# 3. Берем только центральную часть (с 7 по 43 пиксель), убирая границы клеток,
# и выделяем контуры Canny
cell_edge = cv2.Canny(gray_cell[7:43, 7:43], 50, 150)
# 4. Проверка на пустоту (если мало белых пикселей на Canny — клетка пустая)
if np.count_nonzero(cell_edge) < 25:
row_pieces.append('.')
continue
# 5. Извлекаем преобладающий цвет фигуры
cell_color = np.array(extract_dominant_piece_color(cell))
best_match, max_score = '.', -999.0
# 6. Сравниваем форму (Canny) + вычитаем штраф за разницу цвета
for piece_symbol in ALL_PIECES:
res = cv2.matchTemplate(cell_edge, templates_edges[piece_symbol], cv2.TM_CCOEFF_NORMED)
_, shape_score, _, _ = cv2.minMaxLoc(res)
# Евклидово расстояние между цветами
color_dist = np.linalg.norm(cell_color - np.array(color_database[piece_symbol]))
# Итоговый балл: Совпадение формы МИНУС отклонение по цвету
score = shape_score - (color_dist / 100.0)
if score > max_score:
max_score, best_match = score, piece_symbol
row_pieces.append(best_match)
board_matrix.append(row_pieces)
# 7. Генерация FEN
fen_rows = []
for r in board_matrix:
empty, row_str = 0, ""
for p in r:
if p == '.':
empty += 1
else:
if empty > 0:
row_str += str(empty)
empty = 0
row_str += p
if empty > 0:
row_str += str(empty)
fen_rows.append(row_str)
return board_matrix, "/".join(fen_rows) + " w - - 0 1"