Aqui está ainda uma solução alternativa para o seu problema, modelando sua pergunta como um 'problema de otimização de caminho'. Embora seja mais complicado do que a solução simples de montagem de binarização e curva, é mais robusta na prática.
Do nível muito alto, devemos considerar esta imagem como um gráfico, onde
cada pixel da imagem é um nó neste gráfico
cada nó está conectado a outros nós, conhecidos como vizinhos, e essa definição de conexão é frequentemente referida como a topologia deste gráfico.
cada nó tem um peso (recurso, custo, energia ou o que você quiser chamar), refletindo a probabilidade de que esse nó esteja em uma linha central ideal que estamos procurando.
Desde que possamos modelar essa probabilidade, seu problema de encontrar 'as linhas centrais das franjas' passa a ser o problema para encontrar caminhos ótimos locais no gráfico , que podem ser efetivamente resolvidos pela programação dinâmica, por exemplo, o algoritmo Viterbi.
Aqui estão alguns profissionais da adoção dessa abordagem:
todos os seus resultados serão contínuos (diferente do método do limite que pode quebrar uma linha central em pedaços)
muitas liberdades para construir esse gráfico, você pode selecionar diferentes recursos e topologia de gráfico.
seus resultados são ótimos no sentido de otimizações de caminho
sua solução será mais robusta contra o ruído, porque, enquanto o ruído estiver igualmente distribuído entre todos os pixels, esses caminhos ideais permanecerão estáveis.
Aqui está uma breve demonstração da idéia acima. Como não uso nenhum conhecimento prévio para especificar quais são os possíveis nós iniciais e finais, simplesmente decodifico wrt todos os nós iniciais possíveis.
Para as terminações difusas, isso é causado pelo fato de estarmos procurando caminhos ideais para todos os nós finais possíveis. Como resultado, embora para alguns nós localizados em áreas escuras, o caminho destacado ainda seja o ideal local.
Para o caminho difuso, você pode suavizá-lo após encontrá-lo ou usar alguns recursos suavizados em vez da intensidade bruta.
É possível restaurar caminhos parciais alterando os nós inicial e final.
Não será difícil remover esses caminhos ótimos locais indesejados. Como temos a probabilidade de todos os caminhos após a decodificação de viterbi, e você pode usar vários conhecimentos anteriores (por exemplo, vemos que é verdade que precisamos apenas de um caminho ideal para aqueles que compartilham a mesma fonte).
Para mais detalhes, consulte o 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.
Aqui está um pequeno pedaço de código python usando para fazer o gráfico acima.
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 ) );