Keras语义分割:小尺寸训练后无法预测大尺寸图像的问题
问题解答
完全可以在小尺寸图像上训练模型,同时对大尺寸图像进行预测,以下是具体解决思路和代码调整方案:
方案一:修改模型为动态输入尺寸(推荐)
你的U-Net模型当前输入尺寸固定为(128,128,1),这是导致输入不兼容的核心原因。U-Net的结构天然支持可变尺寸输入(只要输入尺寸是下采样/上采样步长的整数倍,256是128的2倍,完全符合要求),只需要修改输入层为动态尺寸即可:
修改后的模型代码
# 将固定输入尺寸改为动态尺寸,支持任意符合下采样倍数的输入 inputs = Input((None, None, 1)) s = Lambda(lambda x: x / 255)(inputs) c1 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(s) c1 = Dropout(0.1)(c1) c1 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c1) p1 = MaxPooling2D((2, 2))(c1) c2 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(p1) c2 = Dropout(0.1)(c2) c2 = Conv2D(32, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c2) p2 = MaxPooling2D((2, 2))(c2) # 保留原模型中间层代码... u9 = Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(c8) u9 = concatenate([u9, c1], axis=3) c9 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(u9) c9 = Dropout(0.1)(c9) c9 = Conv2D(16, (3, 3), activation='elu', kernel_initializer='he_normal', padding='same')(c9) outputs = Conv2D(1, (1, 1), activation='sigmoid')(c9) model = Model(inputs=[inputs], outputs=[outputs]) model.compile(optimizer='adam', loss='binary_crossentropy')
训练与预测调整
- 训练阶段:依然使用128x128的图像输入,训练逻辑无需改变,模型会自动适配该尺寸。
- 预测阶段:直接输入256x256的单通道图像(和训练输入格式一致),模型会输出对应尺寸的分割结果,完全满足竞赛要求。
方案二:缩放输入输出(临时替代方案)
如果不想修改模型结构,可以采用“缩放输入-预测-缩放输出”的流程,但会损失一定精度:
- 预测时将256x256的图像缩放到128x128,输入模型得到128x128的预测结果
- 将预测结果缩放到256x256,注意使用和图像缩放一致的插值方式(推荐用
bilinear或nearest,避免模糊)
示例代码(预测阶段)
from skimage.transform import resize # 加载256x256的单通道图像 image_256 = np.array(Image.open(test_path).convert('L')) image_256 = np.expand_dims(image_256, axis=-1) # 缩放到128x128用于预测 image_128 = resize(image_256, (128, 128), mode='constant', preserve_range=True) image_128 = np.expand_dims(image_128, axis=0) # 增加batch维度 # 预测 pred_128 = model.predict(image_128) # 缩放回256x256 pred_256 = resize(pred_128[0], (256, 256), mode='constant', preserve_range=True) pred_256 = np.expand_dims(pred_256, axis=0) # 恢复batch维度
额外修正:数据获取函数的bug
你的get_data函数存在缩进错误,out[i] = image应该在for循环内部,否则只会将最后一张图像赋值到输出数组中,修正后的代码:
def get_data(a, path, IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS, t): out = np.zeros((len(a), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=t) for i, image_id in enumerate(a): path_image = path + image_id image = np.array(Image.open(path_image).convert('L')) image = resize(image, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True) image = np.expand_dims(image, axis=-1) out[i] = image # 修正缩进,放到循环内部 return out
内容的提问来源于stack exchange,提问作者Snork Maiden
相关产品推荐
相关产品推荐

