You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python和OpenCV通过掩码提取原图像中的非矩形白色区域子图像?

基于掩码提取非矩形白色区域子图像(Python + OpenCV)

嘿,我来帮你搞定这个问题!要从原始图像里提取掩码中那些非矩形白色区域的子图像,用Python+OpenCV完全可以实现,核心就是先找到每个独立的白色连通区域,再把对应区域从原图里抠出来——还能完美保留区域的不规则形状哦。下面是具体的步骤和代码示例:

核心思路

  • 通过轮廓检测定位掩码里所有独立的白色连通区域
  • 对每个区域,我们可以创建带Alpha通道的图像,只保留轮廓内的像素,其他区域设为透明,这样就能得到真正的非矩形子图像
  • 如果不需要透明背景,也可以提取区域的最小外接矩形,再用掩码裁剪出对应形状的像素

步骤1:导入依赖并读取图像

首先导入需要的库,然后读取原始图像和掩码图像:

import cv2
import numpy as np

# 读取原始图像(BGR格式)
original_img = cv2.imread('original_image.jpg')
# 以灰度模式读取掩码图像(确保是二值图:0为黑,255为白)
mask_img = cv2.imread('mask_image.png', 0)

如果你的掩码不是二值图,先做阈值处理:_, mask_img = cv2.threshold(mask_img, 127, 255, cv2.THRESH_BINARY)

步骤2:检测掩码中的所有连通轮廓

用OpenCV的轮廓检测功能,找出掩码里所有独立的白色区域:

# 只检测最外层的独立轮廓,避免嵌套区域干扰
contours, _ = cv2.findContours(mask_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  • cv2.RETR_EXTERNAL:只提取最外层轮廓,适合分离独立的白色区域
  • cv2.CHAIN_APPROX_SIMPLE:压缩轮廓点的数量,减少计算量

步骤3:提取带透明背景的非矩形子图像

这是最常用的方式,保存的PNG图像会只显示轮廓内的原始图像内容,其他区域透明:

# 遍历每个检测到的轮廓
for idx, contour in enumerate(contours):
    # 创建和掩码大小一致的Alpha通道,初始全黑(透明)
    alpha_channel = np.zeros_like(mask_img)
    # 将当前轮廓区域填充为白色(不透明)
    cv2.drawContours(alpha_channel, [contour], 0, 255, thickness=cv2.FILLED)
    
    # 把原始图像转为BGRA格式(添加Alpha通道)
    bgra_img = cv2.cvtColor(original_img, cv2.COLOR_BGR2BGRA)
    # 将Alpha通道赋值给BGRA图像的第4通道
    bgra_img[:, :, 3] = alpha_channel
    
    # 提取当前轮廓的最小外接矩形,裁剪出子图像(避免保存整个大图像)
    x, y, w, h = cv2.boundingRect(contour)
    cropped_subimg = bgra_img[y:y+h, x:x+w]
    
    # 保存子图像(必须用PNG格式,JPG不支持透明)
    cv2.imwrite(f'subimage_{idx+1}.png', cropped_subimg)
    print(f"已成功保存第{idx+1}个子图像")

可选:提取无透明背景的子图像(背景为黑色)

如果不需要透明背景,只想保留区域内的像素,背景设为黑色,可以用这个方法:

for idx, contour in enumerate(contours):
    # 创建只包含当前轮廓的掩码
    single_mask = np.zeros_like(mask_img)
    cv2.drawContours(single_mask, [contour], 0, 255, thickness=cv2.FILLED)
    
    # 用掩码提取原始图像的对应区域
    subimg = cv2.bitwise_and(original_img, original_img, mask=single_mask)
    
    # 裁剪最小外接矩形
    x, y, w, h = cv2.boundingRect(contour)
    cropped_subimg = subimg[y:y+h, x:x+w]
    
    # 保存(可以用JPG格式)
    cv2.imwrite(f'subimage_no_alpha_{idx+1}.jpg', cropped_subimg)

小提示

  • 如果掩码里有嵌套的白色区域,把cv2.RETR_EXTERNAL改成cv2.RETR_TREE就能检测所有层次的轮廓
  • 轮廓检测前可以对掩码做一次形态学操作(比如cv2.morphologyEx),去除小的噪点,避免提取不必要的小区域

内容的提问来源于stack exchange,提问作者Maximus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:16:29