J'essaie de détecter toutes les images de dés de forme carrée afin de pouvoir les recadrer individuellement et les utiliser pour l'OCR. Ci-dessous est l'image originale:
Voici le code que j'ai, mais il manque quelques carrés.
def find_squares(img):
img = cv2.GaussianBlur(img, (5, 5), 0)
squares = []
for gray in cv2.split(img):
for thrs in range(0, 255, 26):
if thrs == 0:
bin = cv2.Canny(gray, 0, 50, apertureSize=5)
bin = cv2.dilate(bin, None)
else:
_retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
bin, contours, _hierarchy = cv2.findContours(bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
cnt_len = cv2.arcLength(cnt, True)
cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in range(4)])
#print(cnt)
a = (cnt[1][1] - cnt[0][1])
if max_cos < 0.1 and a < img.shape[0]*0.8:
squares.append(cnt)
return squares
dice = cv2.imread('img1.png')
squares = find_squares(dice)
cv2.drawContours(dice, squares, -1, (0, 255, 0), 3)
Selon mon analyse, certains carrés manquent en raison de bords ronds manquants le long des dés en raison de la transition d'intensité en douceur entre les dés et l'arrière-plan.
Étant donné la contrainte qu'il y aura toujours 25 dés dans un motif de grille carré (5 * 5), pouvons-nous prédire les positions carrées manquantes sur la base des carrés reconnus? Ou pouvons-nous modifier l'algorithme ci-dessus pour l'algorithme de détection carré?
Voici une approche
Accentuer l'image avec cv2.filter2D()
. Nous utilisons un noyau de netteté générique, d'autres noyaux peuvent être trouvés ici
Maintenant seuil pour obtenir une image binaire
Effectuer des opérations morphologiques
De là, nous trouvons les contours et filtrons en utilisant cv2.contourArea()
avec des zones de seuil minimum/maximum.
Nous pouvons recadrer chaque région carrée souhaitée en utilisant la découpe Numpy et enregistrer chaque ROI comme ceci
x,y,w,h = cv2.boundingRect(c)
ROI = image[y:y+h, x:x+h]
cv2.imwrite('ROI_{}.png'.format(image_number), ROI)
import cv2
import numpy as np
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 5)
sharpen_kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
sharpen = cv2.filter2D(blur, -1, sharpen_kernel)
thresh = cv2.threshold(sharpen,160,255, cv2.THRESH_BINARY_INV)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
min_area = 100
max_area = 1500
image_number = 0
for c in cnts:
area = cv2.contourArea(c)
if area > min_area and area < max_area:
x,y,w,h = cv2.boundingRect(c)
ROI = image[y:y+h, x:x+h]
cv2.imwrite('ROI_{}.png'.format(image_number), ROI)
cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
image_number += 1
cv2.imshow('sharpen', sharpen)
cv2.imshow('close', close)
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()
Cette information supplémentaire est absolument dorée. Oui, étant donné la matrice de dés 5x5, vous pouvez très bien définir les positions. Les dés que vous pouvez identifier vous donnent le centre, la taille et l'orientation des dés. Continuez simplement ces motifs le long des deux axes. Pour votre deuxième passe, augmentez le contraste dans chaque "région d'intérêt" où vous vous attendez à trouver le bord d'une souris (ne dites jamais mourir!). Vous savez en quelques pixels où seront les bords: atténuez simplement l'image jusqu'à ce que vous identifiiez ces bords.