How to use image masking to crop around a complex image?

Hi all,

I am attempting to crop around the image of this car below to acquire a transparent background:

image 1

Using an approach developed in here I have been able to acquire a silhouette of the car as shown below:

image 2

Using the following script I try to create a mask by turning the greyscale silhouette into a binary silhouette, which can be overlayed upon the original.

import matplotlib.pyplot as plt
from matplotlib.pyplot import imread
import cv2
import numpy as np
from PIL import Image

#aml is the original image
#aml2 is the outline of the foreground object in the image
#both images are of dim (4500,3000)

aml = imread(r'dir\AML.jpg')
aml2 = imread(r'dir\AML.png', 0)

aml2_gray=cv2.cvtColor(aml2,cv2.COLOR_BGR2GRAY) #aml2 to grayscale
_, outline = cv2.threshold(aml2_gray, thresh=0, maxval=255, type=cv2.THRESH_BINARY) #creating mask from aml2

plt.imshow(outline, cmap='Greys_r') #output of the mask
outline = outline.astype(np.uint8)

masked = cv2.bitwise_and(aml,aml,mask = outline) #overlaying the mask onto original image <--This is where the error occurs

tmp = cv2.cvtColor(masked, cv2.COLOR_BGR2GRAY)
_,alpha = cv2.threshold(tmp,0,255,cv2.THRESH_BINARY)
b, g, r = cv2.split(masked)
rgba = [b,g,r, alpha]
masked_tr = cv2.merge(rgba,4)


This yields the following results:

image 3
image 4

I am trying to mimic the exact shape presented in the silhouette, however, my code creates a mask that is not precise enough.
Adjusting the threshold value above 0 yields a completely black image as the result.

I feel like I am close to achieving the desired result however, the binary mask requires fine-tuning, this is something I’m confused about and I’m not too sure where to start with.

I would appreciate some support with this, thank you.

(I have linked relevant images as comments)

1 Like

image 1
image 2

image 3
image 4

that’s too extreme. use 128 or something anywhere near the middle of the value range.

import cv2

aml = cv2.imread('d:/test/1.jpg')
aml2 = cv2.imread('d:/test/AML.png', 0)
aml=cv2.cvtColor(aml, cv2.COLOR_BGR2BGRA)
cv2.insertChannel(src=aml2, dst=aml, coi=3);
1 Like

I seem to have made a mess of these replies, my apologies

Thank you for this solution it works very well.