Removing horizontal lines in an image (OpenCV, Python, Matplotlib)

Using the following code, I can remove the horizontal lines in the images. See the result below.

import cv2 from matplotlib import pyplot as plt img = cv2.imread('image.png',0) laplacian = cv2.Laplacian(img,cv2.CV_64F) sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5) plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray') plt.title('Original'), plt.xticks([]), plt.yticks([]) plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray') plt.title('Laplacian'), plt.xticks([]), plt.yticks([]) plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray') plt.title('Sobel X'), plt.xticks([]), plt.yticks([]) plt.show() 

result

The result is pretty good, not perfect, but good. What I want to achieve is what has been shown here . I am using this code .

Original Image .. source

One of my questions: how to save Sobel X without applying a gray effect? Like the original, but crafted ..

Also, is there a better way to do this?

EDIT

Using the following code for the source image is good. It works pretty well.

 import cv2 import numpy as np img = cv2.imread("image.png") 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 #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() horizontalsize = int(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 = int(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() 

result

But if I have this image?

example

I tried to execute the above code and the result is really bad ...

result3

Other images I'm working on are ...

enter image description here

enter image description here

enter image description here

+8
source share
1 answer

Here is the approach

  • Convert grayscale image
  • Otsu Threshold
  • Create a special horizontal core for detecting horizontal lines
  • Find mask contours
  • Restore image

After converting to grayscale, we count the threshold for a binary image.

enter image description here

 image = cv2.imread('1.png') gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] 

Next, we create a special horizontal core for detecting horizontal lines. We draw these lines on the mask, and then find the contours on the mask. To remove the lines, we fill the paths with white

Detected lines

enter image description here

Mask

enter image description here

Filled in the contours

enter image description here

 # Remove horizontal horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1)) detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(image, [c], -1, (255,255,255), 2) 

Image currently has spaces. To fix this, we create a vertical core for image recovery.

enter image description here

 # Repair image repair_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,6)) result = 255 - cv2.morphologyEx(255 - image, cv2.MORPH_CLOSE, repair_kernel, iterations=1) 

Please note that depending on the image, the kernel size will vary. For example, to detect longer strings, we could use the kernel (50,1) instead. If we wanted to get thicker lines, we could increase the second parameter to say (50,2) .

Here are the results with other images

Detected lines

Original (left), deleted (right)


Detected lines

Original (left), deleted (right)

Full code

 import cv2 image = cv2.imread('1.png') gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] # Remove horizontal horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1)) detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(image, [c], -1, (255,255,255), 2) # Repair image repair_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,6)) result = 255 - cv2.morphologyEx(255 - image, cv2.MORPH_CLOSE, repair_kernel, iterations=1) cv2.imshow('thresh', thresh) cv2.imshow('detected_lines', detected_lines) cv2.imshow('image', image) cv2.imshow('result', result) cv2.waitKey() 
+2
source

Source: https://habr.com/ru/post/1264719/


All Articles