import cv2
import numpy as np
def crop_chess_board(
input_path="board.png", output_path="cropped_board.png"
):
img = cv2.imread(input_path)
if img is None:
print(f"Ошибка: Не удалось открыть файл '{input_path}'.")
return
img_h, img_w = img.shape[:2]
total_area = img_h * img_w
# 1. Перевод в оттенки серого
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. Адаптивный порог (отлично выделяет границы шахматных клеток)
thresh = cv2.adaptiveThreshold(
gray,
255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV,
11,
2,
)
# 3. Морфологическое "закрытие" — объединяем стоящие рядом клетки и фигуры
# в один плотный сплошной блок
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# 4. Поиск контуров
contours, _ = cv2.findContours(
closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
if not contours:
print("Контуры не найдены.")
return
# Сортируем контуры по площади
contours = sorted(contours, key=cv2.contourArea, reverse=True)
best_box = None
for c in contours:
x, y, w, h = cv2.boundingRect(c)
area = w * h
# Отбрасываем мелочь (< 3% экрана) и сам браузер/экран (> 95% экрана)
if area < (total_area * 0.03) or area > (total_area * 0.95):
continue
aspect_ratio = float(w) / h
# Доска должна быть близкой к квадрату (0.85 ... 1.15)
if 0.85 <= aspect_ratio <= 1.15:
best_box = (x, y, w, h)
break
# 5. Если по закрытию не нашли, пробуем fallback по Canny без жестких условий
if best_box is None:
edges = cv2.Canny(gray, 50, 150)
contours, _ = cv2.findContours(
edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE
)
contours = sorted(contours, key=cv2.contourArea, reverse=True)
for c in contours:
x, y, w, h = cv2.boundingRect(c)
area = w * h
if (
area > (total_area * 0.05)
and area < (total_area * 0.90)
and (0.85 <= float(w) / h <= 1.15)
):
best_box = (x, y, w, h)
break
if best_box is None:
print("Не удалось найти доску.")
return
x, y, w, h = best_box
cropped_img = img[y : y + h, x : x + w]
cv2.imwrite(output_path, cropped_img)
print(f"Успешно! Доска сохранена в '{output_path}'.")
if __name__ == "__main__":
crop_chess_board()