Como identificar imagem dados do formulário (OpenCV e pyteressact)

 

  Em muitos casos, a nossa fonte de dados de muitas formas, por vezes dados (ou tabela) aparecerá na imagem. Então, como é que vamos chegar a imagem de dados úteis de TI? Quando uma imagem contém dados tabulares, podemos identificar a tabela com linha reta OpenCV, e depois usar a tecnologia OCR texto para identificá-los.
  Este artigo apenas como um exemplo de como identificar uma tabela na imagem, e espero dar aos leitores um pouco de inspiração. Eu usei as seguintes ferramentas:

  • opencv
  • pyteressact
  • numpy

Usamos opencv reconhecimento linha reta para a mesa, para identificar a célula com texto pyteressact, processamento numérico usado para fazer numpy. Queremos identificar a imagem da amostra (AI.png) como segue:

Exemplo imagem AI.png

Nós dividido nas seguintes etapas para identificar:

  1. Identificando a horizontal mesa, isto é ficha de divisão horizontal (cada linha);
  2. Identificando linha vertical na tabela, isto é, as linhas de divisão de cada coluna;
  3. Encontrar a célula onde os dados residem;
  4. reconhecimento de caracteres Pyteressact usando o celular.

A Tabela de identificação da linha horizontal

  Antes de identificar linha horizontal, criamos uma classe de formulário identificação de imagem (ImageTableOCR), como segue:

# -*- coding: utf-8 -*-
import cv2
import pytesseract
import numpy as np

class ImageTableOCR(object):

    # 初始化
    def __init__(self, ImagePath):
        # 读取图片
        self.image = cv2.imread(ImagePath, 1)
        # 把图片转换为灰度模式
        self.gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)

Onde self.image é o módulo de imagem RGB, self.gray para a imagem em tons de cinza.
  Em seguida, vamos identificar a linha horizontal imagem dividindo dois registros. É notado que, entre dois discos de cor adjacentes são inconsistentes, portanto, que o uso da imagem em tons de cinzento, o valor absoluto da diferença entre o valor médio para cada fila de pixels por linha divisória adjacentes dois registos, assim ele pode detectar uma divisão horizontal dos dois registros. função de código Python horizontal reconhecimento específico é a seguinte :( código de acesso acima)

    # 横向直线检测
    def HorizontalLineDetect(self):

        # 图像二值化
        ret, thresh1 = cv2.threshold(self.gray, 240, 255, cv2.THRESH_BINARY)
        # 进行两次中值滤波
        blur = cv2.medianBlur(thresh1, 3)  # 模板大小3*3
        blur = cv2.medianBlur(blur, 3)  # 模板大小3*3

        h, w = self.gray.shape

        # 横向直线列表
        horizontal_lines = []
        for i in range(h - 1):
            # 找到两条记录的分隔线段,以相邻两行的平均像素差大于120为标准
            if abs(np.mean(blur[i, :]) - np.mean(blur[i + 1, :])) > 120:
                # 在图像上绘制线段
                horizontal_lines.append([0, i, w, i])
                cv2.line(self.image, (0, i), (w, i), (0, 255, 0), 2)

        horizontal_lines = horizontal_lines[1:]
        # print(horizontal_lines)
        return horizontal_lines

Em primeiro lugar, o processo de transformação binária imagem, e, em seguida, o filtro de média é realizada duas vezes, de modo que o elemento de imagem é o de distinguir entre duas gravação adjacente tão grande quanto possível. Em seguida, a imagem de cada fila de pixels é detectado, uma diferença média dos pixels entre as duas fiadas adjacentes é maior que o padrão 120 reconhece que a gravação do divididas duas linhas horizontais. Depois de identificar linha verde horizontal abaixo da foto :()

Após a identificação de imagem horizontal

As linhas verticais identificam a mesa

  Neste passo, usamos Hough opencv detecção de linha em métodos para detectar linhas verticais na imagem. código Python da seguinte :( código de acesso completa acima)

    #  纵向直线检测
    def VerticalLineDetect(self):
        # Canny边缘检测
        edges = cv2.Canny(self.gray, 30, 240)

        # Hough直线检测
        minLineLength = 500
        maxLineGap = 30
        lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength, maxLineGap).tolist()
        lines.append([[13, 937, 13, 102]])
        lines.append([[756, 937, 756, 102]])
        sorted_lines = sorted(lines, key=lambda x: x[0])

        # 纵向直线列表
        vertical_lines = []
        for line in sorted_lines:
            for x1, y1, x2, y2 in line:
                # 在图片上绘制纵向直线
                if x1 == x2:
                    print(line)
                    vertical_lines.append((x1, y1, x2, y2))
                    cv2.line(self.image, (x1, y1), (x2, y2), (0, 0, 255), 2)

        return vertical_lines

Em primeiro lugar temos um espaçamento máximo de imagem em escala de cinzento de detecção de borda Canny de, e, em seguida, com base neste método utilizando um linear de detecção da linha de Hough no reconhecimento de imagem, identificado como 30 necessário, o comprimento mínimo da linha 500, e uma linha recta vertical (x1 == X2), é claro, existem alguns factores humanos, isto é, o próprio autor adicionada duas linhas rectas verticais ([[13, 937, 13, 102]], [[756, 937, 756, 102]]). O método de operação descrito acima, os resultados da saída são os seguintes:

[[13, 937, 13, 102]]
[[75, 937, 75, 102]]
[[77, 937, 77, 102]]
[[270, 937, 270, 104]]
[[272, 937, 272, 102]]
[[756, 937, 756, 102]]

reconhecimento de imagem como linha vertical vermelha após :( imagem)

Depois de identificar vertical da imagem

Você pode ver, a imagem seis segmentos verticais têm a tag completa.

imagem de identificação celular

  Em reconhecimento da imagem antes de as células, que primeiro identificar os vértices de cada célula situa-se, isto é, as linhas horizontais e verticais após o cruzamento de identificação. código Python da seguinte :( código de acesso completa acima)

    # 顶点检测
    def VertexDetect(self):
        vertical_lines = self.VerticalLineDetect()
        horizontal_lines = self.HorizontalLineDetect()

        # 顶点列表
        vertex = []
        for v_line in vertical_lines:
            for h_line in horizontal_lines:
                vertex.append((v_line[0], h_line[1]))

        #print(vertex)

        # 绘制顶点
        for point in vertex:
            cv2.circle(self.image, point, 1, (255, 0, 0), 2)

        return vertex

Depois de detectar a imagem, como um vértice :( pontos azuis é o vértice de cada célula da imagem)

Após a detecção de imagem de vértice

Assim, identificamos o ápice da célula está correta. Em seguida, vamos tirar essas células, como segue :( código de acesso acima)

# 寻找单元格区域
    def CellDetect(self):
        vertical_lines = self.VerticalLineDetect()
        horizontal_lines = self.HorizontalLineDetect()

        # 顶点列表
        rects = []
        for i in range(0, len(vertical_lines) - 1, 2):
            for j in range(len(horizontal_lines) - 1):
                rects.append((vertical_lines[i][0], horizontal_lines[j][1], \
                              vertical_lines[i + 1][0], horizontal_lines[j + 1][1]))

        # print(rects)
        return rects

Na primeira célula, por exemplo, uma imagem que é como se segue:

imagem primeira célula

texto de identificação celular

  Depois de identificar a célula na forma de imagens, podemos fazer o reconhecimento de caracteres imagem celular, ferramenta OCR que usamos para Teressact, sua interface Python para pyteressact. código Python detalhado como segue :( mais códigos de acesso)

# 识别单元格中的文字
    def OCR(self):
        rects = self.CellDetect()
        thresh = self.gray

        # 特殊字符列表
        special_char_list = ' `~!@#$%^&*()-_=+[]{}|\\;:‘’,。《》/?ˇ'
        for i in range(20):
            rect1 = rects[i]
            DetectImage1 = thresh[rect1[1]:rect1[3], rect1[0]:rect1[2]]

            # Tesseract所在的路径
            pytesseract.pytesseract.tesseract_cmd = 'C://Program Files (x86)/Tesseract-OCR/tesseract.exe'
            # 识别数字(每行第一列)
            text1 = pytesseract.image_to_string(DetectImage1, config="--psm 10")
            print(text1, end='-->')

            # 识别汉字(每行第二列)
            rect2 = rects[i+20]
            DetectImage2 = thresh[rect2[1]:rect2[3], rect2[0]:rect2[2]]
            text2 = pytesseract.image_to_string(DetectImage2, config='--psm 7', lang='chi_sim')
            text2 = ''.join([char for char in text2 if char not in special_char_list])
            print(text2, end='-->')

            # 识别汉字(每行第三列)
            rect3 = rects[i+40]
            DetectImage3 = thresh[rect3[1]:rect3[3], rect3[0]:rect3[2]]
            text3 = pytesseract.image_to_string(DetectImage3, config='--psm 7', lang='chi_sim')
            text3 = ''.join([char for char in text3 if char not in special_char_list])
            print(text3)

resultado do reconhecimento do seguinte:

I -> um grau -> pessoa aberta, uma plataforma de serviços inteligente
2 -> Muscle News -> serviço de Internet
3 -> rotulado -> pessoa de negócios, uma automação inteligente, peça inteligente Yi
4 -> Ali Baba -> serviço de Internet
5 -> set boca Ping -> financiar a investigação inteligente e desenvolvimento de ze T humanas
6 -> BGI -> detecção precisa, operadores de serviços de dados médicos
de d -> Sogou -> Geral humano T soluções inteligentes plataforma
8 -> a iFLYTEK -> tecnologia de fala inteligente
9 -> um lucro recorde na sopa -> tecnologia de plataforma de terminal inteligente
10 -> Jane Hill Group -> Marketing intelligence SaaS de nível plataforma de nuvem
i -> Shang Tecnologia -> AI profundidade visual plataforma de aprendizagem
12 -> Ultrapower -> produtos de software abrangentes e serviços
13 -> Cambrian-Technology -> estudo aprofundado sobre específica peça glenoid esperto
14 -> tecnologia Hanwang -> tecnologia de reconhecimento de caracteres e mão inteligente ao longo
de 15 -> tecnologia punição Chi -> design de chips inteligentes
16 -> exclusão rosto como a tecnologia -> produtos e T humanas solução da indústria inteligente programa Yi
17 -> Um pouco de tecnologia -> dados do cliente Smart Hub
18 -> dados Haiyun -> empresa grandes de análise de dados operações globais e
19 -> sombra tecnologia Wei -> tecnologia visual, imagem inteligente produtores
20 -> Chi inteligência dança -> plataforma robótica inteligente e forneceu Xiao

Abaixo, nós olhamos para a precisão estatística de reconhecimento. Na tabela original, num total de 20 dígitos mais 280 caracteres (incluindo pontuação) mais 10 letras do inglês (incluindo pontuação), os resultados de reconhecimento, em que numerais 17 identifica a classe correcta, as correctas 256 caracteres, Inglês 8 letras, portanto, a precisão geral de reconhecimento foi de 90,6%, o resultado do reconhecimento ainda é possível.

resumo

  Este artigo apenas como um exemplo de como identificar uma tabela na imagem, e espero dar aos leitores um pouco de inspiração. Por forma imagem diferente, requer uma análise específica sobre questões específicas.
  Apesar de eu escrever, tanto quanto possível todo o processo simples e direto, mas o processo de descoberta é muito complexa. Vale a pena notar que detectam linha horizontal neste artigo aplica-se apenas para gravar duas adjacentes tabelas fotos têm diferença de cor.
  Conclua o seguinte código Python, espero dar-lhe alguns pensamentos.

# -*- coding: utf-8 -*-
import cv2
import pytesseract
import numpy as np

class ImageTableOCR(object):

    # 初始化
    def __init__(self, ImagePath):
        # 读取图片
        self.image = cv2.imread(ImagePath, 1)
        # 把图片转换为灰度模式
        self.gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)

    # 横向直线检测
    def HorizontalLineDetect(self):

        # 图像二值化
        ret, thresh1 = cv2.threshold(self.gray, 240, 255, cv2.THRESH_BINARY)
        # 进行两次中值滤波
        blur = cv2.medianBlur(thresh1, 3)  # 模板大小3*3
        blur = cv2.medianBlur(blur, 3)  # 模板大小3*3

        h, w = self.gray.shape

        # 横向直线列表
        horizontal_lines = []
        for i in range(h - 1):
            # 找到两条记录的分隔线段,以相邻两行的平均像素差大于120为标准
            if abs(np.mean(blur[i, :]) - np.mean(blur[i + 1, :])) > 120:
                # 在图像上绘制线段
                horizontal_lines.append([0, i, w, i])
                # cv2.line(self.image, (0, i), (w, i), (0, 255, 0), 2)

        horizontal_lines = horizontal_lines[1:]
        # print(horizontal_lines)
        return horizontal_lines

    #  纵向直线检测
    def VerticalLineDetect(self):
        # Canny边缘检测
        edges = cv2.Canny(self.gray, 30, 240)

        # Hough直线检测
        minLineLength = 500
        maxLineGap = 30
        lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength, maxLineGap).tolist()
        lines.append([[13, 937, 13, 102]])
        lines.append([[756, 937, 756, 102]])
        sorted_lines = sorted(lines, key=lambda x: x[0])

        # 纵向直线列表
        vertical_lines = []
        for line in sorted_lines:
            for x1, y1, x2, y2 in line:
                # 在图片上绘制纵向直线
                if x1 == x2:
                    # print(line)
                    vertical_lines.append((x1, y1, x2, y2))
                    # cv2.line(self.image, (x1, y1), (x2, y2), (0, 0, 255), 2)

        return vertical_lines

    # 顶点检测
    def VertexDetect(self):
        vertical_lines = self.VerticalLineDetect()
        horizontal_lines = self.HorizontalLineDetect()

        # 顶点列表
        vertex = []
        for v_line in vertical_lines:
            for h_line in horizontal_lines:
                vertex.append((v_line[0], h_line[1]))

        #print(vertex)

        # 绘制顶点
        for point in vertex:
            cv2.circle(self.image, point, 1, (255, 0, 0), 2)

        return vertex

    # 寻找单元格区域
    def CellDetect(self):
        vertical_lines = self.VerticalLineDetect()
        horizontal_lines = self.HorizontalLineDetect()

        # 顶点列表
        rects = []
        for i in range(0, len(vertical_lines) - 1, 2):
            for j in range(len(horizontal_lines) - 1):
                rects.append((vertical_lines[i][0], horizontal_lines[j][1], \
                              vertical_lines[i + 1][0], horizontal_lines[j + 1][1]))

        # print(rects)
        return rects

    # 识别单元格中的文字
    def OCR(self):
        rects = self.CellDetect()
        thresh = self.gray

        # 特殊字符列表
        special_char_list = ' `~!@#$%^&*()-_=+[]{}|\\;:‘’,。《》/?ˇ'
        for i in range(20):
            rect1 = rects[i]
            DetectImage1 = thresh[rect1[1]:rect1[3], rect1[0]:rect1[2]]

            # Tesseract所在的路径
            pytesseract.pytesseract.tesseract_cmd = 'C://Program Files (x86)/Tesseract-OCR/tesseract.exe'
            # 识别数字(每行第一列)
            text1 = pytesseract.image_to_string(DetectImage1, config="--psm 10")
            print(text1, end='-->')

            # 识别汉字(每行第二列)
            rect2 = rects[i+20]
            DetectImage2 = thresh[rect2[1]:rect2[3], rect2[0]:rect2[2]]
            text2 = pytesseract.image_to_string(DetectImage2, config='--psm 7', lang='chi_sim')
            text2 = ''.join([char for char in text2 if char not in special_char_list])
            print(text2, end='-->')

            # 识别汉字(每行第三列)
            rect3 = rects[i+40]
            DetectImage3 = thresh[rect3[1]:rect3[3], rect3[0]:rect3[2]]
            text3 = pytesseract.image_to_string(DetectImage3, config='--psm 7', lang='chi_sim')
            text3 = ''.join([char for char in text3 if char not in special_char_list])
            print(text3)

    # 显示图像
    def ShowImage(self):
        cv2.imshow('AI', self.image)
        cv2.waitKey(0)
        # cv2.imwrite('E://Horizontal.png', self.image)

ImagePath = 'E://AI.png'
imageOCR = ImageTableOCR(ImagePath)
imageOCR.OCR()

Nota: Eu já abriu número público micro-canal: rastreadores e algoritmos (Micro Signal como: easy_web_scrape) Python, bem-vindo a atenção Oh ~ ~

Publicado 86 artigos originais · Louvor obteve 267 · Visualizações 1,77 milhão +

Acho que você gosta

Origin blog.csdn.net/javastart/article/details/105338424
Recomendado
Clasificación