I am trying to clear out the grids so that I can use the plot alone in a different process. I am trying to solve it using opencv. I have both actual and inverted image. I am not expert in python. Any help could be great.
Thanks in advance
Actual image
inverted image
You can use the opening or closing of your image (depending if you are using the normal or inverted image). Opening will first erode your image and then dilate it. This will remove small/thin objects assuming bright objects over black background.
For example, in the case of your inverted image, use
out = cv2.morphologyEx(src, MORPH_OPEN)
For more information check out this tutorial
Here's an approach that uses a combination of filtering techniques and masks.
Here's the result
import cv2
import numpy as np
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 15)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,3)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
erode = cv2.erode(thresh, kernel, iterations=1)
dilate = cv2.dilate(erode, kernel, iterations=3)
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
mask = np.zeros(image.shape, dtype=np.uint8)
for c in cnts:
area = cv2.contourArea(c)
if area > 850:
cv2.drawContours(mask, [c], -1, (255,255,255), -1)
mask = cv2.dilate(mask, kernel, iterations=1)
image = 255 - image
result = 255 - cv2.bitwise_and(mask, image)
cv2.imshow('result', result)
cv2.waitKey(0)
2nd Approach
Here's an alternative approach which is the same as the 1st approach but uses specialized horizontal and vertical kernels for filtering instead. This approach is probably more robust. Instead of using guess and check morphological transformations, we have dedicated kernels that filter out the horizontal/vertical grid lines.
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,5))
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,1))
Here's the mask result after going through each kernel
The result is pretty much the same but slightly cleaner :)
import cv2
import numpy as np
image = cv2.imread('1.png',0)
blur = cv2.GaussianBlur(image, (5,5), 0)
thresh = cv2.threshold(blur, 130, 255, cv2.THRESH_BINARY_INV)[1]
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,5))
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,1))
remove_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel)
remove_vertical = cv2.morphologyEx(remove_horizontal, cv2.MORPH_OPEN, horizontal_kernel)
cnts = cv2.findContours(remove_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
mask = np.ones(image.shape, dtype=np.uint8)
for c in cnts:
area = cv2.contourArea(c)
if area > 50:
cv2.drawContours(mask, [c], -1, (255,255,255), -1)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
mask = cv2.dilate(mask, kernel, iterations=1)
image = 255 - image
result = 255 - cv2.bitwise_and(mask, image)
cv2.imshow('result', result)
cv2.imwrite('result.png', result)
cv2.imshow('mask', mask)
cv2.waitKey(0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With