You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手写数字图像平移至质心时缩小的问题排查与解决

手写数字图像平移至质心时图像缩小的问题排查

我尝试将手写数字图像平移至其像素质心,同时保留图像尺寸并将空白区域填充为白色,为此编写了如下函数:

import numpy as np

def shift(image : np.ndarray, x : int = 0, y : int = 0, output_shape : tuple = (28, 28), fill_value : float = 255.0, dtype : str = "float32"):

    image_shape = image.shape[:2]
    res = image
    col = np.array([[fill_value]]*image_shape[0])
    row = np.array([fill_value]*image_shape[1])

    if x > 0:
        for i in range(x):
            res = np.hstack((col, res))
            res = np.delete(res, len(res[0]) - 1 - i, 1)
    elif x < 0:
        for i in range(np.abs(x)):
            res = np.hstack((res, col))
            res = np.delete(res, i, 1)
    
    if y > 0:
        for i in range(y):
            res = np.vstack((row, res))
            res = np.delete(res, len(res) - 1 - i, 0)
    elif y < 0:
        for i in range(np.abs(y)):
            res = np.vstack((res, row))
            res = np.delete(res, i, 0)
    
    return res.reshape(output_shape).astype(dtype)

但运行后发现图像在平移的同时被缩小,测试代码如下:

from keras.util import load_img, img_to_array
import scipy.ndimage as ndi
import matplotlib.pyplot as plt

fig, ax = plt.subplots(2,1)
ax = ax.ravel()
img = load_img("7.png", color_mode="grayscale")
img = img_to_array(img).reshape(28, 28).astype("float32")
x, y = ndi.center_of_mass(img)

ax[0].imshow(img, cmap="gray")
ax[0].plot(x, y, "ro")

new_img = shift(img, -int(x), int(y))
ax[1].imshow(new_img, cmap="gray")
ax[1].plot(x, y, "ro")

plt.show()

错误效果:图像被缩小,数字出现变形,不符合保留原尺寸的要求。我期望的效果是保留图像形状与像素值,数字平移至质心位置,空白区域填充为白色。

我也曾尝试使用cv2.warpAffine结合skimage.transform.resize,但会留下黑色背景且分辨率较差。


更新1:使用NumPy数组切片修复问题

我通过移除np.delete并改用NumPy数组切片解决了问题:

def shift(image : np.ndarray, x : int = 0, y : int = 0, output_shape : tuple = (28, 28), fill_value : float = 255.0, dtype : str = "float32"):

    image_shape = image.shape[:2]
    res = image
    col = np.array([[fill_value]]*image_shape[0])
    row = np.array([fill_value]*image_shape[1])

    if x > 0:
        for _ in range(x):
            res = np.hstack((col, res))
            res = res[:, :-1]
    elif x < 0:
        for _ in range(np.abs(x)):
            res = np.hstack((res, col))
            res = res[:, 1:]
    
    if y > 0:
        for _ in range(y):
            res = np.vstack((row, res))
            res = res[:-1, :]
    elif y < 0:
        for _ in range(np.abs(y)):
            res = np.vstack((res, row))
            res = res[1:, :]
    
    return res.reshape(output_shape).astype(dtype)

修复后效果:图像尺寸保持28×28不变,数字成功平移至质心位置,空白区域填充为白色,符合预期。不过我当时不确定np.delete为何会导致图像缩小。


更新2:np.delete本身无问题,是索引错误

后来发现我搞错了,np.delete并没有问题!错误原因是之前的删除索引计算错误,修正索引后代码同样可以正常运行:

def shift(image : np.ndarray, x : int = 0, y : int = 0, output_shape : tuple = (28, 28), fill_value : float = 255.0, dtype : str = "float32"):

    image_shape = image.shape[:2]
    res = image
    col = np.array([[fill_value]]*image_shape[0])
    row = np.array([fill_value]*image_shape[1])

    if x > 0:
        for _ in range(x):
            res = np.hstack((col, res))
            res = np.delete(res, len(res[0]) - 1, 1)
    elif x < 0:
        for _ in range(np.abs(x)):
            res = np.hstack((res, col))
            res = np.delete(res, 0, 1)
    
    if y > 0:
        for _ in range(y):
            res = np.vstack((row, res))
            res = np.delete(res, len(res) - 1, 0)
    elif y < 0:
        for _ in range(np.abs(y)):
            res = np.vstack((res, row))
            res = np.delete(res, 0, 0)
    
    return res.reshape(output_shape).astype(dtype)

内容的提问来源于stack exchange,提问作者Leah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:39:42