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:
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:
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 :
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
:
How to crop image based on the object radius using OpenCV?
Here is the processing in Python/OpenCV for your new image.
Input:
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:
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()
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:
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:
Mask:
Cropped result with transparent background:
Related Topics
How to Cleanly Uninstall Ansible
How to Split an Integer into an Array of Digits
Tkinter Ttk Treeview How to Set Fixed Width Why It Change With Number of Column
How to Avoid Last Comma in Python Loop
Python: Pickle.Load() Raising Eoferror
Python: How to Calculate the Sum of Numbers from a File
How to Iterate Through Cur.Fetchall() in Python
How to Convert Signed to Unsigned Integer in Python
Convert HTML String to an Image in Python
Changing Presence Discord Status
Cannot Convert the Series to <Class 'Int''>
Read CSV from Google Cloud Storage to Pandas Dataframe
Python | Make the Percentage of a List
How to Convert .Dat to .Csv Using Python
Accuracy Score Valueerror: Can't Handle Mix of Binary and Continuous Target