Leitores como você ajudam a apoiar o MUO. Quando você faz uma compra usando links em nosso site, podemos ganhar uma comissão de afiliado. Consulte Mais informação.

Você pode querer digitalizar um documento para economizar espaço físico ou criar um backup salvo. De qualquer forma, escrever um programa que pode converter fotos de seus arquivos em papel em um formato padrão é uma tarefa em que o Python se destaca.

Usando uma combinação de bibliotecas apropriadas, você pode criar um pequeno aplicativo para digitalizar documentos. Seu programa pegará uma imagem de um documento físico como entrada, aplicará várias técnicas de processamento de imagem a ela e produzirá uma versão digitalizada da entrada.

Preparando seu ambiente

Para acompanhar este artigo você deve estar familiarizado com o noções básicas de Python. Você também precisa ter uma compreensão como trabalhar com a biblioteca NumPy Python.

Abra qualquer IDE Python e crie dois arquivos Python. Nomeie um main.py e o outro transform.py. Em seguida, execute o seguinte comando no terminal para instalar as bibliotecas necessárias.

instagram viewer
pip instalar OpenCV-Python imutils scikit-image NumPy

Você usará o OpenCV-Python para obter a entrada da imagem e executar algum processamento de imagem. Imutils para redimensionar as imagens de entrada e saída. scikit-image para aplicar um limite na imagem. NumPy irá ajudá-lo a trabalhar com matrizes.

Aguarde a instalação terminar e o IDE atualizar os esqueletos do projeto. Depois que a atualização dos esqueletos estiver concluída, você estará pronto para começar a codificar. O código-fonte completo está disponível em um Repositório GitHub.

Importando as bibliotecas instaladas

Abra o arquivo main.py e importe as bibliotecas que você instalou no ambiente. Isso permitirá que você chame e use suas funções quando necessário.

importar cv2
importar imutils
de skimage.filters importar limiar_local
de transformar importar perspective_transform

Ignore o erro lançado em perspective_transform. Ele desaparecerá quando você terminar de trabalhar no arquivo transform.py.

Tomando e redimensionando a entrada

Tire uma imagem nítida do documento que deseja digitalizar. Certifique-se de que os quatro cantos do documento e seu conteúdo estejam visíveis. Copie a imagem para a mesma pasta em que você está armazenando os arquivos do programa.

Passe o caminho da imagem de entrada para o OpenCV. Faça uma cópia da imagem original conforme necessário durante a transformação de perspectiva. Divida a altura da imagem original pela altura para a qual deseja redimensioná-la. Isso manterá a proporção. Por fim, imprima a imagem redimensionada.

# Passando o caminho da imagem
original_img = cv2.imread('amostra.jpg')
copiar = original_img.copy()

# A altura redimensionada em centenas
proporção = original_img.shape[0] / 500.0
img_resize = imutils.resize (original_img, altura=500)

# Exibindo a saída
cv2.imshow('Imagem redimensionada', img_resize)

# Esperando o usuário pressionar qualquer tecla
cv2.waitKey(0)

A saída do código acima é a seguinte:

Agora você redimensionou a altura da imagem original para 500 pixels.

Convertendo a imagem redimensionada para tons de cinza

Converta a imagem RGB redimensionada em tons de cinza. A maioria das bibliotecas de processamento de imagem só funciona com imagens em tons de cinza, pois são mais fáceis de processar.

gray_image = cv2.cvtColor (img_resize, cv2.COLOR_BGR2GRAY)
cv2.imshow('Imagem acinzentada', gray_image)
cv2.waitKey(0)

Observe a diferença entre a imagem original e a cinza.

A mesa colorida virou preto e branco.

Aplicando um detector de borda

Aplique um filtro de desfoque gaussiano na imagem acinzentada para remover o ruído. Em seguida, chame a função astuta do OpenCV para detectar as bordas presentes na imagem.

blurred_image = cv2.GaussianBlur (gray_image, (5, 5), 0)
edged_img = cv2.Canny (blurred_image, 75, 200)
cv2.imshow('Bordas da imagem', edged_img)
cv2.waitKey(0)

As arestas são visíveis na saída.

As bordas com as quais você trabalhará são as do documento.

Encontrando o maior contorno

Detecte os contornos presentes na imagem com bordas. Classifique-os em ordem decrescente mantendo apenas os cinco maiores contornos. Aproxime o maior contorno com quatro lados percorrendo os contornos classificados.

cnts, _ = cv2.findContours (edged_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = classificado (cnts, chave=cv2.contourArea, reverse=Verdadeiro)[:5]

para c em cnts:
peri = cv2.arcLength (c, Verdadeiro)
aprox = cv2.approxPolyDP(c, 0.02 *peri, Verdadeiro)

se len (aprox) == 4:
doc = aprox
quebrar

O contorno com quatro lados provavelmente conterá o documento.

Circulando os quatro cantos do contorno do documento

Circule os cantos do contorno do documento detectado. Isso o ajudará a determinar se o seu programa foi capaz de detectar o documento na imagem.

p = []

para d em documento:
ponto_tupla = tupla (d[0])
cv2.circle (img_resize, tuple_point, 3, (0, 0, 255), 4)
p.append (tuple_point)

cv2.imshow('Pontos de canto circulados', img_resize)
cv2.waitKey(0)

Implemente a circulação na imagem RGB redimensionada.

Tendo detectado o documento, agora você precisa extrair o documento da imagem.

Usando Warp Perspective para obter a imagem desejada

A perspectiva de distorção é uma técnica de visão computacional para transformar uma imagem para corrigir distorções. Ele transforma uma imagem em um plano diferente, permitindo que você visualize a imagem de um ângulo diferente.

warped_image = perspective_transform (cópia, doc.reshape(4, 2) * razão)
warped_image = cv2.cvtColor (warped_image, cv2.COLOR_BGR2GRAY)
cv2.imshow("Imagem distorcida", imutils.resize (warped_image, height=650))
cv2.waitKey(0)

Para obter uma imagem distorcida, você precisa criar um módulo simples que executará a transformação de perspectiva.

Módulo de Transformação

O módulo ordenará os pontos dos cantos do documento. Ele também transformará a imagem do documento em um plano diferente e alterará o ângulo da câmera para uma tomada aérea.

Abra o arquivo transform.py que você criou anteriormente. Importe bibliotecas OpenCV e NumPy.

importar entorpecido como np
importar cv2

Este módulo conterá duas funções. Crie uma função que irá ordenar as coordenadas dos pontos de canto do documento. A primeira coordenada será a do canto superior esquerdo, a segunda será a do canto superior direito, a terceira será do canto inferior direito, e a quarta coordenada será a do canto inferior esquerdo canto.

defpontos_pedido(pontos):
# inicializando a lista de coordenadas a serem ordenadas
rect = np.zeros((4, 2), dtipo = "flutuar32")

s = pts.soma (eixo = 1)

# ponto superior esquerdo terá a menor soma
rect[0] = pts[np.argmin (s)]

# ponto inferior direito terá a maior soma
rect[2] = pts[np.argmax (s)]

calculando a diferença entre os pontos, o
ponto superior direito terá a menor diferença,
enquanto o canto inferior esquerdo terá a maior diferença
diff = np.diff (pts, axis = 1)
rect[1] = pts[np.argmin (diff)]
rect[3] = pts[np.argmax (diff)]

# retorna as coordenadas ordenadas
retornar retificar

Crie uma segunda função que calculará as coordenadas de canto da nova imagem e obterá uma tomada aérea. Em seguida, ele calculará a matriz de transformação de perspectiva e retornará a imagem distorcida.

defperspective_transform(imagem, pontos):
# desempacote as coordenadas solicitadas individualmente
rect = order_points (pts)
(tl, tr, br, bl) = ret

calcular a largura da nova imagem, que será a
distância máxima entre o canto inferior direito e inferior esquerdo
coordenadas x ou o canto superior direito e coordenadas x superior esquerda
larguraA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
larguraB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
maxWidth = max (int (larguraA), int (larguraB))

calcular a altura da nova imagem, que será a
distância máxima entre o canto superior esquerdo e coordenadas y inferior esquerda
alturaA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
alturaB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
maxHeight = max (int (alturaA), int (alturaB))

construir o conjunto de pontos de destino para obter um tiro aéreo
dst = np.array([
[0, 0],
[largura máxima - 1, 0],
[largura máxima - 1, altura máxima - 1],
[0, altura máxima - 1]], dtipo = "flutuar32")

# calcula a matriz de transformação de perspectiva
transform_matrix = cv2.getPerspectiveTransform (rect, dst)

# Aplique a matriz de transformação
warped = cv2.warpPerspective (image, transform_matrix, (maxWidth, maxHeight))

# retorna a imagem distorcida
retornar deformado

Agora você criou o módulo de transformação. O erro na importação de perspective_transform agora desaparecerá.

Observe que a imagem exibida tem uma tomada aérea.

Aplicando o Limite Adaptável e Salvando a Saída Digitalizada

No arquivo main.py, aplique o limite gaussiano à imagem distorcida. Isso dará à imagem distorcida uma aparência digitalizada. Salve a saída da imagem digitalizada na pasta que contém os arquivos do programa.

T = threshold_local (warped_image, 11, deslocamento=10, método="gaussiano")
warped = (warped_image > T).astype("uint8") * 255
cv2.imwrite('./'+'Varredura'+'.png', deformado)

Salvar a digitalização no formato PNG mantém a qualidade do documento.

Exibindo a Saída

Saída da imagem do documento digitalizado:

cv2.imshow("Imagem digitalizada final", imutils.resize (empenado, altura=650))
cv2.waitKey(0)
cv2.destroyAllWindows()

A imagem a seguir mostra a saída do programa, uma tomada aérea do documento digitalizado.

Como Avançar na Visão Computacional

A criação de um scanner de documentos abrange algumas áreas centrais da visão computacional, que é um campo amplo e complexo. Para avançar na visão computacional, você deve trabalhar em projetos interessantes, mas desafiadores.

Você também deve ler mais sobre como usar a visão computacional com as tecnologias atuais. Isso irá mantê-lo informado e dar-lhe novas ideias de projetos para trabalhar.