基于OpenCV从旋转填充图像提取合规224×224非重叠切块的问题
解决方案
问题根源分析
你当前代码存在两个核心问题:
- 背景像素判断错误:你用
np.ones创建背景,生成的是值为[1,1,1]的近黑色像素,而非纯黑的[0,0,0],导致判断黑像素的条件np.all(cropped == [0,0,0], axis=-1)无法识别填充区域,反而会误保留原图中全黑的切块(如果存在)。 - 效率低下:逐个切块遍历像素计数的方式,时间复杂度为
O(N*M*S²)(N、M是切块数量,S是切块边长),当图像较大时会明显卡顿。
优化方案:掩码+积分图
通过掩码标记填充区域,再用积分图快速计算区域内填充像素占比,既能解决判断错误问题,又能将效率提升至O(N*M)。
步骤1:修正背景创建与生成掩码
先确保背景是纯黑,同时生成对应掩码(填充区域标记为1,原图区域标记为0):
import cv2 import numpy as np img = cv2.imread("maxresdefault.jpg") background_size = 1475 # 修正:用np.zeros创建纯黑背景 background = np.zeros((background_size, background_size, 3), dtype=np.uint8) start_y = (background_size - img.shape[0]) // 2 start_x = (background_size - img.shape[1]) // 2 background[start_y:start_y+img.shape[0], start_x:start_x+img.shape[1]] = img # 生成掩码:原图区域为0,填充区域为1 mask = np.ones((background_size, background_size), dtype=np.uint8) mask[start_y:start_y+img.shape[0], start_x:start_x+img.shape[1]] = 0 # 旋转图像和掩码 angle = 60 rot_point = (background_size//2, background_size//2) rot_mat = cv2.getRotationMatrix2D(rot_point, angle, 1.0) img_rot = cv2.warpAffine(background, rot_mat, (background_size, background_size)) mask_rot = cv2.warpAffine(mask, rot_mat, (background_size, background_size))
步骤2:用积分图快速计算填充像素占比
积分图可以让我们在O(1)时间内算出任意矩形区域的像素总和,避免逐个切块遍历像素:
crop_size = 224 valid_cropped_images = [] # 计算掩码的积分图 integral = cv2.integral(mask_rot) height, width = img_rot.shape[:2] # 遍历所有非重叠切块 for y in range(0, height - crop_size + 1, crop_size): for x in range(0, width - crop_size + 1, crop_size): # 利用积分图公式计算当前切块内的填充像素数量 # 积分图公式:sum = integral[y2][x2] - integral[y1][x2] - integral[y2][x1] + integral[y1][x1] y2, x2 = y + crop_size, x + crop_size black_count = integral[y2, x2] - integral[y, x2] - integral[y2, x] + integral[y, x] total_count = crop_size * crop_size black_ratio = black_count / total_count # 筛选符合条件的切块 if black_ratio <= 0.1: valid_cropped_images.append(img_rot[y:y2, x:x2])
额外说明
- 积分图的计算仅需一次,后续每个切块的占比计算都是常数时间,相比原方法效率提升显著。
- 掩码旋转时,
cv2.warpAffine会自动处理边缘的插值,确保填充区域的标记准确。
内容的提问来源于stack exchange,提问作者Aladin
相关产品推荐
相关产品推荐

