Cómo eliminar líneas horizontales y verticales de una imagen

Tengo una imagen que es de un texto escrito en un papel de cuaderno espiral. El papel tiene líneas horizontales. Me gustaría quitar las líneas horizontales de la imagen.

Mientras buscaba en Google, encontré una solución que pensé que funcionaría: extraer líneas horizontales y verticales mediante operaciones morfológicas. La solución estaba en C ++, así que la convertí a Python. Funciona bien en la imagen de muestra proporcionada en esa solución, sin embargo, no parece funcionar para mis imágenes.

Mientras lo ejecuto en mi imagen obtengo estos resultados:

Imagen original

Imagen resultante

A continuación se muestra el código Python que traduje desde C ++

#cpp code converted from http://sofes.miximages.com/python/tutorial_moprh_lines_detection.html import cv2 import numpy as np img = cv2.imread(original.jpg") img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) img = cv2.bitwise_not(img) th2 = cv2.adaptiveThreshold(img,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,15,-2) cv2.imshow("th2", th2) cv2.imwrite("th2.jpg", th2) cv2.waitKey(0) cv2.destroyAllWindows() horizontal = th2 vertical = th2 rows,cols = horizontal.shape horizontalsize = cols / 30 horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontalsize,1)) horizontal = cv2.erode(horizontal, horizontalStructure, (-1, -1)) horizontal = cv2.dilate(horizontal, horizontalStructure, (-1, -1)) cv2.imshow("horizontal", horizontal) cv2.imwrite("horizontal.jpg", horizontal) cv2.waitKey(0) cv2.destroyAllWindows() verticalsize = rows / 30 verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize)) vertical = cv2.erode(vertical, verticalStructure, (-1, -1)) vertical = cv2.dilate(vertical, verticalStructure, (-1, -1)) cv2.imshow("vertical", vertical) cv2.imwrite("vertical.jpg", vertical) cv2.waitKey(0) cv2.destroyAllWindows() vertical = cv2.bitwise_not(vertical) cv2.imshow("vertical_bitwise_not", vertical) cv2.imwrite("vertical_bitwise_not.jpg", vertical) cv2.waitKey(0) cv2.destroyAllWindows() #step1 edges = cv2.adaptiveThreshold(vertical,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,-2) cv2.imshow("edges", edges) cv2.imwrite("edges.jpg", edges) cv2.waitKey(0) cv2.destroyAllWindows() #step2 kernel = np.ones((2, 2), dtype = "uint8") dilated = cv2.dilate(edges, kernel) cv2.imshow("dilated", dilated) cv2.imwrite("dilated.jpg", dilated) cv2.waitKey(0) cv2.destroyAllWindows() # step3 smooth = vertical.copy() #step 4 smooth = cv2.blur(smooth, (4,4)) cv2.imshow("smooth", smooth) cv2.imwrite("smooth.jpg", smooth) cv2.waitKey(0) cv2.destroyAllWindows() #step 5 (rows, cols) = np.where(img == 0) vertical[rows, cols] = smooth[rows, cols] cv2.imshow("vertical_final", vertical) cv2.imwrite("vertical_final.jpg", vertical) cv2.waitKey(0) cv2.destroyAllWindows() 

He intentado ImageMagik en mi imagen original también en un esfuerzo por eliminar líneas.

Obtengo mejores resultados con ImageMagik pero aún no soy completamente exacto.

 convert original -morphology close:3 "1x5: 0,1,1,1,0" original_im.jpg 

Su caso es menos trivial que el proporcionado en el tutorial en el que ha basado su solución. Con este enfoque, no podrá filtrar las líneas al 100%, debido al hecho de que las partes horizontales de los caracteres a veces se tratarán como líneas.

Depende de sus expectativas (que no ha especificado realmente) y, específicamente, de la precisión que espera, puede intentar encontrar los caracteres en lugar de encontrar la línea. Eso debería proporcionarte más robustez.

Con respecto a su código, al agregar algunas líneas de código justo después de encontrar líneas horizontales en la imagen (antes de verticalsize = rows / 30 líneas de código), puede obtener algunos resultados. He trabajado en una imagen de tamaño medio.

Resultado con horizontalsize = int (cols / 30)

Resultado con horizontalsize = int (cols / 15)

Nuevamente, estoy enfatizando que esos nunca serán precisos con ese enfoque en su caso. Aquí está el fragmento:

 #inverse the image, so that lines are black for masking horizontal_inv = cv2.bitwise_not(horizontal) #perform bitwise_and to mask the lines with provided mask masked_img = cv2.bitwise_and(img, img, mask=horizontal_inv) #reverse the image back to normal masked_img_inv = cv2.bitwise_not(masked_img) cv2.imshow("masked img", masked_img_inv) cv2.imwrite("result2.jpg", masked_img_inv) cv2.waitKey(0) cv2.destroyAllWindows() 

Intente jugar con horizontalsize si las imágenes que proporcioné son algo satisfactorias. También he usado la conversión int, ya que eso es lo que la función getStructuringElement espera: horizontalsize = int(cols / 30) .

También puedes probar un poco de suavizado y morfología en el resultado. Eso debería hacer que los personajes sean un poco más legibles.