程序于2023年10月10日更新,移步代码仓库(https://github.com/NICE-FUTURE/predict-gender-and-age-from-camera)查看最新程序及效果。
更新说明摘录如下:
- 特征提取主干由 ResNet50 替换为 Swin-Small, 性别和年龄预测分支由少量卷积替换为 MLP
- 性别预测比较准确, 年龄预测误差较大, 原因及解决思路下面(指 README 说明中的下文 🙂 )单独说明
- 更新了 README 中的说明
程序于2022年4月7日更新,移步代码仓库(https://github.com/NICE-FUTURE/predict-gender-and-age-from-camera)查看最新程序及效果。
更新说明摘录如下:
- 深度学习框架由Keras替换为PyTorch
- 模型结构由少量的卷积层替换为成熟的ResNet作为主干,并将年龄预测和性别预测统一到一个模型中,采用双分支输出结构。
- 目前在验证集的性别预测准确率为 91%
- 实际体验差强人意,但与去年5月份的试水版本相比,效果会更好
以下为旧文:
【Demo】基于CNN实现对摄像头捕捉人脸的性别和年龄预测
主要组成部分
- 人脸识别模块(使用OpenCV自带的人脸识别功能,效果一般)
- 性别分类模型(使用keras构建的一个CNN)
- 年龄预测模型(使用keras构建的一个CNN)
实现思路
准备数据
原始数据来源于 https://data.vision.ee.ethz.ch/cvl/rrothe/imdb-wiki/static/wiki_crop.tar
原始数据集包含的图片数量很多,我从中筛选了大约10000张图片(筛选条件为:由OpenCV识别出的face数目为1、性别已知、男女各约5000张)
将图片由RGB图转换为灰度图,将图片尺寸压缩为20*20
从10000张图片中抽取1000张(男女比例相当)作为测试集,其余作为训练集
训练模型
性别分类模型和年龄预测模型的结构相同,均为两层卷积层,一层池化层,一层全连接层,一层输出层
性别分类模型的输出层使用sigmoid激活,损失函数选用binary_crossentropy
年龄预测模型的输出层使用relu激活,损失函数选用mean_absolute_error
性别分类:
# train4gender.py
def train_CNN(x_train, y_train, x_test, y_test):
input_layer = Input(shape=(20, 20, 1), name="input_layer")
conv2d_layer = Conv2D(32, kernel_size=(3, 3), activation='relu')(input_layer)
conv2d_layer = Conv2D(64, (3, 3), activation='relu')(conv2d_layer)
pool_layer = MaxPooling2D(pool_size=(2, 2))(conv2d_layer)
pool_layer = Dropout(0.25)(pool_layer)
flatten_layer = Flatten()(pool_layer)
hidden_layer = Dense(128, activation='relu')(flatten_layer)
hidden_layer = Dropout(0.5)(hidden_layer)
output_layer = Dense(units=1, activation="sigmoid", name="output_layer")(hidden_layer)
model = Model(input_layer, output_layer)
model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
history = model.fit(x_train, y_train, validation_data=(x_test, y_test), batch_size=batch_size, epochs=epochs, verbose=2)
return model, history
年龄预测:
# train4age.py
def train_CNN(x_train, y_train, x_test, y_test):
input_layer = Input(shape=(20, 20, 1), name="input_layer")
conv2d_layer = Conv2D(32, kernel_size=(3, 3), activation='relu')(input_layer)
conv2d_layer = Conv2D(64, (3, 3), activation='relu')(conv2d_layer)
pool_layer = MaxPooling2D(pool_size=(2, 2))(conv2d_layer)
pool_layer = Dropout(0.25)(pool_layer)
flatten_layer = Flatten()(pool_layer)
hidden_layer = Dense(128, activation='relu')(flatten_layer)
hidden_layer = Dropout(0.5)(hidden_layer)
output_layer = Dense(units=1, activation="relu", name="output_layer")(hidden_layer)
model = Model(input_layer, output_layer)
model.compile(optimizer="adam", loss="mae")
history = model.fit(x_train, y_train, validation_data=(x_test, y_test), batch_size=batch_size, epochs=epochs, verbose=2)
return model, history
模型效果
模型效果并不好,一是模型构建的简陋,二是数据量不大。模型方面有很多CNN模型如:AlexNet、VGG、Inception、ResNet等都可以进一步了解。
这是一次训练过程的记录
train4gender_history.png
train4age_history.png
能够实时对摄像头拍摄的图像处理并展示。
下面是一张不敢恭维的效果图,结果有点惨不忍睹……(组合的四张图片挑选自imdb-wiki数据集)
完整代码
https://github.com/nice-future/predict-gender-and-age-from-camera