I am trying to write a program that could record chess moves played on a physical chessboard. The first step is to identify the chessboard and the individual squares. I have come up with a code that looks like it could work, but unfortunately, it's not functioning as expected. I have tried it on various chessboards with different viewing angles, but I still can't get it to work. After some research, I found that cv2.findChessboardCorners can be quite confusing. Can someone please help?
The following code is what I have tried. I expected it to find the chessboard, extract individual squares to temporary files, and print out the file names of the temporary files. However, I keep getting "Chessboard not found."
import cv2
import numpy as np
import tempfile
def extract_chessboard_squares(image_path, rows, columns):
# Load the chessboard image
image = cv2.imread(image_path)
# Convert the image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Find the chessboard corners
found, corners = cv2.findChessboardCorners(gray, (rows, columns), None)
if found:
# Refine the corner locations
corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1))
# Create a 2D list to store file names of chessboard squares
square_files = [[None] * columns for _ in range(rows)]
# Iterate over each chessboard square
for row in range(rows):
for col in range(columns):
# Calculate the square corners' coordinates
pt1 = corners[row * columns + col]
pt2 = corners[(row + 1) * columns + col]
pt3 = corners[(row + 1) * columns + col + 1]
pt4 = corners[row * columns + col + 1]
# Create a mask for the current square
mask = np.zeros_like(image)
cv2.fillConvexPoly(mask, np.int32([pt1, pt2, pt3, pt4]), (255, 255, 255))
# Apply the mask to the original image
masked_image = cv2.bitwise_and(image, mask)
# Save the masked image to a temporary file
_, temp_filename = tempfile.mkstemp(suffix='.jpg')
cv2.imwrite(temp_filename, masked_image)
# Store the temporary file name in the 2D list
square_files[row][col] = temp_filename
return square_files
else:
print("Chessboard not found.")
return None
# Example usage:
image_path = 'path/to/chessboard_image.jpg'
rows = 8
columns = 8
result = extract_chessboard_squares(image_path, rows, columns)
if result:
square_files = result
# Use the square_files list as per your requirements
Make sure to replace 'path/to/chessboard_image.jpg' with the actual path to your chessboard image file.
following Lelouch suggestion this is what i came up with. note this solution is still not perfect as it ONLY extract the inner 6x6 squares that is surrounded by the 7x7 inner corners.