-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsave.py
More file actions
130 lines (94 loc) · 3.86 KB
/
save.py
File metadata and controls
130 lines (94 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import cv2
import numpy as np
from ultralytics import YOLO
# Object classes for chess pieces
classNames = ["B", "K", "N", "P", "Q", "R", "b", "k", "n", "p", "q", "r"]
# Load the YOLOv8 model
model = YOLO("runs/detect/train6/weights/best.pt")
def detect_chess_pieces(frame):
results = model(frame, stream=True)
piece_positions = {} # Dictionary to store piece positions
for r in results:
boxes = r.boxes
for box in boxes:
# Bounding box
x1, y1, x2, y2 = box.xyxy[0]
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
# Calculate the center coordinates of the bounding box
center_x = (x1 + x2) // 2
center_y = (y1 + y2) // 2
# Draw bounding box on the original frame
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
# Class name
cls = int(box.cls[0])
piece_name = classNames[cls]
# Object details
org = (x1, y1 - 5)
font = cv2.FONT_HERSHEY_SIMPLEX
fontScale = 0.7
color = (255, 0, 0)
thickness = 2
# Draw the piece name on the original frame
cv2.putText(frame, piece_name, org, font, fontScale, color, thickness)
# Store the piece position
square_position = chr(ord('a') + (center_x // 75)) + str(8 - (center_y // 75)) # Approximation
piece_positions[square_position] = piece_name
return frame, piece_positions
def detect_chess_board(frame):
# Convert the frame to grayscale
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Apply Gaussian blur to reduce noise
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# Apply Canny edge detection
edges = cv2.Canny(blur, 50, 150)
# Use morphology to remove noise and fill gaps
kernel = np.ones((5, 5), np.uint8)
morph = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
# Find contours in the morphed image
contours, _ = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Initialize variables for chess board dimensions
board_contour = None
board_area = 0
# Loop through the contours to find the largest quadrilateral (the chess board)
for cnt in contours:
# Approximate the contour to a polygon
approx = cv2.approxPolyDP(cnt, 0.02 * cv2.arcLength(cnt, True), True)
# Check if the approximated contour has 4 vertices (quadrilateral)
if len(approx) == 4:
# Calculate the area of the contour
area = cv2.contourArea(cnt)
# Update the board contour and area if the current contour is larger
if area > board_area:
board_contour = approx
board_area = area
return board_contour
# Load the video
cap = cv2.VideoCapture("Video/16.mp4")
# Get the original video dimensions and define the codec
new_width = 600
new_height = 600
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('Video/output_video.mp4', fourcc, 30.0, (new_width, new_height))
while True:
ret, frame = cap.read()
if not ret:
break
frame = cv2.resize(frame, (new_width, new_height))
# Detect the chessboard in the current frame
board_contour = detect_chess_board(frame)
if board_contour is not None:
# Draw the detected chessboard contour on the frame
cv2.drawContours(frame, [board_contour], -1, (0, 255, 0), 3)
# Detect chess pieces on the current frame
frame, piece_positions = detect_chess_pieces(frame)
# Write the frame to the output video
out.write(frame)
# Display the frame
cv2.imshow('Chess Pieces and Board Detection', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()