1

Let's say I have an image like this:

enter image description here

For which I want to remove the border and get this:

enter image description here

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?

3
  • 1
    Floodfill with white starting at any corner. Trim all white pixels. Commented Aug 20, 2018 at 14:58
  • Sorry, I'm a complete noob in OpenCV, could you elaborate? Commented Aug 20, 2018 at 15:03
  • 2
    Call cv2.floodFill() on your image with 0,0 as the seed point and a fill value of white to fill all the black, edge pixels with white. Then call it again, but with a fill value of black, to make all white pixels touching the corner black. Commented Aug 20, 2018 at 15:09

3 Answers 3

6

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:

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

By the way, consider saving your images as PNG when doing image processing because JPEGs will change values in your file. You may threshold an image to pure black (0) and white (255) and save as JPEG and when you reopen it you will find 8s and 240s and all sorts of unexpected rubbish.
or do a threshold to make sure you get pure black and white if it is not possible to save it as png
this works better for me than the accepted answer, thanks!
3

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!!! :)

With border

Result:

Removed border and keep original format

Comments

0

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.

1 Comment

Didn't think about that... but it works fine! :) I just drew a fine black line of thickness 1 on each iteration until the border is gone. Thanks for the suggestion!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.