如何用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
相关产品推荐
相关产品推荐

