如何基于NumPy数组实现图像中物体的居中?(已完成质心计算)
图像物体居中的实现方案
原代码问题修正
原代码中pxl_array = np.array(pixels)得到的是一维数组,无法直接获取height和width,需要先reshape为二维数组;另外如果原图像是RGB格式,必须先转为灰度图,否则像素数组是三维结构,会导致归一化和质心计算出错。
核心步骤:基于偏移量平移图像
算出偏移量后,我们需要创建一个和原图像尺寸一致的新数组,将原图像的像素按偏移量复制到新数组对应位置,空白区域用背景色(比如白色)填充。
完整代码示例
from PIL import Image import numpy as np import matplotlib.pyplot as plt # 读取图像并转为灰度图(彩色图需此步骤简化计算) img = Image.open("image.png").convert('L') width, height = img.size # 将像素转为二维NumPy数组 pixels = list(img.getdata()) pxl_array = np.array(pixels).reshape(height, width) # 归一化像素值(背景为0,物体为1,用于质心计算) pxl_array_norm = pxl_array // 255 total_intensity = np.sum(pxl_array_norm) # 用向量化操作计算质心(比嵌套循环效率高很多) y_indices, x_indices = np.mgrid[:height, :width] centroid_x = np.sum(x_indices * pxl_array_norm) / total_intensity centroid_y = np.sum(y_indices * pxl_array_norm) / total_intensity print(f"物体质心坐标: ({centroid_x:.2f}, {centroid_y:.2f})") # 计算偏移量 offset_x = width // 2 - centroid_x offset_y = height // 2 - centroid_y # 创建新图像数组,背景设为白色(255) new_pxl_array = np.full_like(pxl_array, 255) # 平移坐标取整(像素位置为整数) start_x = int(np.round(offset_x)) start_y = int(np.round(offset_y)) # 计算有效区域,避免数组索引越界 # X轴方向 src_x_min = max(0, -start_x) src_x_max = min(width, width - start_x) dst_x_min = max(0, start_x) dst_x_max = min(width, width + start_x) # Y轴方向 src_y_min = max(0, -start_y) src_y_max = min(height, height - start_y) dst_y_min = max(0, start_y) dst_y_max = min(height, height + start_y) # 将原图像有效区域复制到新图像对应位置 new_pxl_array[dst_y_min:dst_y_max, dst_x_min:dst_x_max] = pxl_array[src_y_min:src_y_max, src_x_min:src_x_max] # 转换为PIL图像并保存、显示 new_img = Image.fromarray(new_pxl_array.astype(np.uint8)) new_img.save("centered_image.png") # 对比显示原图像和居中后的图像 plt.figure(figsize=(10, 5)) plt.subplot(121) plt.imshow(img, cmap='gray') plt.title("原图像") plt.subplot(122) plt.imshow(new_img, cmap='gray') plt.title("居中后的图像") plt.show()
关键说明
- 灰度转换:
convert('L')将彩色图转为单通道灰度图,简化质心计算逻辑;若需处理彩色图,可对每个通道单独计算质心,或转为灰度后处理。 - 向量化计算:用
np.mgrid生成坐标网格替代循环,处理大图像时效率提升明显。 - 边界处理:通过计算有效区域避免索引越界,确保平移操作不会报错。
- 背景自定义:可将
np.full_like中的255改为其他值(比如0代表黑色),自定义背景颜色。
内容的提问来源于stack exchange,提问作者Abderrahmane Alloubane
相关产品推荐
相关产品推荐

