import cv2
import numpy as np
def find_and_crop_chessboard(image_path, pattern_size=(7, 7)):
"""Ищет шахматную доску на изображении и вырезает её.
:param image_path: Путь к исходному файлу изображения.
:param pattern_size: Количество ВНУТРЕННИХ углов клетки (по горизонтали и
вертикали).
Стандартная доска 8x8 имеет (7, 7) внутренних углов.
:return: Вырезанная доска или None, если доска не найдена.
"""
# 1. Загружаем изображение
img = cv2.imread(image_path)
if img is None:
print("Ошибка: Не удалось загрузить изображение.")
return None
# Переводим в оттенки серого для улучшения распознавания
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. Ищем внутренние углы шахматной доски
found, corners = cv2.findChessboardCorners(
gray,
pattern_size,
flags=cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE,
)
if not found:
print("Шахматная доска не найдена на экране.")
return None
# 3. Уточняем координаты углов для максимальной точности
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
corners_subpix = cv2.cornerSubPix(
gray, corners, (11, 11), (-1, -1), criteria
)
# 4. Находим крайние границы (Bounding Box) найденных углов
x_coords = corners_subpix[:, 0, 0]
y_coords = corners_subpix[:, 0, 1]
x_min, x_max = int(np.min(x_coords)), int(np.max(x_coords))
y_min, y_max = int(np.min(y_coords)), int(np.max(y_coords))
# Добавляем небольшой отступ (margin), чтобы забрать крайние клетки целиком
# (так как findChessboardCorners находит именно пересечения внутренних линий)
height, width = img.shape[:2]
cell_estimated_size = (x_max - x_min) / (pattern_size[0] - 1)
margin = int(cell_estimated_size)
x_min = max(0, x_min - margin)
y_min = max(0, y_min - margin)
x_max = min(width, x_max + margin)
y_max = min(height, y_max + margin)
# 5. Вырезаем область доски
cropped_board = img[y_min:y_max, x_min:x_max]
return cropped_board
# Пример использования:
# result = find_and_crop_chessboard('screenshot.png')
# if result is not None:
# cv2.imwrite('cropped_board.png', result)