You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于Keras的图像回归:如何用图像训练关键点预测模型?

图像关键点回归:将文件名转为像素输入的解决方案

你现在在做一个关键点回归任务(预测头部、双手、方向盘的XY坐标),用KerasRegressor训练模型,但目前X只是图像文件名,需要转换成图像像素数据作为模型输入对吧?完全没问题,用RGB像素值作为输入是非常常规且可行的方案,下面一步步给你实现:

一、核心思路

你需要遍历每个图像文件名,加载对应的图像文件,做必要的预处理(统一尺寸、归一化),最终把所有图像转换成模型能接受的4维数组格式:(样本数, 图像高度, 图像宽度, 通道数)

二、具体代码实现

1. 导入必备库

import numpy as np
from PIL import Image
import pandas as pd
from sklearn.model_selection import KFold
from keras.wrappers.scikit_learn import KerasRegressor
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D

2. 编写图像加载与预处理函数

假设你的图像都存在./images/目录下(记得改成你自己的实际路径):

def load_and_preprocess_images(image_filenames, target_size=(224, 224)):
    image_list = []
    for filename in image_filenames:
        # 加载图像并转为RGB格式(避免灰度图的通道问题)
        img = Image.open(f"./images/{filename}").convert("RGB")
        # 统一所有图像的尺寸,保证输入维度一致
        img_resized = img.resize(target_size)
        # 转为numpy数组并归一化到0-1区间,加速模型收敛
        img_array = np.array(img_resized) / 255.0
        image_list.append(img_array)
    # 转换为4维数组,符合Keras输入要求
    return np.array(image_list)

3. 替换X为图像像素数据

用上面的函数把原来的文件名数组转换成图像像素数组:

# 假设你的原始数据存在pandas DataFrame里
# 先提取图像文件名
X_filenames = data["image"].values
# 加载并预处理所有图像
X = load_and_preprocess_images(X_filenames)
# 处理标签Y,转为浮点型数组(回归任务推荐)
Y = data.drop("image", axis=1).values.astype(np.float32)

4. 调整你的模型结构(关键!)

原来的baseline_model如果是全连接模型,需要先把2D图像展平;如果用CNN会更适合图像任务,给你两个可选方案:

方案1:全连接模型(适合快速验证)

def baseline_model():
    model = Sequential()
    # 展平224*224*3的图像为1维向量
    model.add(Flatten(input_shape=(224, 224, 3)))
    model.add(Dense(512, activation='relu'))
    model.add(Dense(256, activation='relu'))
    # 输出8个连续值(对应8个坐标)
    model.add(Dense(8))
    # 回归任务用均方误差损失,优化器选Adam
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model

方案2:CNN模型(更擅长提取图像特征,效果通常更好)

def cnn_baseline_model():
    model = Sequential()
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)))
    model.add(MaxPooling2D((2, 2)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2)))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2)))
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dense(8))
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model

5. 执行交叉验证训练

现在X已经是正确的输入格式了,可以直接用你的原有流程训练:

seed = 42
# 这里换成你选的模型,比如cnn_baseline_model
estimator = KerasRegressor(build_fn=cnn_baseline_model, epochs=10, batch_size=16, verbose=True)
kfold = KFold(n_splits=10, random_state=seed, shuffle=True)
results = cross_val_score(estimator, X, Y, cv=kfold)
print(f"交叉验证平均MSE: {results.mean():.4f} (+/- {results.std():.4f})")

三、额外优化建议

  • 图像尺寸调整:224x224是常用的折中尺寸,太大训练慢,太小会丢失关键特征,你可以根据你的图像实际大小调整
  • 坐标归一化:可以把Y坐标也归一化到0-1区间(比如除以图像的宽、高),模型更容易学习,预测后再反归一化得到真实坐标
  • 数据增强:如果你的数据集较小,用keras.preprocessing.image.ImageDataGenerator做数据增强(旋转、平移、翻转等),能有效防止过拟合
  • 迁移学习:如果样本量很少,可以用ResNet50、MobileNet等预训练模型做迁移学习,能大幅提升模型性能

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

火山引擎 最新活动