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

46 投票
2 回答
46056 浏览
提问于 2025-04-17 18:41

我有一组点,这些点组成了一个形状(封闭的折线)。现在我想从某张图片中复制/裁剪出这个形状内部的所有像素,其他部分则留黑或透明。我该怎么做呢?

比如,我现在有这个:

在这里输入图片描述

我想得到的是这个:

在这里输入图片描述

2 个回答

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)

输入图片: 输入图片

遮罩图片: 遮罩图片

处理后的输出图片: 处理后的图片

68

*编辑 - 更新以支持具有透明通道的图像。

这个方法对我有效:

  • 先制作一个全黑的遮罩(表示全部被遮住)
  • 在你感兴趣的区域(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)

撰写回答