How do I crop an image based on custom mask in python?

こ雲淡風輕ζ 提交于 2020-07-31 04:20:04

问题


Below I have attached two images. I want the first image to be cropped in a heart shape according to the mask image (2nd image).

I searched for solutions but I was not able to get the simple and easier way to do this. Kindly help me with the solution.

2 images:

  1. Image to be cropped:

  2. Mask image:


回答1:


Let's start by loading the temple image from sklearn:

from sklearn.datasets import load_sample_images

dataset = load_sample_images()     
temple = dataset.images[0]
plt.imshow(temple)

Since, we need to use the second image as mask, we must do a binary thresholding operation. This will create a black and white masked image, which we can then use to mask the former image.

from matplotlib.pyplot import imread

heart = imread(r'path_to_im\heart.jpg', cv2.IMREAD_GRAYSCALE)
_, mask = cv2.threshold(heart, thresh=180, maxval=255, type=cv2.THRESH_BINARY)

We can now trim the image so its dimensions are compatible with the temple image:

temple_x, temple_y, _ = temple.shape
heart_x, heart_y = mask.shape

x_heart = min(temple_x, heart_x)
x_half_heart = mask.shape[0]//2

heart_mask = mask[x_half_heart-x_heart//2 : x_half_heart+x_heart//2+1, :temple_y]
plt.imshow(heart_mask, cmap='Greys_r')

Now we have to slice the image that we want to mask, to fit the dimensions of the actual mask. Another shape would have been to resize the mask, which is doable, but we'd then end up with a distorted heart image. To apply the mask, we have cv2.bitwise_and:

temple_width_half = temple.shape[1]//2
temple_to_mask = temple[:,temple_width_half-x_half_heart:temple_width_half+x_half_heart]
masked = cv2.bitwise_and(temple_to_mask,temple_to_mask,mask = heart_mask)
plt.imshow(masked)

If you want to instead make the masked (black) region transparent:

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)

plt.axis('off')
plt.imshow(dst)




回答2:


Since I am on a remote server, cv2.imshow doesnt work for me. I imported plt.

This code does what you are looking for:

import cv2
import matplotlib.pyplot as plt

img_org = cv2.imread('~/temple.jpg')
img_mask = cv2.imread('~/heart.jpg')
##Resizing images
img_org = cv2.resize(img_org, (400,400), interpolation = cv2.INTER_AREA)
img_mask = cv2.resize(img_mask, (400,400), interpolation = cv2.INTER_AREA)

for h in range(len(img_mask)):
    for w in range(len(img_mask)):
        if img_mask[h][w][0] == 0:
            for i in range(3):
                img_org[h][w][i] = 0
        else:
            continue
            
plt.imshow(img_org)


来源:https://stackoverflow.com/questions/62813546/how-do-i-crop-an-image-based-on-custom-mask-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!