如何基于OpenCV提取的前两大轮廓裁剪对应图像区域?
解决OpenCV裁剪前2大轮廓内图像区域的问题
以下是修改后的完整代码,在原有检测并绘制前2大轮廓的基础上,新增了裁剪轮廓内图像区域的功能:
import cv2 import numpy as np import matplotlib.pyplot as plt image_path = r'C:\Users\bear\Good\230903134657_HNN3TDMXY_1_Delam Analysis.jpg' image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) def count_contours(image, th): _, binary_image = cv2.threshold(image, th, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contour_areas = [(cv2.contourArea(contour), contour) for contour in contours] contour_areas.sort(key=lambda x: x[0], reverse=True) total_contours_count = len(contour_areas) print(total_contours_count) return total_contours_count def draw_and_crop_contours(image, th): _, binary_image = cv2.threshold(image, th, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contour_areas = [(cv2.contourArea(contour), contour) for contour in contours] contour_areas.sort(key=lambda x: x[0], reverse=True) top_contours = [contour for _, contour in contour_areas[:2]] # 绘制轮廓并保存 contour_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) cv2.drawContours(contour_image, top_contours, -1, (0, 255, 0), 2) cv2.imwrite('drawcountourtest.png', contour_image) # 裁剪每个轮廓内的区域 for idx, contour in enumerate(top_contours): # 创建与原图像尺寸一致的空白掩码 mask = np.zeros_like(image) # 用白色填充轮廓内部 cv2.drawContours(mask, [contour], -1, 255, thickness=cv2.FILLED) # 提取轮廓内的图像(非轮廓区域为黑色) cropped_full = cv2.bitwise_and(image, image, mask=mask) # 获取轮廓的外接矩形,裁剪掉周围的黑色区域 x, y, w, h = cv2.boundingRect(contour) cropped_roi = cropped_full[y:y+h, x:x+w] # 保存裁剪后的图像 cv2.imwrite(f'cropped_contour_{idx+1}.png', cropped_roi) # 展示绘制结果和裁剪结果 plt.figure(figsize=(12, 6)) plt.subplot(1, 3, 1) plt.imshow(cv2.cvtColor(contour_image, cv2.COLOR_BGR2RGB)) plt.title('绘制的轮廓') plt.axis('off') for idx in range(len(top_contours)): cropped_img = cv2.imread(f'cropped_contour_{idx+1}.png', cv2.IMREAD_GRAYSCALE) plt.subplot(1, 3, idx+2) plt.imshow(cropped_img, cmap='gray') plt.title(f'裁剪区域{idx+1}') plt.axis('off') plt.show() test_count = count_contours(image, 130) if test_count > 300: print(test_count) draw_and_crop_contours(image, 200) else: print(test_count) draw_and_crop_contours(image, 130)
关键修改说明
- 功能整合:将原
draw_contours函数重命名为draw_and_crop_contours,同时保留绘制功能并新增裁剪逻辑 - 掩码提取轮廓区域:为每个轮廓创建空白掩码,用
cv2.FILLED参数填充轮廓内部,确保仅保留轮廓范围内的图像 - 过滤与裁剪:通过
cv2.bitwise_and过滤掉轮廓外区域,再用cv2.boundingRect获取轮廓的最小包围矩形,裁剪掉结果中的黑色冗余区域 - 结果输出:每个裁剪后的区域单独保存为图片,同时在画布上直观展示绘制结果和裁剪效果
内容的提问来源于stack exchange,提问作者Liu Xu
相关产品推荐
相关产品推荐

