【问题标题】:How do I crop an image based on custom mask in python?如何在 python 中根据自定义蒙版裁剪图像?
【发布时间】:2020-10-29 23:18:12
【问题描述】:

下面我附上了两张图片。我希望根据蒙版图像(第二张图像)将第一张图像裁剪成心形。

我搜索了解决方案,但无法找到简单易行的方法。请帮助我解决问题。

2 张图片:

  1. 要裁剪的图像:

  2. 面具图片:

【问题讨论】:

  • 请不要使用“裁剪”。裁剪意味着您正在裁剪图像中的矩形区域。您实际上的意思是 masking

标签: python image opencv python-imaging-library processing


【解决方案1】:

让我们从sklearn加载temple图像开始:

from sklearn.datasets import load_sample_images

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

由于我们需要使用第二张图像作为掩码,我们必须进行二元阈值操作。这将创建一个黑白蒙版图像,然后我们可以使用它来蒙版以前的图像。

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)

我们现在可以修剪图像,使其尺寸与 temple 图像兼容:

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

现在我们必须对想要遮罩的图像进行切片,以适应实际遮罩的尺寸。另一种形状是调整蒙版的大小,这是可行的,但我们最终会得到一个扭曲的心脏图像。要应用面具,我们有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)

如果您想让蒙版(黑色)区域透明:

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】:

因为我在远程服务器上,所以 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)

【讨论】:

  • 您可以将for 循环替换为cv2.bitwise_and(img_mask, img_org)。迭代每个像素是昂贵的。
猜你喜欢
  • 2021-10-02
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 2015-11-04
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多