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


import os
import cv2
import numpy as np


def verify_chessboard_grid(gray_crop):
  """Проверяет, есть ли внутри найденного квадрата 1x1 характерная сетка 8x8."""
  h, w = gray_crop.shape
  if h < 64:
    return False, 0

  edges = cv2.Canny(gray_crop, 40, 120)

  col_sums = np.sum(edges, axis=0)
  row_sums = np.sum(edges, axis=1)

  cell_size = w / 8.0

  score_x = 0
  score_y = 0

  for i in range(1, 8):
    idx = int(round(i * cell_size))
    x_min, x_max = max(0, idx - 2), min(w, idx + 3)
    y_min, y_max = max(0, idx - 2), min(h, idx + 3)

    score_x += np.max(col_sums[x_min:x_max]) if x_max > x_min else 0
    score_y += np.max(row_sums[y_min:y_max]) if y_max > y_min else 0

  total_score = score_x + score_y
  return True, total_score


def save_board_cells(board_size, txt_path='Boardcells.txt'):
  """Записывает координаты 64 клеток 8x8 относительно обрезанного изображения."""
  cell_size = board_size / 8.0

  with open(txt_path, 'w', encoding='utf-8') as f:
    cell_idx = 1
    for row in range(8):
      for col in range(8):
        # Верхний левый угол клетки (x, y)
        x = int(round(col * cell_size))
        y = int(round(row * cell_size))

        # Нижний правый угол клетки (z=x2, w=y2)
        z = int(round((col + 1) * cell_size))
        w = int(round((row + 1) * cell_size))

        # Если вам нужны ширина и высота вместо (x2, y2), раскомментируйте:
        # z = z - x  # ширина (width)
        # w = w - y  # высота (height)

        f.write(f'cells_{cell_idx}: {x}, {y}, {z}, {w}\n')
        cell_idx += 1

  print(f'[OK] Координаты клеток сохранены в файл: {txt_path}')


def find_chessboard_strictly_1to1(
    input_path='board1.png',
    output_path='aboard1.png',
    cells_path='Boardcells.txt',
):
  img = cv2.imread(input_path)
  if img is None:
    print(f'[Ошибка] Не удалось загрузить {input_path}')
    return False

  gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

  # 1. Поиск границ
  edges = cv2.Canny(gray, 30, 150)

  # 2. Поиск контуров
  contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

  best_board = None
  max_score = -1

  for cnt in contours:
    x, y, w, h = cv2.boundingRect(cnt)

    if w < 80 or h < 80:
      continue

    aspect_ratio = float(w) / h
    if not (0.98 <= aspect_ratio <= 1.02):
      continue

    size = min(w, h)
    crop = gray[y : y + size, x : x + size]

    is_grid, score = verify_chessboard_grid(crop)

    if is_grid and score > max_score:
      max_score = score
      best_board = (x, y, size)

  if best_board is None:
    print(f'[Ошибка] Квадратная доска 1*1 не найдена в {input_path}')
    return False

  bx, by, size = best_board
  cropped_board = img[by : by + size, bx : bx + size]

  # Сохраняем вырезанную доску
  cv2.imwrite(output_path, cropped_board)
  print(
      f'[OK] {input_path} -> {output_path} | Квадрат 1*1: {size}x{size} px'
      f' (Координаты доски на исходнике: X={bx}, Y={by})'
  )

  # Сохраняем координаты каждой из 64 клеток
  save_board_cells(size, cells_path)

  return True


if __name__ == '__main__':
  input_file = 'board1.png'
  output_file = 'aboard1.png'

  if os.path.exists(input_file):
    find_chessboard_strictly_1to1(input_file, output_file)
  else:
    print(f'Файл {input_file} не найден.')