Python图像处理:背景减除、居中、缩放、裁剪、配准问题咨询
Python图像处理实操方案(基于OpenCV)
以下方案均依赖opencv-python和numpy库,提前通过pip安装即可使用。
1. 单目标(苹果)自动居中
每张图仅含单个苹果时,不需要复杂分割模型,通过质心检测+平移变换即可实现居中,比固定方向裁剪的鲁棒性更强,不会因为苹果位置特殊丢失边缘内容:
- 先通过OTSU自适应阈值分割出苹果的二值mask
- 通过图像矩计算苹果的质心坐标
- 计算质心与图像画布中心的偏移量,构造平移矩阵做仿射变换,空缺区域填充背景色
import cv2 import numpy as np def center_apple(img, bg_value=(255,255,255)): h, w = img.shape[:2] canvas_center_x, canvas_center_y = w//2, h//2 # 生成苹果分割mask gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5,5), 0) _, mask = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 计算苹果质心 M = cv2.moments(mask) if M["m00"] == 0: return img apple_cx = int(M["m10"] / M["m00"]) apple_cy = int(M["m01"] / M["m00"]) # 平移对齐中心 dx = canvas_center_x - apple_cx dy = canvas_center_y - apple_cy trans_mat = np.float32([[1,0,dx],[0,1,dy]]) centered_img = cv2.warpAffine(img, trans_mat, (w,h), borderValue=bg_value) return centered_img
如果要走纯裁剪逻辑,只需要根据质心位置计算四边裁剪量即可:苹果在左下角时,右侧、上侧的裁剪宽度更大,左、下侧裁剪宽度更小,保证裁剪后的图像中心刚好落在苹果质心上。
2. 多尺寸图像统一调整
根据是否需要保留图像原始比例选对应方案:
- 不需要保留比例:直接调用
cv2.resize(img, (target_w, target_h))即可,缺点是目标可能被拉伸变形 - 需要保留比例:采用letterbox补边逻辑,等比例缩放后将图像贴在统一尺寸画布的中心,空缺区域填充背景色,无变形
def resize_with_padding(img, target_size=(512,512), bg_value=(255,255,255)): h, w = img.shape[:2] target_w, target_h = target_size scale = min(target_w/w, target_h/h) new_w, new_h = int(w*scale), int(h*scale) resized_img = cv2.resize(img, (new_w, new_h)) # 生成画布并贴图 canvas = np.full((target_h, target_w, 3), bg_value, dtype=np.uint8) paste_x = (target_w - new_w) // 2 paste_y = (target_h - new_h) // 2 canvas[paste_y:paste_y+new_h, paste_x:paste_x+new_w] = resized_img return canvas
3. 固定中心的外围裁剪缩放
该操作不会改变图像中心位置,仅裁掉外围冗余区域后缩放到目标尺寸,适合已经完成目标居中的图像预处理:
- 先以图像中心为基准,裁剪出和目标尺寸宽高比一致的最大中心区域
- 将裁剪出的区域直接缩放到目标尺寸即可
def center_crop_and_resize(img, target_size=(512,512)): h, w = img.shape[:2] target_w, target_h = target_size target_ratio = target_w / target_h img_ratio = w / h # 按比例裁中心区域 if img_ratio > target_ratio: new_w = int(h * target_ratio) x_start = (w - new_w) // 2 cropped = img[:, x_start:x_start+new_w] else: new_h = int(w / target_ratio) y_start = (h - new_h) // 2 cropped = img[y_start:y_start+new_h, :] # 缩放到目标尺寸 final_img = cv2.resize(cropped, target_size) return final_img
注意:该操作会丢弃外围图像内容,如果目标没有提前居中,可能裁掉部分目标主体。
4. 微小偏移图像对齐(配准)用于差分检测
间隔固定时间拍摄的图像仅存在刚性位移(平移、轻微旋转,无明显形变),用OpenCV自带的ECC(增强相关系数)算法即可完成高精度对齐,对齐后再做差分就不会因为偏移产生大量误检:
def align_to_ref(ref_img, moving_img): ref_gray = cv2.cvtColor(ref_img, cv2.COLOR_BGR2GRAY) moving_gray = cv2.cvtColor(moving_img, cv2.COLOR_BGR2GRAY) # 初始化刚性变换矩阵 warp_mat = np.eye(2, 3, dtype=np.float32) # 迭代终止条件 stop_criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 1000, 1e-8) # 计算最优变换参数 _, warp_mat = cv2.findTransformECC(ref_gray, moving_gray, warp_mat, cv2.MOTION_EUCLIDEAN, stop_criteria) h, w = ref_img.shape[:2] aligned_img = cv2.warpAffine(moving_img, warp_mat, (w,h), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP) return aligned_img # 差分检测调用示例 # ref_frame = cv2.imread("first_shot.jpg") # next_frame = cv2.imread("5min_later.jpg") # aligned_frame = align_to_ref(ref_frame, next_frame) # # 计算差分图 # diff = cv2.absdiff(ref_frame, aligned_frame) # diff_gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY) # # 阈值过滤噪声,得到真实变化区域 # _, change_mask = cv2.threshold(diff_gray, 25, 255, cv2.THRESH_BINARY)
如果图像位移极小、没有旋转,也可以用相位相关算法直接计算x/y方向的平移量,对齐速度更快。
内容的提问来源于stack exchange,提问作者김수환
相关产品推荐
相关产品推荐

