reconocimiento de formularios python-opencv

Recientemente aprendí sobre opencv e hice una pequeña cosa simple, que es reconocer la tabla en la imagen, y luego escribir los datos en el csv y guardarlos después de que se complete el reconocimiento.

Preparación ambiental:

Primero hablemos sobre qué entorno debemos preparar:
1. la instalación de Python está completa (autor python3.7)
2. tesseract (el marco de trabajo de código abierto de Google)
3. pytesseract (encapsulación de Python de tesseract, la llamada es a través de pytesseract para llamar tesseract)
4. Algunas bibliotecas de python, numpy, matplotlib
5. Una mención especial es importar el paquete opencv, el nombre es opencv-python cuando se instala y el nombre es cv2 cuando se usa
Cv2 no significa que sea la versión dos de opencv. Significa que se ha mejorado y optimizado en base a cv, y no tiene nada que ver con la versión.
Hay una cosa más a tener en cuenta aquí. Si usa cv2 para informar un error, es posible que deba instalar opencv-python-headless.

Pasos de identificación:

Primero hablemos brevemente sobre el principio, ¿cómo reconoces la mesa? Este es el caso. Si utilizamos tesseract directamente para reconocer una imagen como chino, contará las líneas horizontales y verticales de la tabla.
Muchos caracteres chinos no se pueden reconocer y el efecto es feo. Entonces, el paso previo que debemos hacer es identificar las celdas de la imagen de Excel, identificar la información en cada celda y luego unirla
en un csv, y finalmente convertirlo a Excel, solo es necesario importar los datos csv a través de Excel. Eso es.

Nota: Mi nivel es limitado y solo puedo trabajar con formas relativamente simples y cuadradas. Los siguientes procedimientos se pueden ejecutar directamente. Sin embargo, si hay algunas formas de imagen que se toman de forma oblicua, o hay interferencias,
como un bolígrafo en la imagen, o una marca de agua muy complicada, esto no se puede manejar en la actualidad y aún se está estudiando. Los amigos interesados ​​pueden jugar juntos, agregar un WeChat para discutir e intercambiar.

Sin embargo, también tenemos algunas soluciones para estas situaciones, que aún se están procesando:
1. Si la tabla está inclinada, podemos usar la transformación de transmisión para procesar primero la tabla en un rectángulo normal;
2. Para una marca de agua simple, puede seleccionar una después de pasar la escala de grises. Con un umbral razonable, después de binarizar la imagen, la marca de agua se puede eliminar de las imágenes en blanco y negro.

Aquí hay un buen tutorial introductorio para python-opencv: dirección github

Vale, se acabó la tontería, empieza el tutorial:
imagen original:

1. Lea en la imagen en escala de grises:

Puede entenderse como cambiar una imagen en color a una imagen gris.

raw = cv2.imread(src, 1)
# 灰度图片
gray = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)

2. Binarización de imágenes:

Se puede entender que la imagen se vuelve solo en blanco y negro en dos colores, lo que es más conveniente de procesar. Además, no necesitamos color al procesar tablas.

binary = cv2.adaptiveThreshold(~gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 35, -5)
# 展示图片
cv2.imshow("binary_picture", binary)

Imagen binaria:

3. Identificar líneas horizontales y verticales:

Después de eso, si la imagen no es lo suficientemente clara o hay píxeles pequeños, puede usar operaciones como corrosión y expansión para hacer la imagen más clara

rows, cols = binary.shape
scale = 40
# 自适应获取核值
# 识别横线:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (cols // scale, 1))
eroded = cv2.erode(binary, kernel, iterations=1)
dilated_col = cv2.dilate(eroded, kernel, iterations=1)
cv2.imshow("excel_horizontal_line", dilated_col)

# 识别竖线:
scale = 20
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, rows // scale))
eroded = cv2.erode(binary, kernel, iterations=1)
dilated_row = cv2.dilate(eroded, kernel, iterations=1)
cv2.imshow("excel_vertical_line:", dilated_row)

Diagrama de líneas horizontales y verticales:

4. Calcule el foco de las líneas horizontales y verticales y obtenga las coordenadas de cada celda.

# 将识别出来的横竖线合起来
bitwise_and = cv2.bitwise_and(dilated_col, dilated_row)
cv2.imshow("excel_bitwise_and", bitwise_and)

# 标识表格轮廓
merge = cv2.add(dilated_col, dilated_row)
cv2.imshow("entire_excel_contour:", merge)

# 两张图片进行减法运算,去掉表格框线
merge2 = cv2.subtract(binary, merge)
cv2.imshow("binary_sub_excel_rect", merge2)

new_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
erode_image = cv2.morphologyEx(merge2, cv2.MORPH_OPEN, new_kernel)
cv2.imshow('erode_image2', erode_image)
merge3 = cv2.add(erode_image, bitwise_and)
cv2.imshow('merge3', merge3)

# 将焦点标识取出来
ys, xs = np.where(bitwise_and > 0)

Mapa de enfoque:

5. Filtre las coordenadas y cuente las vecinas como una:

Hablemos de que la matriz de imágenes es (y, x) así, y está al frente

# 横纵坐标数组
y_point_arr = []
x_point_arr = []
# 通过排序,排除掉相近的像素点,只取相近值的最后一点
# 这个10就是两个像素点的距离,不是固定的,根据不同的图片会有调整,基本上为单元格表格的高度(y坐标跳变)和长度(x坐标跳变)
i = 0
sort_x_point = np.sort(xs)
for i in range(len(sort_x_point) - 1):
    if sort_x_point[i + 1] - sort_x_point[i] > 10:
        x_point_arr.append(sort_x_point[i])
    i = i + 1
# 要将最后一个点加入
x_point_arr.append(sort_x_point[i])

i = 0
sort_y_point = np.sort(ys)
# print(np.sort(ys))
for i in range(len(sort_y_point) - 1):
    if (sort_y_point[i + 1] - sort_y_point[i] > 10):
        y_point_arr.append(sort_y_point[i])
    i = i + 1
y_point_arr.append(sort_y_point[i])

6. Saque la imagen de cada celda por coordenadas y luego use pytesseract para reconocer el texto: después de eliminar los símbolos especiales, los datos son el valor procesado

# 循环y坐标,x坐标分割表格
data = [[] for i in range(len(y_point_arr))]
for i in range(len(y_point_arr) - 1):
    for j in range(len(x_point_arr) - 1):
        # 在分割时,第一个参数为y坐标,第二个参数为x坐标
        cell = src[y_point_arr[i]:y_point_arr[i + 1], x_point_arr[j]:x_point_arr[j + 1]]
        cv2.imshow("sub_pic" + str(i) + str(j), cell)

        # 读取文字,此为默认英文
        # pytesseract.pytesseract.tesseract_cmd = 'E:/Tesseract-OCR/tesseract.exe'
        text1 = pytesseract.image_to_string(cell, lang="chi_sim+eng")

        # 去除特殊字符
        text1 = re.findall(r'[^\*"/:?\\|<>″′‖ 〈\n]', text1, re.S)
        text1 = "".join(text1)
        print('单元格图片信息:' + text1)
        data[i].append(text1)
        j = j + 1
    i = i + 1

6. Finalmente escriba toda la información en csv

ruta es la ruta del archivo a escribir, los datos son los datos

with open(path, "w", newline='') as csv_file:
      writer = csv.writer(file, dialect='excel')
      for index, item in enumerate(data):
          if index != 0 and index != len(data) - 1:
              writer.writerows([[item[0], item[1], item[2], item[3], item[4], item[5]]])

Escribir datos de la tabla:

para resumir:

1. Después de la finalización, conozco aproximadamente el principio de reconocimiento de formularios y tengo cierta comprensión y familiaridad con la API de opencv, aquí está la dirección de github: dirección del proyecto , creo que puede hacer clic en estrella, bifurcación, etc.
2. Pero esta introducción es sobre el proceso general. De hecho, todavía hay muchos pozos en el proceso. Ejecutar directamente el proyecto github puede producir resultados diferentes al mío.
Eso es porque uno es para descargar el conjunto de datos chino de tesseract. La segunda es que no se reconocen las matemáticas y algunas palabras de este, y
algunos conjuntos de entrenamiento deben agregarse a tesseract manualmente . Este mayor conjunto de datos de entrenamiento debería tener otro artículo más adelante.
3. Después de finalizar el reconocimiento de formularios, prepárese para mirar la imagen para corregir y eliminar la marca de agua También se utilizará el reconocimiento de formularios complejos.

Materiales de referencia:

1.https: //github.com/tesseract-ocr/tesseract
2.https: //pypi.org/project/pytesseract/
3.https: //blog.csdn.net/muxiong0308/article/details/80969355
4. https://www.cnblogs.com/HL-space/p/10547259.html

Supongo que te gusta

Origin blog.csdn.net/sc9018181134/article/details/104577247
Recomendado
Clasificación