Ecco ancora una soluzione alternativa al tuo problema modellando la tua domanda come un "problema di ottimizzazione del percorso". Sebbene sia più complicato della semplice soluzione di binarizzazione e adattamento della curva, in pratica è più robusto.
Da un livello molto alto, dovremmo considerare questa immagine come un grafico, dove
ogni pixel dell'immagine è un nodo su questo grafico
ciascun nodo è collegato ad alcuni altri nodi, noti come vicini, e questa definizione di connessione viene spesso definita come la topologia di questo grafico.
ogni nodo ha un peso (caratteristica, costo, energia o come vuoi chiamarlo), riflettendo la probabilità che questo nodo si trovi in una linea centrale ottimale che stiamo cercando.
Finché possiamo modellare questa probabilità, allora il tuo problema di trovare "le linee centrali delle frange" diventa il problema di trovare percorsi ottimali locali sul grafico , che possono essere risolti efficacemente con la programmazione dinamica, ad esempio l'algoritmo di Viterbi.
Ecco alcuni pro dell'adozione di questo approccio:
tutti i risultati saranno continui (a differenza del metodo della soglia che potrebbe spezzare una linea centrale in pezzi)
molte libertà per costruire un tale grafico, è possibile selezionare diverse funzionalità e topologia del grafico.
i tuoi risultati sono ottimali nel senso di ottimizzazioni del percorso
la tua soluzione sarà più robusta contro il rumore, perché finché il rumore è equamente distribuito tra tutti i pixel, quei percorsi ottimali rimangono stabili.
Ecco una breve dimostrazione dell'idea sopra. Dato che non utilizzo alcuna conoscenza precedente per specificare quali sono possibili nodi di inizio e di fine, decodifico semplicemente ogni nodo iniziale possibile.
Per i finali fuzzy, è causato dal fatto che stiamo cercando percorsi ottimali per ogni possibile nodo finale. Di conseguenza, sebbene per alcuni nodi situati in aree scure, il percorso evidenziato sia comunque quello ottimale locale.
Per il percorso sfocato, è possibile attenuarlo dopo averlo trovato o utilizzare alcune funzioni uniformi anziché l'intensità non elaborata.
È possibile ripristinare percorsi parziali modificando i nodi iniziale e finale.
Non sarà difficile potare questi percorsi ottimali locali indesiderati. Perché abbiamo le probabilità di tutti i percorsi dopo la decodifica del viterbi e puoi usare varie conoscenze precedenti (ad esempio, vediamo che è vero che abbiamo bisogno di un solo percorso ottimale per coloro che condividono la stessa fonte.)
Per maggiori dettagli, puoi fare riferimento al documento.
Wu, Y.; Zha, S.; Cao, H.; Liu, D., & Natarajan, P. (2014, February). A Markov Chain Line Segmentation Method for Text Recognition. In IS&T/SPIE 26th Annual Symposium on Electronic Imaging (DRR), pp. 90210C-90210C.
Ecco un breve pezzo di codice Python che usa per creare il grafico sopra.
import cv2
import numpy as np
from matplotlib import pyplot
# define your image path
image_path = ;
# read in an image
img = cv2.imread( image_path, 0 );
rgb = cv2.imread( image_path, -1 );
# some feature to reflect how likely a node is in an optimal path
img = cv2.equalizeHist( img ); # equalization
img = img - img.mean(); # substract DC
img_pmax = img.max(); # get brightest intensity
img_nmin = img.min(); # get darkest intensity
# express our preknowledge
img[ img > 0 ] *= +1.0 / img_pmax;
img[ img = 1 :
prev_idx = vt_path[ -1 ].astype('int');
vt_path.append( path_buffer[ prev_idx, time ] );
time -= 1;
vt_path.reverse();
vt_path = np.asarray( vt_path ).T;
# plot found optimal paths for every 7 of them
pyplot.imshow( rgb, 'jet' ),
for row in range( 0, h, 7 ) :
pyplot.hold(True), pyplot.plot( vt_path[row,:], c=np.random.rand(3,1), lw = 2 );
pyplot.xlim( ( 0, w ) );
pyplot.ylim( ( h, 0 ) );