import os
import cv2
import numpy as np
def verify_chessboard_grid(gray_crop):
"""Проверяет, есть ли внутри найденного квадрата 1x1 характерная сетка 8x8.
Использует принцип 1D-проекций градиентов из tensorflow_chessbot.
"""
h, w = gray_crop.shape
if h < 64: # Слишком маленькая область
return False, 0
# Выделяем внутренние границы клеток
edges = cv2.Canny(gray_crop, 40, 120)
# Суммируем пиксели вдоль колонок (X) и строк (Y)
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
# Проверяем всплески градиента на границах 7 внутренних линий (1..7)
for i in range(1, 8):
idx = int(round(i * cell_size))
# Берем окрестность в +-2 пикселя от идеальной линии
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 find_chessboard_strictly_1to1(input_path, output_path):
img = cv2.imread(input_path)
if img is None:
print(f"[Ошибка] Не удалось загрузить {input_path}")
return False
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h_img, w_img = gray.shape
# 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)
# Пропускаем мелкие шумы (доска должна быть хотя бы 80x80 px)
if w < 80 or h < 80:
continue
# СТРОГОЕ УСЛОВИЕ 1*1: пропорция сторон должна быть идеально близка к 1.0
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]
# Проверяем, что внутри этого квадрата реально находится сетка 8x8
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})"
)
return True
if __name__ == "__main__":
targets = [
("board1.png", "aboard1.png"),
("board2.png", "aboard2.png"),
("board3.png", "aboard3.png"),
]
for inp, outp in targets:
if os.path.exists(inp):
find_chessboard_strictly_1to1(inp, outp)
else:
print(f"Файл {inp} не найден.")