Estou tentando encontrar as caixas delimitadoras de texto em uma imagem e atualmente estou usando esta abordagem:
// calculate the local variances of the grayscale image
Mat t_mean, t_mean_2;
Mat grayF;
outImg_gray.convertTo(grayF, CV_32F);
int winSize = 35;
blur(grayF, t_mean, cv::Size(winSize,winSize));
blur(grayF.mul(grayF), t_mean_2, cv::Size(winSize,winSize));
Mat varMat = t_mean_2 - t_mean.mul(t_mean);
varMat.convertTo(varMat, CV_8U);
// threshold the high variance regions
Mat varMatRegions = varMat > 100;
Quando recebe uma imagem como esta:
Então, quando eu mostro varMatRegions
, recebo esta imagem:
Como você pode ver, combina um pouco o bloco de texto esquerdo com o cabeçalho do cartão, para a maioria dos cartões esse método funciona muito bem, mas em cartões mais ocupados, pode causar problemas.
A razão pela qual é ruim conectar esses contornos é que faz com que a caixa delimitadora do contorno ocupe quase todo o cartão.
Alguém pode sugerir uma maneira diferente de encontrar o texto para garantir a detecção adequada do texto?
200 pontos para quem encontrar o texto no cartão acima dos dois.
c++
opencv
image-processing
text
bounding-box
Grampo
fonte
fonte
Respostas:
Você pode detectar texto localizando elementos de borda estreita (inspirados em um LPD):
Uso:
Resultados:
uma. elemento = getStructuringElement (cv :: MORPH_RECT, cv :: Size (17, 3));
b. elemento = getStructuringElement (cv :: MORPH_RECT, cv :: Size (30, 30));
Os resultados são semelhantes para a outra imagem mencionada.
fonte
n
? Obrigado pela solução que funciona muito bem!cv::Rect a;
. Ampliado por n:a.x-=n/2;a.y-=n/2;a.width+=n;a.height+=n;
.Eu usei um método baseado em gradiente no programa abaixo. Adicionadas as imagens resultantes. Observe que estou usando uma versão reduzida da imagem para processamento.
versão c ++
versão python
fonte
rect
. Há umpyrdown
, então multiplicamx, y, width, height
darect
por 4.Aqui está uma abordagem alternativa que eu usei para detectar os blocos de texto:
Abaixo está o código escrito em python com pyopencv; deve ser fácil portar para C ++.
A imagem original é a primeira imagem em sua postagem.
Após o pré-processamento (escala de cinza, limiar e dilatação - portanto, após a etapa 3), a imagem ficou assim:
Abaixo está a imagem resultante ("contoured.jpg" na última linha); as caixas delimitadoras finais dos objetos na imagem ficam assim:
Você pode ver o bloco de texto à esquerda ser detectado como um bloco separado, delimitado de seus arredores.
Usando o mesmo script com os mesmos parâmetros (exceto para o tipo de limiar que foi alterado para a segunda imagem como descrito abaixo), aqui estão os resultados para os outros 2 cartões:
Ajustando os Parâmetros
Os parâmetros (valor limite, parâmetros de dilatação) foram otimizados para esta imagem e para esta tarefa (localização de blocos de texto) e podem ser ajustados, se necessário, para outras imagens de cartões ou outros tipos de objetos a serem encontrados.
Para limiar (etapa 2), usei um limite preto. Para imagens em que o texto é mais claro que o plano de fundo, como a segunda imagem em sua postagem, um limite de branco deve ser usado; portanto, substitua o tipo de limite por
cv2.THRESH_BINARY
). Para a segunda imagem, também usei um valor ligeiramente mais alto para o limiar (180). A variação dos parâmetros para o valor limite e o número de iterações para dilatação resultará em diferentes graus de sensibilidade na delimitação de objetos na imagem.Localizando outros tipos de objetos:
Por exemplo, diminuir a dilatação para 5 iterações na primeira imagem nos fornece uma delimitação mais fina dos objetos na imagem, localizando aproximadamente todas as palavras na imagem (em vez de blocos de texto):
Conhecendo o tamanho aproximado de uma palavra, descartei aqui áreas muito pequenas (abaixo de 20 pixels de largura ou altura) ou muito grandes (acima de 100 pixels de largura ou altura) para ignorar objetos que provavelmente não são palavras, para obter os resultados em a imagem acima.
fonte
cv2.findContours
. DizValueError: too many values to unpack
.cv2.findContours
retorna 3 argumentos, e as capturas de código originais única 2.A abordagem do @ dhanushka mostrou a maior promessa, mas eu queria brincar em Python, então fui em frente e traduzi-o por diversão:
Agora, para exibir a imagem:
Não é o mais Python dos scripts, mas tentei lembrar o código C ++ original o mais próximo possível dos leitores.
Funciona quase tão bem quanto o original. Ficarei feliz em ler as sugestões de como ele pode ser melhorado / corrigido para se parecer com os resultados originais.
fonte
drawContours
esse estado "A função desenha contornos de contorno na imagem se espessura> 0 ou preenche a área delimitada pelos contornos se espessura <0". Isso é feito para que possamos verificar a proporção de pixels diferentes de zero para decidir se a caixa provavelmente contém texto.Você pode tentar esse método desenvolvido por Chucai Yi e Yingli Tian.
Eles também compartilham um software (que é baseado no Opencv-1.0 e deve ser executado na plataforma Windows.) Que você pode usar (embora não haja código fonte disponível). Ele irá gerar todas as caixas delimitadoras de texto (mostradas em sombras de cores) na imagem. Ao aplicar às imagens de amostra, você obterá os seguintes resultados:
Nota: para tornar o resultado mais robusto, você pode mesclar ainda mais as caixas adjacentes.
Atualização: se seu objetivo final é reconhecer os textos na imagem, você pode conferir o gttext , que é um software livre de OCR e a ferramenta Ground Truthing para imagens coloridas com texto. O código fonte também está disponível.
Com isso, você pode obter textos reconhecidos como:
fonte
Código acima da versão JAVA: Obrigado @William
E use este código na prática:
fonte
Implementação Python para a solução da @ dhanushka:
fonte
Esta é uma versão em C # da resposta de dhanushka usando OpenCVSharp
fonte
esta é uma versão VB.NET da resposta de dhanushka usando o EmguCV .
Algumas funções e estruturas no EmguCV precisam de consideração diferente da versão C # do OpenCVSharp
fonte