Home > Enterprise >  Is it possible to translate this OpenCV into Pillow?
Is it possible to translate this OpenCV into Pillow?

Time:03-28

I was wondering if I can translate this opencv-python method into Pillow as I am forced furtherly to process it in Pillow.

A workaround I thought about would be to just save it with OpenCV and load it after with Pillow but I am looking for a cleaner solution, because I am using the remove_background() method's output as input for each frame of a GIF. Thus, I will read and write images N * GIF_frames_count times for no reason.

The method I want to convert from Pillow to opencv-python:

def remove_background(path):
    img = cv2.imread(path)

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

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

    # Negate mask
    mask = 255 - mask

    # Apply morphology to remove isolated extraneous noise
    # Use border constant of black since foreground touches the edges
    kernel = np.ones((3, 3), np.uint8)
    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

    # Anti-alias the mask -- blur then stretch
    # Blur alpha channel
    mask = cv2.GaussianBlur(mask, (0, 0), sigmaX=2, sigmaY=2, borderType=cv2.BORDER_DEFAULT)

    # Linear stretch so that 127.5 goes to 0, but 255 stays 255
    mask = (2 * (mask.astype(np.float32)) - 255.0).clip(0, 255).astype(np.uint8)

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

    return result

Code taken from: how to remove background of images in python

CodePudding user response:

Rather than re-writing all the code using PIL equivalents, you could adopt the "if it ain't broke, don't fix it" maxim, and simply convert the Numpy array that the existing code produces into a PIL Image that you can use for your subsequent purposes.

That is this described in this answer, which I'll paraphrase as:

# Make "PIL Image" from Numpy array
pi = Image.fromarray(na)

Note that the linked answer refers to scikit-image (which uses RGB ordering like PIL) rather than OpenCV, so there is the added wrinkle that you will also need to reorder the channels from BGRA to RGBA, so the last couple of lines will look like:

...
...
result = cv2.cvtColor(result, cv2.COLOR_BGR2RGBA)
result[:, :, 3] = mask
pi = Image.fromarray(result)
  • Related