web-dev-qa-db-fra.com

Python + OpenCV: segmentation d'image OCR

J'essaie de faire de l'OCR à partir de cet exemple de jouet de reçus. Utilisation de Python 2.7 et OpenCV 3.1.

enter image description here

Niveaux de gris + Flou + Détection de bord externe + Segmentation de chaque zone dans les reçus (par exemple "Catégorie" pour voir plus tard laquelle est marquée -dans ce cas en espèces-).

Je trouve compliqué lorsque l'image est "biaisée" de pouvoir transformer correctement puis segmenter "automatiquement" chaque segment des reçus.

Exemple:

enter image description here

Toute suggestion?

Le code ci-dessous est un exemple à obtenir jusqu'à la détection des contours, mais lorsque le reçu est comme la première image. Mon problème n'est pas l'image au texte. Est le prétraitement de l'image.

Toute aide plus qu'appréciée! :)

import os;
os.chdir() # Put your own directory

import cv2 
import numpy as np

image = cv2.imread("Rent-Receipt.jpg", cv2.IMREAD_GRAYSCALE)

blurred = cv2.GaussianBlur(image, (5, 5), 0)

#blurred  = cv2.bilateralFilter(gray,9,75,75)

# apply Canny Edge Detection
edged = cv2.Canny(blurred, 0, 20)

#Find external contour

(_,contours, _) = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
14
donpresente

Un excellent tutoriel sur la première étape que vous avez décrite est disponible sur pyimagesearch (et ils ont de grands tutoriels en général)

En bref, comme décrit par Ella, vous devez utiliser cv2.CHAIN_APPROX_SIMPLE. Une méthode légèrement plus robuste consisterait à utiliser cv2.RETR_LIST au lieu de cv2.RETR_EXTERNAL, puis triez les zones, car cela devrait fonctionner correctement même dans les arrière-plans blancs/si la page inscrit une forme plus grande en arrière-plan, etc.

Pour en venir à la deuxième partie de votre question, un bon moyen de segmenter les caractères serait d'utiliser l'extracteur de région extrême extrêmement stable disponible dans OpenCV. Une implémentation complète dans CPP est disponible ici dans un projet que j'aidais récemment. L'implémentation Python irait dans le sens de (Le code ci-dessous fonctionne pour OpenCV 3.0+. Pour la syntaxe OpenCV 2.x, vérifiez-la en ligne)

import cv2

img = cv2.imread('test.jpg')
mser = cv2.MSER_create()

#Resize the image so that MSER can work better
img = cv2.resize(img, (img.shape[1]*2, img.shape[0]*2))

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
vis = img.copy()

regions = mser.detectRegions(gray)
hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions[0]]
cv2.polylines(vis, hulls, 1, (0,255,0)) 

cv2.namedWindow('img', 0)
cv2.imshow('img', vis)
while(cv2.waitKey()!=ord('q')):
    continue
cv2.destroyAllWindows()

Cela donne la sortie comme

enter image description here

Maintenant, pour éliminer les faux positifs, vous pouvez simplement parcourir les points dans les coques et calculer le périmètre (somme de la distance entre tous les points adjacents dans les coques [i], où coques [i] est une liste de tous les points dans une coque convexe) ). Si le périmètre est trop grand, classifiez-le comme n'étant pas un caractère.

Les lignes de diagnostic à travers l'image viennent car la bordure de l'image est noire. qui peut simplement être supprimé en ajoutant la ligne suivante dès que l'image est lue (sous la ligne 7)

img = img[5:-5,5:-5,:]

ce qui donne la sortie

enter image description here

15

L'option sur le dessus de ma tête nécessite l'extraction des 4 coins de l'image asymétrique. Pour ce faire, utilisez cv2.CHAIN_APPROX_SIMPLE au lieu de cv2.CHAIN_APPROX_NONE lors de la recherche des contours. Ensuite, vous pouvez utiliser cv2.approxPolyDP et j'espère rester avec les 4 coins du reçu (si toutes vos images sont comme celle-ci, il n'y a aucune raison pour que cela ne fonctionne pas).

Utilisez maintenant cv2.findHomography et cv2.wardPerspective pour rectifier l'image selon les points source qui sont les 4 points extraits de l'image asymétrique et les points de destination qui doivent former un rectangle, par exemple les dimensions complètes de l'image.

Ici vous pouvez trouver des exemples de code et plus d'informations: OpenCV-Geometric Transformations of Images

Cette réponse peut également être utile - SO - Détecter et corriger le biais de texte

EDIT: correction de la deuxième chaîne d'environ cv2.CHAIN_APPROX_NONE.

5
Elia