Saltar al contenido

Eliminar líneas no rectas de la imagen de texto

Recuerda que en la informática un problema casi siempre tiene más de una soluciones, no obstante mostraremos lo más óptimo y mejor.

Solución:

Los métodos típicos para eliminar líneas son usar núcleos horizontales/verticales o cv2.HoughLinesP() pero estos métodos solo funcionan si las líneas son rectas. En este caso, las líneas no son rectas, por lo que una idea es utilizar un núcleo diagonal, transformaciones morfológicas y filtrado de contornos para eliminar las líneas del texto. Usaré el enfoque de una respuesta anterior que se encuentra en la eliminación de líneas horizontales en una imagen pero con un núcleo diagonal


Comenzamos convirtiendo la imagen a escala de grises y realizamos el umbral de Otsu para obtener una imagen binaria. A continuación, creamos un núcleo diagonal y luego realizamos una transformación cercana para detectar/filtrar las líneas diagonales. Ya que cv2.getStructuringElement() no tiene ningún kernel diagonal incorporado, creamos el nuestro propio

# Read in image, grayscale, and Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Create diagonal kernel
kernel = np.array([[0, 0, 1],
                   [0, 1, 0],
                   [1, 0, 0]], dtype=np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)

La imagen aisló las principales líneas diagonales pero también incluyó pequeñas líneas del texto. Para eliminarlos buscamos contornos y filtramos usando área de contorno. Si el contorno pasa nuestro filtro, eliminamos efectivamente el ruido “rellenando” el contorno con cv2.drawContours(). Esto nos deja con nuestras líneas diagonales deseadas para eliminar

# Find contours and filter using contour area to remove noise
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < 500:
        cv2.drawContours(opening, [c], -1, (0,0,0), -1)

A partir de aquí simplemente cv2.bitwise_xor() con la imagen original para obtener nuestro resultado

# Bitwise-xor with original image
opening = cv2.merge([opening, opening, opening])
result = cv2.bitwise_xor(image, opening)

Notas: Es difícil eliminar las líneas sin afectar el texto, aunque es posible y necesitará algunos trucos inteligentes para "reparar" el texto. Eche un vistazo a eliminar los bordes de la imagen pero mantenga el texto escrito en los bordes para obtener un método para reconstruir el texto que falta. Otro método para aislar las líneas diagonales sería adoptar un enfoque contrario; en lugar de tratar de detectar líneas de diagnóstico, ¿por qué no intentar determinar qué no es una línea de diagnóstico? Probablemente podría hacer esto mediante técnicas de filtrado simples. Para crear núcleos diagonales dinámicos, puede usar np.diag() para diferentes anchos de línea diagonal

Código completo para completar

import cv2
import numpy as np

# Read in image, grayscale, and Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Create diagonal kernel
kernel = np.array([[0, 0, 1],
                   [0, 1, 0],
                   [1, 0, 0]], dtype=np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)

# Find contours and filter using contour area to remove noise
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < 500:
        cv2.drawContours(opening, [c], -1, (0,0,0), -1)

# Bitwise-xor with original image
opening = cv2.merge([opening, opening, opening])
result = cv2.bitwise_xor(image, opening)

cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('result', result)
cv2.waitKey()

Si para ti ha sido útil nuestro post, sería de mucha ayuda si lo compartieras con otros seniors así nos ayudas a dar difusión a este contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *