Reputation: 745
Let's say I have an image like this:
For which I want to remove the border and get this:
So exactly the same image, without the border.
I found a "hacky" way to do it which finds the outer contour and draws a line over it... To be honest it's not the best way because I need to adjust the "thickness" of the line so that it is thick enough to cover up the border, but not too thick so it doesn't cover any of the circles.
The image
variable is the image you see above (already grayscaled, thresholded).
cnts = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
cv2.drawContours(image, cnts, -1, 0, 15) # 15 is the right thickness for this image, but might not be for other ones...
The results is the 2nd picture above. Works great, but it doesn't work for ALL images (because of different thickness). Is there a better way to do this?
Upvotes: 1
Views: 17676
Reputation: 92
Here I am considering you had done all the image processing and others. The recommended threshold (cv2.THRESH_OTSU)!
mask = np.zeros(img.shape, dtype=img.dtype)
cont = cv2.findContours(img_th, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cont = cont[0] if len(cont) == 2 else cont[1]
for c in cont:
area = cv2.contourArea(c)
if area < 500:
cv2.drawContours(mask, [c], -1, (255, 255, 255), -1)
print(mask.shape)
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY) # making it to 2D (removing the channel value)
removed_border = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow("result", removed_border)
cv2.waitKey()
cv2.destroyAllWindows()
If you have any problem with understanding the code please let me know. I m happy to help you out and if you like the answer please thumps up!!! :)
Result:
Upvotes: 3
Reputation: 207345
This is what I meant in the comments... fill everything that is black like the top-left corner, and connected to it, with white so that the bit you want is now entirely surrounded by white all the way to the edges. Then fill everything that is white and connected to the top-left corner with black.
#!/usr/local/bin/python3
import numpy as np
import cv2
from PIL import Image
# Load image and greyscale it
im = np.array(Image.open("framedcircles.jpg").convert('L'))
# Normalize and threshold image
im = cv2.normalize(im, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
res, im = cv2.threshold(im, 64, 255, cv2.THRESH_BINARY)
# Fill everything that is the same colour (black) as top-left corner with white
cv2.floodFill(im, None, (0,0), 255)
# Fill everything that is the same colour (white) as top-left corner with black
cv2.floodFill(im, None, (0,0), 0)
# Save result
Image.fromarray(im).save("result.png")
Result:
Upvotes: 6
Reputation: 178
I have a little hack for this. If you're falling low on thickness, repeat the process. Again, it's not the best way to do it, but it should work.
Upvotes: 0