OpenCV (quick forOpen Supply Pc Imaginative and prescient) is a library for Pc Imaginative and prescient, Machine Studying, and Picture Processing. It may be used to establish patterns in a picture, extract options, and carry out mathematical operations on it. Step one is to course of the puzzle screenshot utilizing OpenCV, lets have a fast refresher on fundamentals of OpenCV picture processing.
Set up the OpenCV python package deal
pip set up opencv-python
Find out how to load a picture
cv.imread
reads a picture file and converts it to an OpenCV matrix. If the picture can’t be learn as a result of the file could also be lacking or in a format that OpenCV can’t perceive an empty matrix is returned. The OpenCV matrix may be transformed to a picture again utilizing cv.imshow
operate.
import cv2 as cv
import numpy as np# Studying a picture
authentic = cv.imread("<file_name">)
cv.imshow("authentic", authentic)
How to attract a line, circle, rectangle, textual content on the identical picture
As soon as we detect the grid, we have to recreate it utilizing traces and place Q
utilizing textual content. Let’s take a look at a brief snippet to attract a line, circle, rectangle, and textual content on the above learn matrix.
# Drawing a line
line = cv.line(authentic, (authentic.form[1]//2, authentic.form[0]//2), (0,0) , (0,255,0), thickness=2)
cv.imshow("line", line)# Drawing different shapes
circle = cv.circle(line, (line.form[1]//2, line.form[0]//2), 50, (0,0,255), thickness=2)
rect = cv.rectangle(circle, (10,10), (circle.form[1]//2, circle.form[0]//2), (255,0,0), thickness=2)
textual content = cv.putText(rect, "Hello", (rect.form[1]//2, rect.form[0]//2), cv.FONT_HERSHEY_SIMPLEX, 1, (255,255,255), thickness=2)
cv.imshow("all shapes", textual content)
Find out how to detect contours
Contours are merely a form becoming a member of all factors of comparable colour and depth at a steady boundary. These are helpful when detecting shapes and object define evaluation. We’ll draw our puzzle grid by detecting the person cells.
# Its finest to transform picture to grayscale
# and add a little bit of blur for higher contour detections
# since our picture is generally a grid we dont want blur# by default OpenCV reads pictures as BGR
# versus conventional RGB
grey = cv.cvtConvert(authentic, cv.COLOR_BGR2GRAY)
contours, _ = cv.findContours(grey, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
By default, OpenCV reads pictures as BGR, versus conventional RGB
Cropping a picture
For us to remove pointless areas from screenshots and scale back noise, as soon as we’ve detected our contours
# its primarily choosing the pixels we want from your complete picture
cropped = authentic[0:original.shape[1]//2, 0:authentic.form[0]//2]
cv.imshow("cropped", cropped)
First, we start by loading the picture into reminiscence and changing it into Grayscale. This helps in simplifying contour detection, a common step that’s at all times adopted because it reduces the picture complexity. Subsequent, we discover contours, type them, and choose the most important one. Sometimes, the primary contour is the sure field of the unique picture, so we use the second largest contour to isolate the puzzle grid. Then, we crop the picture simply to get the grid and nothing else. We once more discover contours, since now the noise is lowered, it’ll detect the grid higher. We decide the variety of cells inside the grid and iterate over every cell, take the common colour, and assign plenty of every colour, which provides us the 2D array of our puzzle
# Learn the enter picture and save the unique
authentic = cv.imread(file_name)
cv.imwrite("answer/authentic.png", authentic)# Convert the picture to grayscale
grey = cv.cvtColor(authentic, cv.COLOR_BGR2GRAY)
# Discover contours within the grayscale picture and kind them by space
contours, _ = cv.findContours(grey, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
contours = sorted(contours, key=cv.contourArea, reverse=True)
# Extract the bounding field of the puzzle grid (utilizing the second largest contour)
x, y, w, h = cv.boundingRect(contours[1])
# Crop the grid space from the unique picture
grid = authentic[y:y+h, x:x+w]
cv.imwrite("answer/grid.png", grid)
# Convert the cropped grid to grayscale
grey = cv.cvtColor(grid, cv.COLOR_BGR2GRAY)
cv.imwrite("answer/gray-grid.png", grey)
# Discover contours once more within the cropped grayscale grid
contours, _ = cv.findContours(grey, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
contours = sorted(contours, key=cv.contourArea)
# Decide the full variety of cells within the grid
total_cells = len(contours) - 2
grid_size = int(math.sqrt(total_cells))
# Examine if the detected cells kind an entire sq. grid
if total_cells != grid_size**2:
print("Unable to detect full grid! Aborting")
# Calculate particular person cell dimensions
cell_width = w // grid_size
cell_height = h // grid_size
# Initialize colour mappings and board illustration
colours = []
board = []
color_index = 1
color_map = {}
reverse_color_map = {}
padding = 10
# Iterate by way of every cell within the grid
for i in vary(grid_size):
row = []
for j in vary(grid_size):
# Calculate cell coordinates with padding
cell_x = j * cell_width
cell_y = i * cell_height
padding = 15
cell = grid[cell_y+padding:cell_y+cell_height-padding, cell_x+padding:cell_x+cell_width-padding]
# Get the common colour of the cell
avg_color = cell.imply(axis=0).imply(axis=0)
avg_color = avg_color.astype(int)
avg_color = tuple(avg_color)
# Map the colour to a novel index if not already mapped
if avg_color not in color_map:
color_map[avg_color] = str(color_index)
reverse_color_map[str(color_index)] = avg_color
color_index += 1
# Add the colour index to the row
row.append(color_map[avg_color])
# Add the row to the board
board.append(row)