人脸性别和年龄识别

本文是对age-gender-estimation项目的详细讲解,它给出了使用keras进行性别和年龄识别的完整流程。

数据

采用的数据集为imdb-wiki,这是一个包含 20,284名人的460,723张以及维基百科上imdb的 62,328张共计523,051 张人脸图像的数据集,是目前开源的数据集中量级最大的,它给出了图像中人物的性别和出生时间、照片的拍摄时间等信息。原始的图片很大,分成了9个部分共计100多G,而裁剪出人脸的图片比较小,只有3G多,因此大家使用的基本都是wiki.tar.gz,不需要注册,直接就可以下载,这点很良心,省去了很多下载话费的时间。

解压后的目录为100个子文件夹,每个子文件夹再存储图片文件。

不过由于是采用matlab的mat格式文件存储的,实际用起来还要做一些转化。里面还含有一些噪声,比如性别标记为NAN,年龄算出来不对等,我写了一些代码来对这些信息进行过滤和统计


 
 
  1. import os
  2. import numpy as np
  3. from scipy.io import loadmat
  4. from datetime import datetime
  5. from tqdm import tqdm
  6. import matplotlib.pyplot as plt
  7. def calc_age(taken, dob):
  8. birth = datetime.fromordinal(max(int(dob) - 366, 1))
  9. # assume the photo was taken in the middle of the year
  10. if birth.month < 7:
  11. return taken - birth.year
  12. else:
  13. return taken - birth.year - 1
  14. def get_meta(mat_path, db):
  15. meta = loadmat(mat_path)
  16. full_path = meta[db][ 0, 0][ "full_path"][ 0]
  17. dob = meta[db][ 0, 0][ "dob"][ 0] # Matlab serial date number
  18. gender = meta[db][ 0, 0][ "gender"][ 0]
  19. photo_taken = meta[db][ 0, 0][ "photo_taken"][ 0] # year
  20. face_score = meta[db][ 0, 0][ "face_score"][ 0]
  21. second_face_score = meta[db][ 0, 0][ "second_face_score"][ 0]
  22. age = [calc_age(photo_taken[i], dob[i]) for i in range(len(dob))]
  23. return full_path, dob, gender, photo_taken, face_score, second_face_score, age
  24. def load_data(mat_path):
  25. d = loadmat(mat_path)
  26. return d[ "image"], d[ "gender"][ 0], d[ "age"][ 0], d[ "db"][ 0], d[ "img_size"][ 0, 0], d[ "min_score"][ 0, 0]
  27. def convert2txt(mat_path="imdb.mat",db="imdb"):
  28. lines=[]
  29. min_score= 1.0
  30. full_path, dob, gender, photo_taken, face_score, second_face_score, age = get_meta(mat_path,db)
  31. genders=[ 0, 0]
  32. ages=[]
  33. for i in range( 101):
  34. ages.append( 0)
  35. for i in tqdm(range(len(full_path))):
  36. #if face_score[i] < min_score:
  37. #continue
  38. #if (~np.isnan(second_face_score[i])) and second_face_score[i] > 0.0:
  39. #continue
  40. if ~( 0 <= age[i] <= 100):
  41. continue
  42. if np.isnan(gender[i]):
  43. continue
  44. g=int(gender[i])
  45. genders[g]+= 1
  46. ag=int(age[i])
  47. ages[ag]+= 1
  48. #print(i,gender[i],age[i])
  49. line=full_path[i][ 0]+ " "+str(g)+ " "+str(ag)
  50. lines.append(line)
  51. with open( "gt.txt", "w") as f:
  52. for line in lines:
  53. f.write(line+ "\n")
  54. print( "genders",genders[ 0],genders[ 1])
  55. print( "age:")
  56. for i in range( 101):
  57. print(i,ages[i])
  58. plt.plot(np.linspace( 0, 101, 101),ages)
  59. plt.savefig( "plot.png")
  60. plt.show()
  61. if __name__== "__main__":
  62. convert2txt()

结果如下:

性别比(男:女)=188746:262834

年龄分布:


 
 
  1. 0 29
  2. 1 149
  3. 2 165
  4. 3 50
  5. 4 77
  6. 5 221
  7. 6 237
  8. 7 440
  9. 8 590
  10. 9 873
  11. 10 1071
  12. 11 1705
  13. 12 1736
  14. 13 2337
  15. 14 2114
  16. 15 2727
  17. 16 2856
  18. 17 3391
  19. 18 4122
  20. 19 5563
  21. 20 7784
  22. 21 8294
  23. 22 8769
  24. 23 9813
  25. 24 11478
  26. 25 12151
  27. 26 13299
  28. 27 12937
  29. 28 13778
  30. 29 14600
  31. 30 16356
  32. 31 16255
  33. 32 15374
  34. 33 15096
  35. 34 14704
  36. 35 15056
  37. 36 15139
  38. 37 14063
  39. 38 14417
  40. 39 13729
  41. 40 11068
  42. 41 11831
  43. 42 10501
  44. 43 10160
  45. 44 8917
  46. 45 10238
  47. 46 8200
  48. 47 7151
  49. 48 6688
  50. 49 6117
  51. 50 5783
  52. 51 5485
  53. 52 4816
  54. 53 4148
  55. 54 4211
  56. 55 3482
  57. 56 3096
  58. 57 3057
  59. 58 3290
  60. 59 3267
  61. 60 2709
  62. 61 2324
  63. 62 2129
  64. 63 2318
  65. 64 1889
  66. 65 1883
  67. 66 1273
  68. 67 1395
  69. 68 1147
  70. 69 1256
  71. 70 1052
  72. 71 926
  73. 72 809
  74. 73 701
  75. 74 585
  76. 75 590
  77. 76 593
  78. 77 490
  79. 78 362
  80. 79 467
  81. 80 267
  82. 81 250
  83. 82 196
  84. 83 164
  85. 84 196
  86. 85 121
  87. 86 70
  88. 87 111
  89. 88 72
  90. 89 31
  91. 90 69
  92. 91 13
  93. 92 17
  94. 93 15
  95. 94 9
  96. 95 6
  97. 96 12
  98. 97 3
  99. 98 4
  100. 99 2
  101. 100 3

画成图如下:

不难看出30-50岁之间的图片最多 ,这也是主流的分布。

具体到age-gender-estimation项目,可以简单的通过

./download.sh
 
 

下载,然后使用

python3 create_db.py --output data/imdb_db.mat --db imdb --img_size 64
 
 

 

将数据集转换为需要的格式,这个格式主要是清理无效标签,省的每次都再重复做,代码和我上面给出的差不多,不再赘述。

模型

使用的模型为WiderResnet

通过Netron可视化出来是

 

可以看出是由6个残差模型拼起来的,不过输出部分有两个输出,一个是性别的2,另一个是年龄的101

训练

训练部分也比较简单,生成了数据文件后直接使用

python3 train.py --input data/imdb_db.mat
 
 

就可以了,如果还想使用数据增强,可以加上--aug

python3 train.py --input data/imdb_db.mat --aug
 
 

demo

想看训练好的效果可以运行

python3 demo.py
 
 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值