2016-06-12 18 views
10

Voglio rilevare l'area di testo delle immagini usando python 2.7 e opencv 2.4.9 e disegnare un'area rettangolare attorno ad essa. Come mostrato nell'immagine di esempio qui sotto.Rileva l'area di testo in un'immagine usando python e opencv

Sono nuovo nell'elaborazione delle immagini quindi qualsiasi idea su come farlo sarà apprezzata.

building blueprint with labeled rooms

+0

Se possibile, utilizzare OpenCV 3.1 e utilizzare la funzione [rilevamento testo scena] (https://github.com/Itseez/opencv_contrib/blob/master/modules/text/samples/textdetection.cpp). – flowfree

+0

@flowfree Non riesco ad aggiornarlo poiché ci sono altri componenti del progetto. – User9412

+0

Devi cercare il colore nell'immagine. Ma avendo il colore simile nella tua immagine, potrebbe essere difficile. Se stai cercando solo il testo all'interno di una libreria chiamata "tesseract" –

risposta

27

Ci sono diversi modi per andare a rilevare il testo in un'immagine.

Mi raccomando guardando this question here, perché potrebbe rispondere anche al tuo caso. Sebbene non sia in python, il codice può essere facilmente tradotto da C++ a python (basta guardare l'API e convertire i metodi da C++ a python, non è difficile, l'ho fatto io stesso quando ho provato il loro codice per il mio problema separato) . Le soluzioni qui potrebbero non funzionare per il tuo caso, ma ti consiglio di provarle.

Se dovessi andare su questo che vorrei fare la seguente procedura:

Prep vostra immagine: Se tutte le immagini che si desidera modificare sono grosso modo come quello che hai fornito, dove il design attuale è costituito da una gamma di colori grigi e il testo è sempre nero. Per prima cosa cancellerei tutto il contenuto che non è nero (o già bianco). Fare così lascerà solo il testo nero rimasto.

# 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) 

Ora che tutto quello che hai è il testo nero l'obiettivo è quello di ottenere quelle scatole. Come affermato in precedenza, ci sono diversi modi per farlo.

Stroke Width Transform (SWT)

Il modo tipico per trovare aree di testo: è possibile trovare le regioni di testo utilizzando larghezza del tratto trasformare come illustrato nella "Detecting Text in Natural Scenes with Stroke Width Transform " da Boris Epshtein, Eyal Ofek, e Yonatan Wexler. Per essere onesti, se questo è veloce e affidabile come credo, allora questo metodo è un metodo più efficiente del mio codice qui sotto. È comunque possibile utilizzare il codice sopra riportato per rimuovere il design del progetto, e che può aiutare le prestazioni generali dell'algoritmo swt.

Here is a c library che implementa il loro algoritmo, ma si dice che sia molto grezzo e che la documentazione sia dichiarata incompleta. Ovviamente, sarà necessario un wrapper per usare questa libreria con python, e al momento non vedo quella ufficiale offerta.

La libreria che ho collegato è CCV. È una libreria pensata per essere utilizzata nelle tue applicazioni, non per ricreare algoritmi. Quindi questo è uno strumento da utilizzare, che va contro la volontà dell'OP di farcela dai "Primi principi", come affermato nei commenti. Tuttavia, è utile sapere che esiste se non si desidera codificare l'algoritmo da soli.


casa Brewed non SWT Metodo

Se si dispone di metadati per ogni immagine, ad esempio in un file XML, che indica quante stanze sono etichettati in ogni immagine, quindi è possibile accedere a tale file xml , ottieni i dati sul numero di etichette presenti nell'immagine, quindi memorizza quel numero in una variabile che dice, num_of_labels. Ora prendi la tua immagine e passala attraverso un ciclo while che erode a una velocità impostata che specifichi, individuando i contorni esterni nell'immagine in ogni loop e fermando il ciclo una volta ottenuto lo stesso numero di contorni esterni del tuo num_of_labels. Quindi trova semplicemente il riquadro di delimitazione di ogni contorno e il gioco è fatto.

# 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 

Le scatole risultanti dal metodo di cui sopra avranno spazio intorno alle etichette, e questo può includere parte del disegno originale, se le scatole vengono applicate all'immagine originale. Per evitare ciò, cerca le regioni di interesse tramite le nuove caselle trovate e ritaglia lo spazio bianco. Quindi salva la forma di quel roi come nuova casella.

Forse non hai modo di sapere quante etichette saranno presenti nell'immagine. Se questo è il caso, allora mi raccomando di giocare con i valori di erosione finché non trovi quello migliore per soddisfare il tuo caso e ottenere i blob desiderati.

Oppure puoi provare a trovare contorni sul contenuto rimanente, dopo aver rimosso il disegno, e unire rettangoli di delimitazione in un rettangolo in base alla loro distanza l'uno dall'altro.

Dopo aver trovato le tue scatole, usa semplicemente quelle scatole rispetto all'immagine originale e sarai fatto.


Scene Detection Testo modulo in OpenCV 3

Come accennato nei commenti alla tua domanda, esiste già un mezzo di rilevamento di testo scena (non documentare rilevamento testo) in OpenCV 3. Capisco che fate non ho la possibilità di cambiare versione, ma per quelli con la stessa domanda e non limitati a una versione precedente di opencv, ho deciso di includerlo alla fine. La documentazione per il rilevamento del testo scena può essere trovata con una semplice ricerca su google.

Il modulo opencv per il rilevamento del testo viene fornito anche con il riconoscimento del testo che implementa tessaract, che è un modulo di riconoscimento del testo open source gratuito. La caduta di tessaract, e quindi il modulo di riconoscimento del testo di scena di opencv, è che non è raffinato come le applicazioni commerciali e richiede molto tempo. Riducendo così le sue prestazioni, ma è gratis da usare, quindi è il migliore che abbiamo ottenuto senza pagare soldi, se vuoi anche il riconoscimento del testo.

Links:

Onestamente, mancano di esperienza e competenze sia opencv e delle immagini al fine di fornire un modo dettagliato nell'attuazione il loro modulo di rilevamento del testo. Lo stesso con l'algoritmo SWT. Sono appena entrato in questa roba negli ultimi mesi, ma man mano che imparerò di più modificheremo questa risposta.

+1

Ho letto su questo e ci sono un paio di implementazioni su Python di SWT che potrebbero essere utili per te: [1] https://github.com/marrrcin/swt-python [2] https: // github.com/mypetyak/StrokeWidthTransform – m33n