如何基于轮廓裁剪图像片段?OpenCV衣物提取遇阻求助
问题:OpenCV轮廓检测后精准裁剪衣物片段
我用OpenCV做轮廓检测,目的是提取人物衣物片段用于后续CNN分类,但现在卡在了轮廓检测后精准沿轮廓裁剪图像的环节。
相关处理步骤图像
- 原始图像:

- 去背景后图像:

- 灰度模糊后图像:

- 边缘检测结果:

- 形态学闭运算结果:

- 轮廓绘制结果:

现有实现代码
导入依赖
import cv2 import imutils import numpy as np from rembg import remove from PIL import Image
去除背景
input_path = 'wear.jpg' output_path = 'cutted_wear.png' output = remove(Image.open(input_path)) output.save(output_path)
预处理与边缘检测
image = cv2.imread('cutted_wear.png') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (9, 9), 0) cv2.imwrite('test.jpg', gray) edges = cv2.Canny(gray, 25, 130) cv2.imwrite('edges.jpg', edges)
形态学闭运算
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10)) closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel) cv2.imwrite('closed.jpg', closed)
轮廓检测与绘制
cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) total = 0 for c in cnts: p = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.00001 * p, True) if len(approx) > 0: cv2.drawContours(image, [approx], -1, (0, 255, ), 4) total +=1 print(total) cv2.imwrite('test_final.jpg', image)
精准沿轮廓裁剪的解决方案
要实现沿轮廓精准裁剪,核心是利用轮廓生成掩码(Mask),再通过掩码与原始图像做位运算提取目标区域,具体步骤如下:
- 筛选面积最大的轮廓(对应衣物主体,过滤小干扰轮廓)
- 创建与原图尺寸一致的掩码,将目标轮廓填充为白色
- 通过位运算提取轮廓内的图像区域
- 获取轮廓外接矩形,裁剪出包含目标的最小边界区域
修改后的完整代码(新增裁剪逻辑)
在原有轮廓检测代码后添加裁剪相关逻辑:
import cv2 import imutils import numpy as np from rembg import remove from PIL import Image # 1. 去除背景 input_path = 'wear.jpg' output_path = 'cutted_wear.png' output = remove(Image.open(input_path)) output.save(output_path) # 2. 预处理与边缘检测 image = cv2.imread('cutted_wear.png') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (9, 9), 0) edges = cv2.Canny(gray, 25, 130) # 3. 形态学闭运算 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10)) closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel) # 4. 轮廓检测 cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) # 5. 精准裁剪核心逻辑 # 筛选面积最大的轮廓(衣物主体) cnts = sorted(cnts, key=cv2.contourArea, reverse=True) target_cnt = cnts[0] # 生成掩码 mask = np.zeros(image.shape[:2], dtype=np.uint8) cv2.drawContours(mask, [target_cnt], -1, 255, thickness=cv2.FILLED) # 位运算提取目标区域 cropped = cv2.bitwise_and(image, image, mask=mask) # 裁剪到最小外接矩形 x, y, w, h = cv2.boundingRect(target_cnt) cropped = cropped[y:y+h, x:x+w] # 保存最终裁剪结果 cv2.imwrite('precision_cropped_wear.png', cropped)
关键细节说明
- 轮廓筛选:通过
cv2.contourArea排序取最大轮廓,可有效过滤背景残留或噪声带来的小轮廓 - 掩码填充:使用
cv2.FILLED确保轮廓内部完全被覆盖,避免裁剪出现漏边 - 外接矩形裁剪:去除多余黑边,得到仅包含衣物的最小尺寸图像,更适配后续CNN模型输入
内容的提问来源于stack exchange,提问作者Денис Лютый
相关产品推荐
相关产品推荐

