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


import os
import cv2

def load_templates(templates_folder="extracted_pieces"):
    """
    Загружает вырезанные шаблоны фигур и сопоставляет их с FEN-символами:
    Заглавные буквы (K, Q, R, B, N, P) - белые фигуры
    Строчные буквы (k, q, r, b, n, p) - черные фигуры
    """
    symbol_map = {
        "white_K": "K", "white_Q": "Q", "white_R": "R", "white_B": "B", "white_N": "N", "white_P": "P",
        "black_k": "k", "black_q": "q", "black_r": "r", "black_b": "b", "black_n": "n", "black_p": "p",
        "black_K": "k", "black_Q": "q", "black_R": "r", "black_B": "b", "black_N": "n", "black_P": "p"
    }

    templates = {}
    if not os.path.exists(templates_folder):
        print(f"Ошибка: Папка с шаблонами '{templates_folder}' не найдена!")
        return templates

    for filename in os.listdir(templates_folder):
        if filename.endswith(".png"):
            name_without_ext = os.path.splitext(filename)[0]
            
            # Определяем символ FEN
            symbol = symbol_map.get(name_without_ext)
            if not symbol:
                continue

            file_path = os.path.join(templates_folder, filename)
            tpl_img = cv2.imread(file_path)
            
            if tpl_img is not None:
                templates[symbol] = tpl_img

    return templates


def generate_fen(board_matrix):
    """
    Преобразует матрицу 8x8 в стандартную FEN-строку.
    """
    fen_rows = []
    for row in board_matrix:
        empty_count = 0
        row_str = ""
        for cell in row:
            if cell == ".":
                empty_count += 1
            else:
                if empty_count > 0:
                    row_str += str(empty_count)
                    empty_count = 0
                row_str += cell
        if empty_count > 0:
            row_str += str(empty_count)
        fen_rows.append(row_str)

    # Присоединяем служебную информацию FEN (ход белых, рокировки и т.д.)
    fen_body = "/".join(fen_rows)
    return f"{fen_body} w - - 0 1"


def scan_board(
    board_path="board.png",
    templates_folder="extracted_pieces",
    threshold=0.75,          # Порог уверенности (от 0.0 до 1.0)
    inner_margin_pct=0.04    # Внутренний отступ клетки против линий сетки
):
    # 1. Загрузка шаблонов
    templates = load_templates(templates_folder)
    if not templates:
        print("Ошибка: Нет загруженных шаблонов фигур.")
        return

    # 2. Загрузка текущей доски
    board_img = cv2.imread(board_path)
    if board_img is None:
        print(f"Ошибка: Не удалось открыть файл доски '{board_path}'.")
        return

    img_h, img_w, _ = board_img.shape
    cell_w = img_w / 8.0
    cell_h = img_h / 8.0

    board_matrix = []

    print("Сканирование доски...\n")

    # 3. Обход всех 64 клеток
    for row in range(8):
        row_symbols = []
        for col in range(8):
            # Расчет координат клетки с внутренним отступом
            x1_raw = col * cell_w
            y1_raw = row * cell_h
            x2_raw = (col + 1) * cell_w
            y2_raw = (row + 1) * cell_h

            pad_w = cell_w * inner_margin_pct
            pad_h = cell_h * inner_margin_pct

            x1 = int(round(x1_raw + pad_w))
            y1 = int(round(y1_raw + pad_h))
            x2 = int(round(x2_raw - pad_w))
            y2 = int(round(y2_raw - pad_h))

            cell_crop = board_img[y1:y2, x1:x2]

            best_match_symbol = "."
            best_score = -1.0

            # Сравниваем клетку с каждым шаблоном
            for symbol, tpl in templates.items():
                tpl_h, tpl_w, _ = tpl.shape
                
                # Масштабируем вырезку клетки под размер шаблона для точного сравнения
                cell_resized = cv2.resize(cell_crop, (tpl_w, tpl_h))

                # Шаблонное сопоставление (Template Matching)
                result = cv2.matchTemplate(cell_resized, tpl, cv2.TM_CCOEFF_NORMED)
                _, max_val, _, _ = cv2.minMaxLoc(result)

                if max_val > best_score:
                    best_score = max_val
                    best_match_symbol = symbol

            # Если совпадение выше порога — значит на клетке стоит фигура
            if best_score >= threshold:
                row_symbols.append(best_match_symbol)
            else:
                row_symbols.append(".")

        board_matrix.append(row_symbols)

    # 4. Отрисовка доски в консоли
    divider = "  +" + "---+" * 8
    print(divider)
    for i, row in enumerate(board_matrix):
        rank_label = 8 - i
        row_content = " | ".join(row)
        print(f"{rank_label} | {row_content} |")
        print(divider)
    print("    a   b   c   d   e   f   g   h\n")

    # 5. Генерация и вывод FEN
    fen_string = generate_fen(board_matrix)
    print(f"FEN: {fen_string}")


if __name__ == "__main__":
    scan_board()