Détecter la zone de texte dans une image en utilisant python et opencv

je veux détecter la zone de texte des images en utilisant python 2.7 et opencv 2.4.9 et dessinez un rectangle autour de lui. Comme le montre l'exemple de l'image ci-dessous.

je suis nouveau dans le traitement d'image donc toute idée sur la façon de faire cela sera appréciée.

building blueprint with labeled rooms

19
demandé sur prijatelj 2016-06-12 09:12:46

1 réponses

il y a plusieurs façons de détecter du texte dans une image.

je vous recommande de regarder cette question ici, car il peut répondre à votre cas. Bien qu'il ne soit pas en python, le code peut être facilement traduit de c++ en python (il suffit de regarder L'API et de convertir les méthodes de c++ en python, pas dur. Je l'ai fait moi-même quand j'ai essayé le code pour mon propre problème). Les solutions ici peuvent ne pas fonctionner pour votre cas, mais je recommande de les essayer hors.

Si je devais aller sur ce que je ferais le processus suivant:

Préparez votre image: Si toutes vos images que vous voulez éditer sont à peu près comme celle que vous avez fournie, où le design réel se compose d'une gamme de couleurs grises, et le texte est toujours noir. Je voudrais tout d'abord blanc sur tout le contenu qui n'est pas noir (ou blanc). Ce faisant, il ne restera que le texte en noir.

# must import if working with opencv in python
import numpy as np
import cv2

# removes pixels in image that are between the range of
# [lower_val,upper_val]
def remove_gray(img,lower_val,upper_val):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    lower_bound = np.array([0,0,lower_val])
    upper_bound = np.array([255,255,upper_val])
    mask = cv2.inRange(gray, lower_bound, upper_bound)
    return cv2.bitwise_and(gray, gray, mask = mask)

Maintenant que tout ce que vous avez est le texte en noir le but est d'obtenir ces boîte. Comme indiqué précédemment, il existe différentes façons de le faire.

la Largeur du trait de Transformation (SWT)

la façon typique de trouver des zones de texte: vous pouvez trouver des zones de texte en utilisant la transformation de la largeur des traits comme indiqué dans "la Détection de Texte dans des Scènes Naturelles avec la Largeur du trait de Transformer " par Boris Epshtein, Eyal Ofek, et Yonatan Wexler. Pour être honnête, si c'est aussi rapide et fiable comme je le crois, alors cette méthode est une méthode plus efficace que mon code ci-dessous. Vous pouvez toujours utiliser le code ci-dessus pour supprimer la conception du plan, et que contribuer à la performance globale de l'swt algorithme.

Voici une bibliothèque c qui implémente leur algorithme, mais il est dit qu'il est très brut et la documentation est déclarée incomplète. Évidemment, un wrapper sera nécessaire afin d'utiliser cette bibliothèque avec python, et pour le moment je ne vois pas d'offre officielle.

La bibliothèque J'ai fait un lien est CCV. C'est une bibliothèque qui est destinée à être utilisée dans vos applications, pas à recréer des algorithmes. Il s'agit donc d'un outil à utiliser, qui va à l'encontre de la volonté de L'OP de le faire à partir des "premiers principes", comme indiqué dans les commentaires. Néanmoins, il est utile de savoir qu'il existe si vous ne voulez pas coder l'algorithme vous-même.


la Maison Brassée Non-SWT Méthode

si vous avez des méta-données pour chaque image, disons dans un fichier xml, qui indique combien de pièces sont étiquetés dans chaque image, vous pouvez accéder à ce fichier xml, d'obtenir les données sur le nombre d'étiquettes sont dans l'image, puis de les stocker ce nombre dans une variable dire, num_of_labels. Maintenant, prenez votre image et passez - la à travers une boucle while qui s'érode à un taux défini que vous spécifiez, en trouvant des contours externes dans l'image dans chaque boucle et en arrêtant la boucle une fois que vous avez le même nombre de contours externes que votre num_of_labels. Ensuite, il suffit de trouver chaque contours ' bounding box et vous êtes faire.

# erodes image based on given kernel size (erosion = expands black areas)
def erode( img, kern_size = 3 ):
    retval, img = cv2.threshold(img, 254.0, 255.0, cv2.THRESH_BINARY) # threshold to deal with only black and white.
    kern = np.ones((kern_size,kern_size),np.uint8) # make a kernel for erosion based on given kernel size.
    eroded = cv2.erode(img, kern, 1) # erode your image to blobbify black areas
    y,x = eroded.shape # get shape of image to make a white boarder around image of 1px, to avoid problems with find contours.
    return cv2.rectangle(eroded, (0,0), (x,y), (255,255,255), 1)

# finds contours of eroded image
def prep( img, kern_size = 3 ):    
    img = erode( img, kern_size )
    retval, img = cv2.threshold(img, 200.0, 255.0, cv2.THRESH_BINARY_INV) #   invert colors for findContours
    return cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # Find Contours of Image

# given img & number of desired blobs, returns contours of blobs.
def blobbify(img, num_of_labels, kern_size = 3, dilation_rate = 10):
    prep_img, contours, hierarchy = prep( img.copy(), kern_size ) # dilate img and check current contour count.
    while len(contours) > num_of_labels:
        kern_size += dilation_rate # add dilation_rate to kern_size to increase the blob. Remember kern_size must always be odd.
        previous = (prep_img, contours, hierarchy)
        processed_img, contours, hierarchy = prep( img.copy(), kern_size ) # dilate img and check current contour count, again.
    if len(contours) < num_of_labels:
        return (processed_img, contours, hierarchy)
    else:
        return previous

# finds bounding boxes of all contours
def bounding_box(contours):
    bBox = []
    for curve in contours:
        box = cv2.boundingRect(curve)
    bBox.append(box)
    return bBox

les boîtes résultant de la méthode ci-dessus auront de l'espace autour des étiquettes, et cela peut inclure une partie de la conception originale, si les boîtes sont appliquées à l'image originale. Pour éviter cela faire des régions d'intérêt via vos nouvelles boîtes trouvées et couper l'espace blanc. Alors garde la forme de ce roi comme ta nouvelle boîte.

peut-être que vous n'avez aucun moyen de savoir combien d'étiquettes sera dans l'image. Si c'est le cas, alors je vous recommande de jouer avec l'érosion valeurs jusqu'à ce que vous trouvez le meilleur pour convenir à votre cas et d'obtenir les taches désirées.

ou vous pouvez essayer de trouver des contours sur le contenu restant, après avoir enlevé le dessin, et combiner les boîtes de délimitation dans un rectangle basé sur leur distance les uns des autres.

après avoir trouvé vos boîtes, utilisez simplement ces boîtes par rapport à l'image originale et vous aurez terminé.


module de détection de texte de scène dans OpenCV 3

Comme mentionné dans les commentaires à votre question, il existe déjà un moyen de détection de texte de scène (pas de détection de texte de document) dans opencv 3. Je comprends que vous n'ayez pas la possibilité de changer de version, mais pour ceux qui ont la même question et qui ne sont pas limités à une ancienne version opencv, j'ai décidé de l'inclure à la fin. La Documentation pour la détection de texte de scène peut être trouvée avec une simple recherche google.

le module opencv pour la détection de texte est également livré avec la reconnaissance de texte qui implémente tessaract, qui est un module de reconnaissance de texte libre. La chute de tessaract, et donc du module de reconnaissance de texte scene d'opencv, est qu'il n'est pas aussi raffiné que les applications commerciales et qu'il prend du temps à utiliser. Ainsi diminuant sa performance, mais son libre à l'utilisation, de sorte que son le meilleur nous avons obtenu sans payer l'argent, si vous voulez la reconnaissance de texte aussi bien.

Liens:

honnêtement, je manque d'expérience et d'expertise en opencv et traitement d'image afin de fournir une façon détaillée dans la mise en œuvre de leur module de détection de texte. La même chose avec l'algorithme SWT. Je viens de me mettre dans ce genre de choses ces derniers mois, mais comme j'en apprends plus je vais éditer cette réponse.

32
répondu prijatelj 2017-05-23 12:02:22