python和opencv人脸表情识别_Windows+Anaconda3+Te
因为项目上的需要,我需要去训练一个人脸识别的系统,但是机器视觉方向并不是我特别喜欢的方向,所以我特别急功求成,想尽快搭建一个人脸识别系统,其实在git上已经有很多相关论文还有已经训练好的模型,大家如果想去了解这方面的知识,这篇文章并不适合您看。当然,时间是必须去付出的,大家如果喜欢这方面的方向,就好好斟酌一下,神经网络现在应用的很广,推荐框架,实在是太简单方便搭建了。当然不要光只学框架,具体的原理一定要搞清楚,推荐- ng-课程,没看过就相当于没学过,这是经典,而且入门简单,好好学,好好吸收,原理就这样。好吧,接下来我就将这10天的工作总结在此吧。
【2019/3/11】鉴于文章关注好像挺多了,过2天我会尝试将代码放到上,我不知道是否能上传这么大量的图片。
一,材料准备
-4.2.0
这是一个.5.2的集成环境,特别好用和方便,方便管理需要用的包。
二,学习教程
这个学习教程无所谓的,你可以看书,也可以找网站来自学,当然必须先有的基础知识了。
这个我推荐莫烦大牛的基础视频教程,不过这个课程说实在的是过于简单,就是快速的让人了解整个过程,其实面对的还是一些有基础的人,所以一定要看- ng-这课程,经典!经典!经典!重要的东西说3遍。当然学习框架的东西最好还是去官方(好难打开)去细酌,当然中文社区也行,看自己喜欢,八仙过海,各显神通。
这个就没什么好说的了,直接看官方的教程,一点点敲,一点点尝试,这是3.0的教程,2.0在某些方面上不一样,我觉得可以直接入3.0。当然个人也极度推荐看毛星云大牛博客,当然自己先需要懂c++,然后去搞懂每个原理就好,更多东西,还是回归官网,官网说的为准。
三,环境布置
1.安装
我刚刚给的链接是个exe文件,所以这我就不用说了吧,就是傻瓜式的下一步,选择安装就好。
注意:这里可能有人纠结选择什么,我选择的是这个。
安装完成后,一般所有软件都会在这里。
2.安装
打开开始找到 ,并以管理员身份运行,其实就是个普通终端罢了。
输入以下命令,然后按下y即可。
conda -c
安装完成后我们可以用以下命令试试是否正常使用,没反应就是最好的反应了啊,能正常使用。
cv2
3.安装
同样地,打开开始找到 ,并以管理员身份运行,输入以下命令,这时候使用的.3.0
#安装完成后,打开 ,输入如下命令,创建虚拟环境。
conda -n =3.5
#进入虚拟环境
退出虚拟环境
安装
pip
亲测可用,完成了之后,同样可以输入以下命令来进行测试。
用就是这么方便,很多东西都集成好在一个地方,如果想卸载,其实很简单,直接把卸载了,什么都脱离了你的环境了。就是这么好用。
四,源代码
ps:下面步骤如果没提示到的文件和数据包,不需要管,我会在每一个文件对应需要下载和安装什么东西,一步一步进行讲述
工具
我们使用的编辑工具叫,自带工具,在开始输入即可找到。
main.py
首先去官网,下载一个包,将下面的两个文件放入xml文件夹。
然后可以运行以下代码,当然要注意我们的----------------------------ps:位置,等等我们将到对应位置之后,遍可打开,将得到你渴望的效果。慢慢来,心急吃不到热豆腐,先试试人脸识别怎么样,这是的demo改写的,就是利用分类器进行分类,有2部判断,先判断是否是人脸,是人脸的话,判断人脸有没眼睛,如果有这个就是人脸。当然相关论文知识我的这篇文章不会详细介绍,大家可以上网去找,我只想用最简单的方式给大家带来效果
代码
# -*- : utf-8 -*-
"""
on Tue Oct 17 10:14:19 2017
@:
"""
cv2
numpy as np
#----------------------------ps:讲到年龄,性别的时候可以打开
# as
#调用自己的表情文档
#----------------------------ps:讲到表情识别的时候可以打开
# model as
#调用自己的文档
#----------------------------ps:讲到头部姿态的时候可以打开
# as
#haar人脸识别分类器数据位置
= "xml/.xml"
#眼睛识别,提高准确率
= "xml/.xml"
#窗口命名
= "Face "
#定义人脸识别分类器
= cv2.()
if .empty() :
raise (' to load the face xml file')
#定义眼睛检测分类器
= cv2.()
if .empty() :
raise (' to load the eye xml file')
#年龄
=['(0, 2)','(4, 6)','(8, 12)','(15, 20)','(25, 32)','(38, 43)','(48, 53)','(60, 100)']
#性别
=['Male','']
#得到性别识别器
#----------------------------ps:讲到年龄,性别的时候可以打开
#=.()
#得到年龄识别器
#----------------------------ps:讲到年龄,性别的时候可以打开
# = .()
#人脸识别画框
def (frame,scale):
#算法开始时间
= ..now()
#将原图转化为灰度图片
= cv2.(frame,cv2.)
#灰度直方图均衡化
= cv2.()
#改变图像大小,使用双线性差值
rows, cols = .shape
#缩小灰度图片加速计算
= cv2.(,(int(round(cols/scale)),round(int(rows/scale))),=cv2.)
#人脸侦测
faces = .(,1.1,2,cv2.,(30, 30))
index=int(1)
for in faces:
x,y,w,h =
#左上角
= (int(round(x * scale)),int(round(y * scale)))
#右上角
= (int(round((x+w-1) * scale)),int(round((y+h-1) * scale)))
#人脸映像
= [int(round(y * scale)):int(round((y+h-1) * scale)), int(round(x * scale)):int(round((x+w-1) * scale))]
#三维人脸映像
= frame[int(round(y * scale)):int(round((y+h-1) * scale)), int(round(x * scale)):int(round((x+w-1) * scale))]
#眼睛识别
eyes = .(,1.1,2,cv2.,(30, 30))
if len(eyes) !=2 :
#得到角度参数
#----------------------------ps:讲到头部姿态的时候可以打开
#pitch,yaw,roll= .()
#print(pitch,yaw,roll)
#得到性别
#----------------------------ps:讲到年龄,性别的时候可以打开
# = .([])
#print([[0].()])
#得到年龄
#----------------------------ps:讲到年龄,性别的时候可以打开
# = .([])
#print([[0].()])
#得到所有表情参数
#----------------------------ps:讲到表情识别的时候可以打开
#=.()
#得到最大值位置
#----------------------------ps:讲到表情识别的时候可以打开
# = np.()
#画正方形
cv2.(frame,,,(0, 0, 255),2,8)
#标记
cv2.(frame,str(index),,cv2.,2.0,(0, 0, 255))
#----------------------------ps:讲到表情识别的时候可以打开
#cv2.(frame,.[],,cv2.,1.0,(0, 0, 255))
index+=1
cv2.(,frame)
#算法结束时间
= ..now()
print ( - )
#---
#main
#初始化窗口
cv2.(,cv2.)
= cv2.(0)
while(.()):
ret, frame = .read()
#判断是否最后一帧
if ret:
(frame,2.0)
#按q退出程序
if cv2.(30) & 0xFF == ord('q'):
break
#释放视频
.()
cv2.()
效果图
model.py
这是我参考的两篇文章,第一篇是参考代码文章,第二篇是作者的文章,第三篇是安装keras教程,这是训练好的结果,所以可以直接调用,这时我测试部分就不写了,直接使用参考代码文章代码即可测试。
这时需要将作者上的文件夹下载,并放置刚刚的目录结构中。利用以下代码即可测试
安装keras
具体请按照这篇文章进行操作
代码
# -*- : utf-8 -*-
"""
on Wed Oct 18 15:36:48 2017
@:
"""
cv2
sys
json
time
numpy as np
from keras.
="real-r-"
#动作表情
#愤怒,害怕,开心,伤心,惊喜,平静
= ['angry', 'fear', 'happy', 'sad', '', '']
# load json and model arch
= open(+'/model.json','r')
= .read()
.close()
print("加载keras模型成功")
model = ()
# load into new model
model.(+'/model.h5')
print("加载权重成功")
#定义预测函数
def ():
= cv2.(, (48,48), = cv2.)
# cv2.(str(index)+'.png', )
image = .(1, 1, 48, 48)
= model.(image, =1, =1)
angry, fear, happy, sad, , = [prob for lst in for prob in lst]
[angry, fear, happy, sad, , ]
# = cv2.('C:/Users////real-r-//happy-fear.png')
# = cv2.(, cv2.)
#angry, fear, happy, sad, , = ()
效果图
这时候还记得我们main.py,有----------------------------ps:标记吗,将----------------------------ps:讲到表情识别的时候可以打开下面的语句全部打开,然后运行main.py
.py
头部姿态识别我是按照这篇文章来进行使用的,这是原版的作者的文章,其实人家写的真够详细了,各种demo都告诉你怎么用了,直接调用就好,人家模型都是训练好的了,直接用就好。
这时需要将作者上的文件夹下载,并放置刚刚的目录结构中。利用以下代码即可测试,记得把文件夹名字改成我这个,不过也无所谓啦,就是个路径问题,当然自己去修改一下代码路径也是没问题的。测试代码我就不讲了,作者的文章上清清楚楚写了demo,自己写一遍测试一下即可。
安装dlib
打开 ,输入如下命令,安装dlib
conda -c conda-forge dlib=19.4
注意: 这是我折腾最久的,我不知道你是否能安装上,我是参考了几篇文章都无法装上,然后不知道搜了哪个位置的文章,使用一条命令就把dlib装上了。如果不行的话,我也推荐我之前参考的文章的链接去试试,但我并没有成功,总说什么不对。然后就放弃了。我用的材料是.57.0,.8.2,.4.0
代码
# -*- : utf-8 -*-
"""
on Wed Oct 18 20:10:15 2017
@:
"""
as tf
from ..
#图像大小设定
width = 64
= 64
sess = tf.()
or = (sess)
or.("/etc///pitch/.tf")
or.("/etc///yaw/")
or.("/etc///roll/.tf")
#输入的图像大小必须要相等(64>=x,64>=x,3),x代表输入
def ():
# = cv2.(, (width,), = cv2.)
pitch = or.()
yaw = or.()
roll = or.()
[pitch,yaw,roll]
效果图
这时候还记得我们main.py,有----------------------------ps:标记吗,将----------------------------ps:讲到头部姿态的时候可以打开下面的语句全部打开,然后运行main.py
这时我多加了一个语句
输出便如下图了
.py
年龄,性别识别部分我是参照我是参考该第一篇作者的文章,利用的是caffe神经网络框架,不过新的caffe好像还是会出问题,所以我还是会一步步让大家运行我的整份代码,第二篇修改caffe的文章。不用紧张,我们继续一步步来。
这是需要将作者的整份代码下载下来,放文件根目录下
这时候还没完成呢,还需要作者已经训练好的模型放到这个文件中。这个文章还是原作者模型的参考文章,有时间还是好好看看。
我下载的是作者最原始的训练好的模型,下完完成之后解压,创建一个文件名为s的文件,把解压缩文件全部放进去。
安装caffe
网上很少有+.5的caffe安装,就算有,也是特别麻烦,还有各种编译的烦事,还不一定成功,得谢谢第二篇文章上知乎上朋友的回答,2个回答的朋友已经告诉你怎么把caffe放到中调用了,当然如果你不想编译,真得谢天谢地。第一篇文章已经提供了的预编译版本,开心吧。接下来我再来一步一步的说该怎么装
首先打开第一篇文章,下载caffe到我们程序根目录当中
因为代码中并不需要添加到环境当中所以我就不需要演示怎么放进环境中了,其实代码已经声明路径添加上去罢了。
修改caffe
参考文章
打开caffe//caffe/io.py 第258行,修改成以下代码
if ms != self.[in_][1:]:
= self.[in_][1:]
m_min, m_max = mean.min(), mean.max()
= (mean - m_min) / (m_max - m_min)
mean = (.((1,2,0)),[1:]).((2,0,1)) * (m_max - m_min) + m_min
#raise ('Mean shape with input shape.')
打开caffe//caffe/.py 第96行,修改成以下代码
代码
os
numpy as np
. as plt
= './caffe/'
sys
sys.path.(0, + '')
caffe
plt.['.'] = (10, 10)
plt.['image.'] = ''
plt.['image.cmap'] = 'gray'
='./g-/s/mean.'
= open(, "rb").read()
a = caffe.io...()
mean = caffe.io.(a)[0]
"""
='./g-/s/.'
='./g-/s/.'
= caffe.(, ,
mean=mean,
=(2,1,0),
=255,
=(256, 256))
d='./g-/s/.'
e='./g-/s/.'
= caffe.(e, d,
mean=mean,
=(2,1,0),
=255,
=(256, 256))
"""
def ():
='./g-/s/.'
='./g-/s/.'
= caffe.(, ,
mean=mean,
=(2,1,0),
=255,
=(256, 256))
def ():
d='./g-/s/.'
e='./g-/s/.'
= caffe.(e, d,
mean=mean,
=(2,1,0),
=255,
=(256, 256))
"""
= ()
=['(0, 2)','(4, 6)','(8, 12)','(15, 20)','(25, 32)','(38, 43)','(48, 53)','(60, 100)']
=['Male','']
= './g-/s/.jpg'
= caffe.io.()
print(.shape)
_ = plt.()
= .([])
print (' :', [[0].()])
"""
效果图
这时候还记得我们main.py,有----------------------------ps:标记吗,将#----------------------------ps:讲到年龄,性别的时候可以打开下面的语句全部打开,然后运行main.py
可以看到性别是,年龄在(38-43)区间。。 我曹,我是女的,还那么老。。
五,总结
上面都是很基础的东西,只是个乱调用,但是很快就做出模型来,可以满足一下小心脏,当然,如果要自己去研究这东西,这是最好的,我是没什么心思搞这个方向,所以我更想快点能调用来使用。但是这个程序速度跑起来有点慢,如果大家有什么好建议的话,可以留言给我,如果在配置上还出了些什么问题,也可以留言,我基本每天都上一下简书的。
最后还有一份性别,年龄代码。我是参考了这篇文章的代码,可是训练出来的模型很有问题,梯度一直没下降,而且调用的时候也各种出状况,我跑了2天的数据,一点卵用也没,待我好好看看,我再整理一下,先保留着。
os
glob
as tf
from .. *
from .s.
numpy as np
from
#年龄区间
=['(0, 2)','(4, 6)','(8, 12)','(15, 20)','(25, 32)','(38, 43)','(48, 53)','(60, 100)']
#性别
=['f','m'] # f:女; m:男
# AGE==True 训练年龄模型,False,训练性别模型
AGE = False
if AGE == True:
#获取长度
= len() # 年龄
else:
#获取长度
= len() # 性别
= 'on'
#拼接路径
= os.path.join(, '.txt')
= os.path.join(, '.txt')
= os.path.join(, '.txt')
= os.path.join(, '.txt')
= os.path.join(, '.txt')
= os.path.join(, '')
#拼接路径
def ():
#数据集存储
= []
with open(, 'r') as f:
#用于标记第一行,第一行数据全部是名称,全部不读
= True
for line in f:
tmp = []
#如果是第一行,继续
if == True:
= False
#获取所在文件编号
tmp.(line.split('\t')[0])
#获取对应图片名称
tmp.(line.split('\t')[1])
#获取年龄区间
tmp.(line.split('\t')[3])
#获取性别
tmp.(line.split('\t')[4])
#查看对应文件夹是否存在
= os.path.join(, tmp[0])
#如果存在
if os.path.():
#获取该文件所有图片
= glob.glob( + "/*.jpg")
#查找图片是否在这批文件中
for in :
if tmp[1] in :
break
#将数据挂载到内存
if AGE == True:
if tmp[2] in :
.([, .index(tmp[2])])
else:
if tmp[3] in :
.([, .index(tmp[3])])
#返回数据集
"""
#------读取数据
= ..now()
#读取所有文件的数据集
= ()
= ()
= ()
= ()
= ()
#合并所有数据
= + + + +
#打乱数据
()
= ..now()
print ("完成读取数据时间:"+str( - ))
#------读取数据
"""
# 缩放图像的大小
= 227
= 227
# 读取缩放图像
#待放入字符串
= tf.(dtype=tf.)
#待解码jpg图片
= tf.image.(, =3)
#对待读取图片重置size
= tf.image.(, [, ])
#优化转换
= tf.cast(, tf.uint8) / 255
#读取图片并重置图片数据
def ():
#读取图片
with tf.gfile.(, 'rb') as f:
= f.read()
#加载程序
with tf.() as sess:
image = sess.run(, ={: })
image
#批量数据处理
= 0
def (, =128):
= []
= []
for i in range():
.(([][0]))
.([][1])
+= 1
,
#分批大小
# = 128
= 1
#总个数
# = len() //
= 1
print("总共的batch数量---"+str())
#输入的数据大小
X = tf.(dtype=tf., shape=[, , , 3])
#输出数据大小
Y = tf.(dtype=tf.int32, shape=[])
def (, , pkeep=1.0):
= tf...(0.0005)
with tf.("", "", [],reuse=True) as scope:
with tf..slim.([, ], =, =tf.(1.), =tf.lizer(=0.005), =True):
with tf..slim.([], =tf.lizer(=0.01)):
conv1 = (, 96, [7,7], [4, 4], ='VALID', =tf.(0.), scope='conv1')
pool1 = (conv1, 3, 2, ='VALID', scope='pool1')
norm1 = tf.nn.(pool1, 5, alpha=0.0001, beta=0.75, name='norm1')
conv2 = (norm1, 256, [5, 5], [1, 1], ='SAME', scope='conv2')
pool2 = (conv2, 3, 2, ='VALID', scope='pool2')
norm2 = tf.nn.(pool2, 5, alpha=0.0001, beta=0.75, name='norm2')
conv3 = (norm2, 384, [3, 3], [1, 1], =tf.(0.), ='SAME', scope='conv3')
pool3 = (conv3, 3, 2, ='VALID', scope='pool3')
flat = tf.(pool3, [-1, 384*6*6], name='')
full1 = (flat, 512, scope='full1')
drop1 = tf.nn.(full1, pkeep, name='drop1')
full2 = (drop1, 512, scope='full2')
drop2 = tf.nn.(full2, pkeep, name='drop2')
with tf.('',reuse=True) as scope:
= tf.(tf.([512, ], mean=0.0, =0.01), name='')
= tf.(tf.(0.0, shape=[], dtype=tf.), name='')
= tf.add(tf.(drop2, ), , name=scope.name)
"""
def ():
= (, X)
def (eta, ):
= tf.(0, =False)
optz = lr: tf.train.(lr, 0.9)
= lr, : tf.train.(lr, , 100, 0.97, =True)
tf...(, , eta, optz, =4., fn=)
def loss(, ):
= tf.nn.( = , = )
= tf.()
s = tf.(tf..S)
= + 0.01 * sum(s)
= tf.train.rage(0.9)
= .apply([] + [])
with tf.([]):
= tf.()
# loss
= loss(, Y)
#
= (0.001, )
saver = tf.train.Saver(tf.())
with tf.() as sess:
sess.run(tf.())
epoch = 0
while True:
print("start-----"+str(epoch))
= 0
for batch in range():
= ..now()
, = (, )
_, = sess.run([, ], ={X:, Y:})
print(epoch, batch, )
= ..now()
print ("一次batch时间训练:"+str( - ))
saver.save(sess, './age.ckpt' if AGE == True else './sex.ckpt')
epoch += 1
print("end-----"+str(epoch))
()
"""
# 检测性别和年龄
# 把改为1
def ():
= (, X)
saver = tf.train.Saver()
with tf.() as sess:
saver.(sess, './age.ckpt' if AGE == True else './sex.ckpt')
= tf.nn.()
res = sess.run(, ={X:[()]})
res = np.(res)
if AGE == True:
[res]
else:
[res]
print(("1.jpg"))