小白记人脸识别Average—Face
写在前面
本学期老师要做一个人脸识别(特征脸的项目),之前做过基于Opencv的其他方式,不过这次做的有些不同,就老老实实地做。
我是一个爱分享的努力男孩,所以把每次小项目记在这里吧。
编辑器使用Anaconda(由于Jupyter Notebook方便执行,并且已经带有许多常用库,较为方便,但是个人更喜欢pycharm),python版本为3.7.0
引入依赖库
既然是图片,那就必然会用到matplotlib库
对图片进行操作,实际就是对其像素点进行操作,可看作是数据处理就少不了用到强大的numpy以及自带库math
import matplotlib.pyplot as plt
import matplotlib.image as mp
#引入2D绘图处理库中的模块并命名
import math
import numpy as np
#数值计算库处理
图片初步处理
图片会放在项目文件夹下,我们是要求三个人,每人十张图片
直接让循环遍历,
然后把数值放在一个列表里,为后续操作就需要把多维数组元素转缓从一个一维数组
下面是重点,重点~
踩最大的坑
图片格式问题!!!
其实程序不难也不多,但是就是这个格式问题,搞了我们一上午,疫情期间沟通不便是其中一部分原因,最大的坑就是:使用pgm格式,pgm格式输出shape值,只有长和宽,其他的格式还会输出RGB通道数更为重要的是:不能直接改后缀,要用软件输出,不然shape值还是会返回三个,就会发生ValueError,最好让一个人操作,用同一个照片编辑器
- 裁剪脸部,更改尺寸大小92*112
- 灰度处理
- 输出为pgm格式
我们当时,这个裁剪,那个处理的,啧啧啧,真的都是泪啊…
简单处理
Path = 'img/{0}.pgm'
count = 30
#确定图片读入路径,以及后续遍历个数
Height,Width = mp.imread(Path.format(1)).shape
#打印图片大小会返回两个个值,长宽(jpg等格式还会有RGB通道数)
print(Height)
print(Width)
#确定图片的大小是否准确
list_imgs = []
#创建用于存放照片像素点的列表
for i in range(1,count+1):
img = mp.imread(Path.format(i))
list_imgs.append(img.ravel())
# ravel是 numpy 的函数: 将多维数组中的元素变成一个一维数组
#遍历每张图片,转换为矩阵 range(1,11)会生成1-10
list_imgs
list_imgs[0].reshape(Height, Width)
输出结果
112
92
array([[105, 105, 125, …, 31, 27, 32],
[104, 110, 109, …, 22, 19, 25],
[125, 120, 102, …, 24, 22, 29],
…,
[143, 173, 196, …, 97, 18, 55],
[194, 215, 220, …, 253, 102, 19],
[228, 226, 229, …, 241, 242, 141]], dtype=uint8)
全部输出
方便确认初步处理结果,以及是否每个照片被遍历到,
我们可以创建窗口输出,主要有两种方式,这里采用横向(个人习惯)
ncols = count
fig, axes = plt.subplots(1, ncols, figsize = (45, 15))
#规定窗口大小,规定横向输出方式
title = 'face {0}'
#窗口命名
for j in range(count):
axes[j].imshow(list_imgs[j].reshape((Height,Width)),"gray")
axes[j].set_title(title.format(1+j))
#遍历映射输出灰度
for ax in axes.ravel():
ax.axis('off')
计算平均脸
我们之前读取的相素点全部保存在列表里面,我们要计算的是平均脸,就需要把列表全部转成数组的形式
gam = np.array(list_imgs)
#把列表变成数组
print(gam.shape)
#30行,10304列
print(gam)
输出结果
(30, 10304)
[[105 105 125 … 241 242 141]
[ 83 89 100 … 214 211 210]
[235 232 248 … 213 214 214]
…
[190 202 194 … 38 35 40]
[193 195 194 … 27 27 27]
[200 198 200 … 38 42 35]]
平均脸就需要把行数置0,求各列的均值,返回是转化为1*n的矩阵
average = np.mean(gam, axis = 0)
#axis = 0:行数置0,求各列均值,返回 1* n 矩阵
print(average)
输出结果
[170.6 164.23333333 165.33333333 … 77.9 76.86666667
80.2 ]
直接把矩阵重新映射为像素点列表,灰度输出
plt.imshow(average.reshape(Height,Width),"gray")
#映射输出
输出结果
那个,我承认我脸大…
写在后面
这个项目会一直写下去的,做到哪就会更新到哪儿
希望多多支持哦。
老规矩,
个人博客:
贴出公众号:兴趣路人甲