Как кадрировать изображение на основе пользовательской маски в python? - PullRequest
0 голосов
/ 09 июля 2020

Ниже я прикрепил два изображения. Я хочу, чтобы первое изображение было обрезано в форме сердца в соответствии с изображением маски (2-е изображение).

Я искал решения, но мне не удалось найти простой и легкий способ сделать это. Пожалуйста, помогите мне с решением.

2 изображения:

  1. Изображение для обрезки: enter image description here

  2. Mask image:

введите описание изображения здесь

Ответы [ 2 ]

2 голосов
/ 09 июля 2020

Начнем с загрузки изображения храма из sklearn:

from sklearn.datasets import load_sample_images

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

enter image description here

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')

enter image description here

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)

enter image description here

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)

введите описание изображения здесь

0 голосов
/ 09 июля 2020

Так как я нахожусь на удаленном сервере, cv2.imshow у меня не работает. Я импортировал plt.

Этот код делает то, что вы ищете:

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)
...