How to Crop the Black Background of the Image Using Opencv in Python

How do I crop the black background of the image using OpenCV in Python?

Applying a simple threshold should get rid of the background, provided it's always darker than the foreground. If you use the Otsu thresholding algorithm, it should choose a good partition for you. Using your example as input, this gives:

Otsu Thresholded image

Next you could compute the bounding box to select the region of the foreground. Provided the background is distinct enough and there are no holes, this gives you the resulting rect:

[619 x 96 from (0, 113)]

You can then use this rect to crop the original, to produce the desired result:

Cropped original

I wrote the code to solve this in C++. A rough translation into Python would look something like this:

import cv2 as cv

img = cv.imread(sys.argv[1])

grayscale = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

thresholded = cv.threshold(grayscale, 0, 255, cv.THRESH_OTSU)

imwrite("otsu.png", thresholded)

bbox = cv.boundingRect(thresholded)

x, y, w, h = bbox

print(bbox)

foreground = img[y:y+h, x:x+w]

imwrite("foreground.png", foreground)

This method is fast and simple. If you find you have some white holes in your background which enlarge the bounding box, try applying an erosion operator.

FWIW I very much doubt you would get results like this as predictably or reliably using NNs.

Crop black edges with OpenCV

I am not sure whether all your images are like this. But for this image, below is a simple python-opencv code to crop it.

first import libraries :

import cv2
import numpy as np

Read the image, convert it into grayscale, and make in binary image for threshold value of 1.

img = cv2.imread('sofwin.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_,thresh = cv2.threshold(gray,1,255,cv2.THRESH_BINARY)

Now find contours in it. There will be only one object, so find bounding rectangle for it.

contours,hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
x,y,w,h = cv2.boundingRect(cnt)

Now crop the image, and save it into another file.

crop = img[y:y+h,x:x+w]
cv2.imwrite('sofwinres.png',crop)

Below is the result :

enter image description here

Removing black background/black stray straight lines from an image in python

As an ad-hoc solution, we may use cv2.floodFill 4 times - one at each corner:

img = cv.imread(file_path, 0)

rows, cols = img.shape

cv.floodFill(img, None, seedPoint=(0, 0), newVal=255, loDiff=1, upDiff=1) # Fill the top left corner.
cv.floodFill(img, None, seedPoint=(cols-1, 0), newVal=255, loDiff=1, upDiff=1) # Fill the top right corner.
cv.floodFill(img, None, seedPoint=(0, rows-1), newVal=255, loDiff=1, upDiff=1) # Fill the bottop left corner.
cv.floodFill(img, None, seedPoint=(cols-1, rows-1), newVal=255, loDiff=1, upDiff=1) # Fill the bottom right corner.

Result after cv.medianBlur:

Sample Image

How to crop image based on the object radius using OpenCV?

Here is the processing in Python/OpenCV for your new image.

Input:

Sample Image

import cv2
import numpy as np

# load image as grayscale
img = cv2.imread('Diabetic-Retinopathy_G_RM_151064169.jpg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold input image
mask = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)[1]

# optional morphology to clean up small spots
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

# put mask into alpha channel of image
result = np.dstack((img, mask))

# save resulting masked image
cv2.imwrite('Diabetic-Retinopathy_G_RM_151064169_masked.png', result)

# display result, though it won't show transparency
cv2.imshow("mask", mask)
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result

Cropping out black borders in image

You cannot crop out corners of an image. But you can turn them transparent. You can convert the image to grayscale, threshold those areas to black and the rest to white and use that as a mask. Put the mask into the alpha channel and the corners will be transparent. Here is an example using Python/OpenCV.

Input:

enter image description here

import cv2
import numpy as np

# load image as grayscale
img = cv2.imread('retina.jpeg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold input image using otsu thresholding as mask and refine with morphology
ret, mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((9,9), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

# put mask into alpha channel of image
result = img.copy()
result = cv2.cvtColor(result, cv2.COLOR_BGR2BGRA)
result[:, :, 3] = mask

# save resulting masked image
cv2.imwrite('retina_masked.png', result)

# display result, though it won't show transparency
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()



enter image description here

Python OpenCV: Crop image to contents, and make background transparent

Here is one way to do that in Python/OpenCV.

As I mentioned in my comment, your provided image has a white circle around the cow and then a transparent background. I have made the background fully white as my input.

Input:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('cow.png')

# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# invert gray image
gray = 255 - gray

# threshold
thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]

# apply close and open morphology to fill tiny black and white holes and save as mask
kernel = np.ones((3,3), np.uint8)
mask = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

# get contours (presumably just one around the nonzero pixels)
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
cntr = contours[0]
x,y,w,h = cv2.boundingRect(cntr)

# make background transparent by placing the mask into the alpha channel
new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
new_img[:, :, 3] = mask

# then crop it to bounding rectangle
crop = new_img[y:y+h, x:x+w]

# save cropped image
cv2.imwrite('cow_thresh.png',thresh)
cv2.imwrite('cow_mask.png',mask)
cv2.imwrite('cow_transparent_cropped.png',crop)

# show the images
cv2.imshow("THRESH", thresh)
cv2.imshow("MASK", mask)
cv2.imshow("CROP", crop)
cv2.waitKey(0)
cv2.destroyAllWindows()



Thresholded image:

enter image description here

Mask:

enter image description here

Cropped result with transparent background:

enter image description here



Related Topics



Leave a reply



Submit