Desenvolvimento - Visual Studio
OCR em Aplicações Universais: extraindo texto de imagens
Neste artigo veremos como utilizar a API de OCR (Optical Character Recognition) do Windows 10 para extrair texto de imagens.
por Joel RodriguesA técnica de OCR (Optical Character Recognition) consiste no reconhecimento de textos a partir de imagens, ou seja, a extração de informação textual a partir de um elemento onde não há distinção bem definida entre imagens e caracteres alfanuméricos (letras, números e pontuação, dependendo do idioma).
O ORC possui aplicações práticas em diversas áreas e tipos, mas em geral, busca automatizar a identificação de textos sem que haja a necessidade de interação direta do usuário final nesta etapa. Na maior parte dos casos, a intenção é facilitar o trabalho do cliente ou mesmo realizar tarefas que se mostram "humanamente inviáveis".
Algumas aplicações conhecidas para esse procedimento são:
- Reconhecimento de placas de veículos a partir de fotos capturadas por mecanismos automatizados de controle;
- Extração de texto de documentos digitalizados e fotos.
Na plataforma Windows/Windows Phone já era possível utilizar esse recurso desde a versão 8.1 ao baixar o pacote Microsoft.Windows.Ocr via Nuget. No Windows 10 essa ferramenta foi evoluída e está disponível por padrão na forma de uma API da plataforma universal, com suporte a 25 idiomas e processamento totalmente local. Assim, não há necessidade de conexão com a internet para que o reconhecimento de texto funcione.
Windows.Media.Ocr
As funcionalidades que precisamos para aplicar a OCR em projetos UWP estão contidas, basicamente, no namespace Windows.Media.Ocr, que contém as seguintes classes:
- OcrEngine: principal classe da biblioteca e contém as funções que definem o idioma e que realizam o reconhecimento propriamente dito;
- OcrResult: essa classe representa o resultado de uma operação de reconhecimento. Ao ser invocado, o método RecognizeAsync da classe OcrEngine retorna um objeto desse tipo;
- OcrLine: representa cada linha do texto obtido pelo método RecognizeAsync da classe OcrEngine. Um objeto OcrResult pode conter um ou mais objetos do tipo OcrLine;
- OcrWord: representa cada palavra de cada linha do texto obtido. Um objeto OcrLine possui uma coleção de objetos do tipo OcrWord.
Exemplo prático
No exemplo que desenvolveremos agora faremos o reconhecimento do texto em duas imagens, com conteúdo em inglês e português. As imagens, que podem ser vistas nas Figuras 1 e 2, contém texto em e composições posições diferentes.
Figura 1. Imagem com texto em português
Figura 2. Imagem com texto em inglês
O primeiro passo será criar um novo projeto do tipo Universal Windows usando o template Blank App no Visual Studio. Em seguida, devemos adicionar as imagens que serão processadas clicando com o botão direito do mouse sobre o projeto e utilizando a opção Add &gr; Existing item. Em seguida, devemos alterar a propriedade Copy to Output Directory das duas imagens para Copy if Newer, assim copiará os arquivos para o pacote gerado.
Vale ressaltar que aqui utilizaremos as imagens embutidas no pacote da aplicação, no entanto, pode-se capturar imagens da câmera ou mesmo solicitar que o usuário selecione uma de sua biblioteca, por exemplo.
Feito isso, adicionaremos na MainPage.xaml apenas um botão para realizar o processamento e um TextBlock para receber o texto obtido. O código adicionado a essa página pode ser visto na Listagem 1.
Listagem 1. Código XAML da MainPage
<StackPanel> <Button Content="Reconhecer texto" Name="btnReconhecer" Click="btnReconhecer_Click"/> <TextBlock Name="txtTexto" HorizontalAlignment="Stretch" TextWrapping="Wrap"/> </StackPanel>
Agora podemos realizar o processamento, bastando para isso acionar o evento Click do botão e no event handler gerado adicionar o código da Listagem 2.
Listagem 2. Reconhecendo o texto da imagem
private async void btnReconhecer_Click(object sender, RoutedEventArgs e) { OcrEngine ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages(); var file = await Package.Current.InstalledLocation.GetFileAsync("imgPortugues.jpg"); using (var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read)) { var decoder = await BitmapDecoder.CreateAsync(stream); var bitmap = await decoder.GetSoftwareBitmapAsync(); OcrResult result = await ocrEngine.RecognizeAsync(bitmap); txtTexto.Text = result.Text; } }
Aqui nos interessam principalmente as linhas onde criamos a OcrEngine com base nos idiomas suportados no ambiente em que a aplicação está rodando, e aquela em que extraímos o texto da imagem, obtendo um OcrResult.
O resultado dessa operação para as duas imagens pode ser visto na Figura 3. É importante observar que apesar de em alguns casos o reconhecimento não ser perfeito, está muito perto disso.
Figura 3. Resultado do reconhecimento do texto
No próximo exemplo adicionaremos um ListBox na MainPage, ao qual chamaremos aqui de listResultado e adicionaremos as linhas do texto separadamente.
Na Listagem 3 temos o texto que deve substituir a linha da Listagem 2 onde atribuímos o texto obtido ao TextBlock.
Listagem 3. Lendo as linhas do texto obtido
foreach(var line in result.Lines) { listResultado.Items.Add(line.Text); }
Na Figura 4 temos o resultado obtido ao processar as duas imagens novamente, agora com cada linha adicionada como um item do ListBox.
Figura 4. Linhas do texto obtido
Por fim, podemos ver na Listagem 4 como recuperar as palavras de cada linha separadamente, adicionando-as como um novo item do ListBox. O resultado é visto na Figura 5.
Listagem 4. Obtendo as palavras de cada linha separadamente
foreach(var line in result.Lines) { foreach(var word in line.Words) { listResultado.Items.Add(word.Text); } }
Figura 5. Palavras obtidas do texto separadamente
A classe OcrWord possui ainda a propriedade BoudingRect, que contém a posição e dimensões do retângulo onde a palavra se encontra na imagem. Também é possível definir um idioma específico ao processar o texto. Para isso, deve-se utilizar a função TryCreateFromLanguage ao criar a OcrEngine e indicar o idioma desejado.
Veja que são várias as aplicações possíveis para essa técnica e a API do Windows simplifica sua utilização em projetos UWP, bastando obter a imagem a partir de alguma fonte e processá-la para obter o texto desejado.
- Contando usuário em tempo realVisual Studio
- ListBox - Visual StudioVisual Studio
- ResolveURLVisual Studio
- Resgatando Imagens Dinamicamente usando ASP.NET MVC e C#Visual Studio
- Solution Explorer poderoso: Novidades do Visual Studio 2011 Visual Studio