import cv2
def crop_chess_board(input_img):
"""
Находит шахматную доску на кадре.
Возвращает:
1) Обрезанное изображение доски (400x400)
2) Координаты доски на экране {'left': x, 'top': y, 'width': w, 'height': h}
"""
img_h, img_w = input_img.shape[:2]
total_area = img_h * img_w
# Если доска не найдена, по умолчанию используем весь кадр
default_roi = {"left": 0, "top": 0, "width": img_w, "height": img_h}
gray = cv2.cvtColor(input_img, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(
gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 11, 2
)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
contours, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if not contours:
return cv2.resize(input_img, (400, 400)), default_roi
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
if area < (total_area * 0.03) or area > (total_area * 0.95):
continue
aspect_ratio = float(w) / h
if 0.85 <= aspect_ratio <= 1.15:
best_box = (x, y, w, h)
break
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 (total_area * 0.05) < 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:
return cv2.resize(input_img, (400, 400)), default_roi
x, y, w, h = best_box
cropped_img = input_img[y:y+h, x:x+w]
# Формируем точные координаты найденной доски
board_roi = {
"left": x,
"top": y,
"width": w,
"height": h
}
# Возвращаем И картинку, И координаты доски
return cv2.resize(cropped_img, (400, 400)), board_roi