Загрузка данных


import cv2
import numpy as np
import os

# Папка для хранения шаблонов 12 фигур
TEMPLATES_DIR = "templates"
PIECES = ['r', 'n', 'b', 'q', 'k', 'p', 'R', 'N', 'B', 'Q', 'K', 'P']


def crop_board(image_path):
    """Вырезает и примет доску под размер 400x400"""
    img = cv2.imread(image_path)
    if img is None:
        raise FileNotFoundError(f"Не удалось открыть файл: {image_path}")

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    edges = cv2.Canny(blur, 50, 150)

    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    board_cnt = None
    max_area = 0

    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area > 10000:
            peri = cv2.arcLength(cnt, True)
            approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
            if len(approx) == 4 and area > max_area:
                board_cnt = approx
                max_area = area

    if board_cnt is not None:
        pts = board_cnt.reshape(4, 2)
        rect = np.zeros((4, 2), dtype="float32")
        s = pts.sum(axis=1)
        rect[0] = pts[np.argmin(s)]
        rect[2] = pts[np.argmax(s)]
        diff = np.diff(pts, axis=1)
        rect[1] = pts[np.argmin(diff)]
        rect[3] = pts[np.argmax(diff)]
        dst = np.array([[0, 0], [399, 0], [399, 399], [0, 399]], dtype="float32")
        M = cv2.getPerspectiveTransform(rect, dst)
        return cv2.warpPerspective(img, M, (400, 400))
    else:
        return cv2.resize(img, (400, 400))


def generate_templates_from_start_position(start_image_path="start_board.png"):
    """Автоматически нарезает 12 шаблонов фигур из начальной позиции"""
    os.makedirs(TEMPLATES_DIR, exist_ok=True)
    board = crop_board(start_image_path)
    
    # Координаты клеток для начальной позиции:
    # Ряд 0: r, n, b, q, k, b, n, r
    # Ряд 1: p (пешка)
    # Ряд 6: P (белая пешка)
    # Ряд 7: R, N, B, Q, K, B, N, R
    coords = {
        'r': (0, 0), 'n': (0, 1), 'b': (0, 2), 'q': (0, 3), 'k': (0, 4), 'p': (1, 0),
        'R': (7, 0), 'N': (7, 1), 'B': (7, 2), 'Q': (7, 3), 'K': (7, 4), 'P': (6, 0)
    }

    cell_size = 50
    for piece, (row, col) in coords.items():
        y1, y2 = row * cell_size, (row + 1) * cell_size
        x1, x2 = col * cell_size, (col + 1) * cell_size
        cell_img = board[y1:y2, x1:x2]
        
        cv2.imwrite(os.path.join(TEMPLATES_DIR, f"{piece}.png"), cell_img)
    
    print(f"✓ Все 12 шаблонов фигур успешно сохранены в папку '{TEMPLATES_DIR}/'!")


def scan_board_with_templates(target_image_path="board.png"):
    """Сканирует любую позицию, сравнивая клетки с сохраненными шаблонами"""
    if not os.path.exists(TEMPLATES_DIR) or len(os.listdir(TEMPLATES_DIR)) < 12:
        print("Шаблоны не найдены! Сначала создаем их из start_board.png...")
        generate_templates_from_start_position("start_board.png")

    # Загружаем 12 шаблонов
    templates = {}
    for piece in PIECES:
        t_path = os.path.join(TEMPLATES_DIR, f"{piece}.png")
        templates[piece] = cv2.imread(t_path)

    board = crop_board(target_image_path)
    cell_size = 50
    board_matrix = []

    for row in range(8):
        row_pieces = []
        for col in range(8):
            y1, y2 = row * cell_size, (row + 1) * cell_size
            x1, x2 = col * cell_size, (col + 1) * cell_size
            cell = board[y1:y2, x1:x2]

            best_match = '.'
            max_score = 0.80  # Порог точности (80% совпадения)

            # Сравниваем клетку с каждым из 12 шаблонов
            for piece, t_img in templates.items():
                # Метод нормированной корреляции пикселей
                res = cv2.matchTemplate(cell, t_img, cv2.TM_CCOEFF_NORMED)
                _, max_val, _, _ = cv2.minMaxLoc(res)

                if max_val > max_score:
                    max_score = max_val
                    best_match = piece

            row_pieces.append(best_match)
        board_matrix.append(row_pieces)

    # Генерация FEN
    fen_rows = []
    for r in board_matrix:
        empty_count = 0
        row_str = ""
        for p in r:
            if p == '.':
                empty_count += 1
            else:
                if empty_count > 0:
                    row_str += str(empty_count)
                    empty_count = 0
                row_str += p
        if empty_count > 0:
            row_str += str(empty_count)
        fen_rows.append(row_str)

    final_fen = "/".join(fen_rows) + " w - - 0 1"
    
    print("\n===========================================")
    print("УСПЕХ! Сгенерированный FEN-код:")
    print(final_fen)
    print("===========================================")


if __name__ == "__main__":
    try:
        # Для сканирования любой доски:
        scan_board_with_templates("board.png")
    except Exception as e:
        print("Ошибка:", e)