NumPy/OpenCV 2:如何裁剪非矩形区域?

45
我有一组点,可以形成一个“形状”(闭合折线)。现在我想复制/裁剪从某个图像“内部这个形状”中的所有像素,同时使其余部分为黑色/透明。如何实现?
例如,我有这个: enter image description here 我想得到这个: enter image description here

1
我相信您想要处理一个不规则的兴趣区域(ROI)。您可以从这里开始:https://dev59.com/i2PVa4cB1Zd3GeqP-fBj - w-m
仅供参考:此问题不是重复的,因为所提到的问题描述的是C API而不是Python(尽管那个问题仍然有帮助)。 - ffriend
2个回答

68

*编辑-已更新,使其适用于具有Alpha通道的图像。

这对我有用:

  • 使用全黑色创建一个遮罩(全部掩蔽)
  • 在您ROI的形状中填充白色多边形
  • 将掩模和图像组合以在其他地方得到黑色的ROI

您可能只想保留图像和遮罩以供接受遮罩的功能使用。 但是,我相信这正是您要求的内容:

import cv2
import numpy as np

# original image
# -1 loads as-is so if it will be 3 or 4 channel as the original
image = cv2.imread('image.png', -1)
# mask defaulting to black for 3-channel and transparent for 4-channel
# (of course replace corners with yours)
mask = np.zeros(image.shape, dtype=np.uint8)
roi_corners = np.array([[(10,10), (300,300), (10,300)]], dtype=np.int32)
# fill the ROI so it doesn't get wiped out when the mask is applied
channel_count = image.shape[2]  # i.e. 3 or 4 depending on your image
ignore_mask_color = (255,)*channel_count
cv2.fillPoly(mask, roi_corners, ignore_mask_color)
# from Masterfool: use cv2.fillConvexPoly if you know it's convex

# apply the mask
masked_image = cv2.bitwise_and(image, mask)

# save the result
cv2.imwrite('image_masked.png', masked_image)

@kobejohn 要创建一个遮罩来裁剪并使背景透明吗? - kju
@KobeJohn 是的,没错。 - kju
3
@kju,这个问题似乎很简单,所以我更新了答案而不是提出一个新的问题。我猜很多人做这件事情可能也想要一张透明口罩。 - KobeJohn
2
如果您的形状是凸多边形,应该使用 cv2.fillConvexPoly文档指出,这种方法比 cv2.fillPoly 更快。 - Masterfool
1
我的fillPoly不起作用,但fillConvexPoly可以。谢谢@Masterfool - Michał Gacka
显示剩余3条评论

7
以下代码可帮助裁剪图像并将其放在白色背景中。
import cv2
import numpy as np

# load the image
image_path = 'input image path'
image = cv2.imread(image_path)

# create a mask with white pixels
mask = np.ones(image.shape, dtype=np.uint8)
mask.fill(255)

# points to be cropped
roi_corners = np.array([[(0, 300), (1880, 300), (1880, 400), (0, 400)]], dtype=np.int32)
# fill the ROI into the mask
cv2.fillPoly(mask, roi_corners, 0)

# The mask image
cv2.imwrite('image_masked.png', mask)

# applying th mask to original image
masked_image = cv2.bitwise_or(image, mask)

# The resultant image
cv2.imwrite('new_masked_image.png', masked_image)

输入图像: 输入图像

遮罩图像: 遮罩图像

处理结果输出图像: 输出图像


这与被接受的答案非常相似。您能解释一下这如何为这个问题增加价值吗? - rayryeng
以下代码可帮助获取白色背景掩码图像而不是黑色的。 - Kanish Mathew
这并没有添加任何新内容。只需反转掩码即可。 - rayryeng
如果您能够创建一个反转的掩码并能够提供相同的结果,那么从第一个答案中得到帮助将是有用的。 - Kanish Mathew
我很欣赏这条评论,因为它有代表性的图片。 - Cătălina Sîrbu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接