写在前面:本实验用到的图片均来自google图片,侵删!


实验介绍

用python手写一个简单bp神经网络,实现人脸的性别识别。由于本人的机器配置比较差,所以无法使用网上很红的人脸大数据数据集(如lfw数据集等等),所以我从google图片下载了一些中国明星的照片来作为本次实验的数据集。

  • 训练数据集:5位中国的男明星(每个明星10张),6位中国的女明星(每个明星10张)。

  • 测试数据集:6张女生,6张男生

实验环境

  • win10

  • python3.5+opencv+dlib+PIL

  • 说明:上面涉及到的库都可以用pip install #### 轻易下载,但要注意它们之间的关联性,被依赖的库要先安装好。直接google就会有更详细的安装教程哦,所以这里不详说。。

实验步骤

1 下载图片,构成数据集

我随机从google图片中下载了5位男明星的图片和6位女明星的图片。男明星的图片放在/photo/boys文件中,女明星的图片放在/photo/girls文件中。

然后,我又随机从google图片中下载了6张‘女生’的图片和6张‘男生’的图片,分别放在/girltest文件和/boytest文件中

男明星:



女明星:

2 框出人脸,并保存人脸区域

利用别人写好的人脸分类器来截取图片中的人脸,并把从训练集中截取到的人脸放到/faces中。图片排序为0.jpg,1.jpg…从女明星的图片开始读起,然后男明星的接上。具体函数对应get_face_from_photo()函数。

人脸分类器下载:人脸分类器

框住人脸:





保存下来的人脸区域:

3 将人脸图片灰度化,且改为28*28大小

具体看函数change_photo_size28()

灰度化后的部分图集:

4 训练

4.1 读取图片的灰度值矩阵

读取图片的灰度值矩阵,读取出来的矩阵为(28,28)的,变为(784,1)的,然后把所有图片的的灰度值矩阵叠加成一个大的矩阵。

具体介绍参照:参考1参考2

4.2 训练、
  • 梯度下降法

  • sigmoid函数

具体介绍参照:参考1

参考2

5 测试

测试图片的前期处理和训练图片的前期处理一样,先框出人脸,再灰度化和改变大小为28*28。

男生测试集:



女生测试集

规定预测出来的pre>0.5为男生,否则为女生。

完整代码

# -*- coding:utf-8 -*-
'''
内容:训练图片处理和人脸识别的训练部分
作者:surecheun
邮箱:surecheun@163.com
版本:1.0
'''
from PIL import Image
import sys
import dlib
import cv2
import os
import os.path
import numpy as np
import PIL.Image
from pylab import * def get_face_from_photo(i,path,spath):
'''
利用别人写好的人脸分类器来截取图片中的人脸,并保存到spath中
分类器下载:https://github.com/opencv/opencv/tree/master/data/haarcascades
参考:官方文档
'''
detector = dlib.get_frontal_face_detector() #获取人脸分类
# 读取path路径下的图片,获得所有的图片名字
filenames = os.listdir(path) for f1 in filenames:
f = os.path.join(path,f1)
iimag = PIL.Image.open(f)
# opencv 读取图片,并显示
img = cv2.imread(f, cv2.IMREAD_COLOR) b, g, r = cv2.split(img) # 分离三个颜色通道
img2 = cv2.merge([r, g, b]) # 生成新图片 counts = detector(img, 1) #人脸检测 for index, face in enumerate(counts): # 在图片中标注人脸,并显示
left = face.left()
top = face.top()
right = face.right()
bottom = face.bottom() #保存人脸区域
j =str(i)
j = j+'.jpg'
save_path = os.path.join(spath,j)
region = (left,top,right,bottom)
#裁切图片
cropImg = iimag.crop(region) #保存裁切后的图片
cropImg.save(save_path)
i +=1 cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 3)
cv2.namedWindow(f, cv2.WINDOW_AUTOSIZE)
cv2.imshow(f, img) # 等待按键,退出,销毁窗口
k = cv2.waitKey(0)
cv2.destroyAllWindows()
return i def change_photo_size28(path,spath):
'''
将人脸图片转化为28*28的灰度图片
''' filenames = os.listdir(path) for filename in filenames:
f = os.path.join(path,filename)
iimag = PIL.Image.open(f).convert('L').resize((28,28))
savepath = os.path.join(spath,filename)
#savepath = spath + '/' + filename
iimag.save(savepath) def read_photo_for_train(k,photo_path):
'''
读取训练图片
'''
for i in range(k):
j = i
j = str(j)
st = '.jpg'
j = j+st
j = os.path.join(photo_path,j)
im1 = array(Image.open(j).convert('L'))
#(28,28)-->(28*28,1)
im1 = im1.reshape((784,1))
#把所有的图片灰度值放到一个矩阵中
#一列代表一张图片的信息
if i == 0:
im = im1
else:
im = np.hstack((im,im1))
return im def layerout(w,b,x): '''
sigmoid函数实现
''' y = np.dot(w,x) + b
t = -1.0*y
# n = len(y)
# for i in range(n):
# y[i]=1.0/(1+exp(-y[i]))
y = 1.0/(1+exp(t))
return y def mytrain(x_train,y_train):
'''
训练样本:中国某些明星的google图片(106张,女60张,男46张),侵删。女生标签为0,男生标签为1.
训练方法:简单的梯度下降法
参考(本人博客另一篇):https://blog.csdn.net/yunyunyx/article/details/80539222
''' '''
设置一个隐藏层,784-->隐藏层神经元个数-->1
''' step=int(input('mytrain迭代步数:'))
a=double(input('学习因子:'))
inn = 784 #输入神经元个数
hid = int(input('隐藏层神经元个数:'))#隐藏层神经元个数
out = 1 #输出层神经元个数 w = np.random.randn(out,hid)
w = np.mat(w)
b = np.mat(np.random.randn(out,1))
w_h = np.random.randn(hid,inn)
w_h = np.mat(w_h)
b_h = np.mat(np.random.randn(hid,1)) for i in range(step):
#打乱训练样本
r=np.random.permutation(106)
x_train = x_train[:,r]
y_train = y_train[:,r]
#mini_batch
for j in range(100):
x = np.mat(x_train[:,j])
x = x.reshape((784,1))
y = np.mat(y_train[:,j])
y = y.reshape((1,1))
hid_put = layerout(w_h,b_h,x)
out_put = layerout(w,b,hid_put) #更新公式的实现
o_update = np.multiply(np.multiply((y-out_put),out_put),(1-out_put))
h_update = np.multiply(np.multiply(np.dot((w.T),np.mat(o_update)),hid_put),(1-hid_put)) outw_update = a*np.dot(o_update,(hid_put.T))
outb_update = a*o_update
hidw_update = a*np.dot(h_update,(x.T))
hidb_update = a*h_update w = w + outw_update
b = b+ outb_update
w_h = w_h +hidw_update
b_h =b_h +hidb_update return w,b,w_h,b_h def mytest(x_test,w,b,w_h,b_h):
'''
预测结果pre大于0.5,为男;预测结果小于或等于0.5为女
'''
hid = layerout(w_h,b_h,x_test);
pre = layerout(w,b,hid);
print(pre)
if pre > 0.5:
print("hello,boy!")
else:
print("hello,girl!") #训练 #框出人脸,并保存到faces中,i为保存的名字
i = 0
#女孩
path = 'C:\\Users\\yxg\\Desktop\\photo\\girls'
spath = 'C:\\Users\\yxg\\Desktop\\faces'
i = get_face_from_photo(i,path,spath)
#男孩
path = 'C:\\Users\\yxg\\Desktop\\photo\\boys'
i = get_face_from_photo(i,path,spath) #将人脸图片转化为28*28的灰度图片
path = 'C:\\Users\\yxg\\Desktop\\faces'
spath = 'C:\\Users\\yxg\\Desktop\\faces'
change_photo_size28(path,spath) #获取图片信息
im = read_photo_for_train(106,spath) #归一化
immin = im.min()
immax = im.max()
im = (im-immin)/(immax-immin) x_train = im #制作标签,前60张是女生,为0
y1 = np.zeros((1,60))
y2 = np.ones((1,46))
y_train = np.hstack((y1,y2)) #开始训练
print("----------------------开始训练-----------------------------------------")
w,b,w_h,b_h = mytrain(x_train,y_train)
print("-----------------------训练结束------------------------------------------") #测试
print("--------------------测试女生-----------------------------------------")
#框出人脸,并保存到girltests中,i为保存的名字
i = 0
#女孩测试集
path = 'C:\\Users\\yxg\\Desktop\\girltest'
spath = 'C:\\Users\\yxg\\Desktop\\girltests'
i = get_face_from_photo(i,path,spath) #将人脸图片转化为28*28的灰度图片
path = 'C:\\Users\\yxg\\Desktop\\girltests'
spath = 'C:\\Users\\yxg\\Desktop\\girltests'
change_photo_size28(path,spath) #获取图片信息
im = read_photo_for_train(6,spath) #归一化
immin = im.min()
immax = im.max()
im = (im-immin)/(immax-immin) x_test = im
#print(x_test.shape)
for i in range(6):
xx = x_test[:,i]
xx = xx.reshape((784,1))
mytest(xx,w,b,w_h,b_h)
print("---------------------测试男生-----------------------------")
#框出人脸,并保存到boytests中,i为保存的名字
i = 0
#男孩测试集
path = 'C:\\Users\\yxg\\Desktop\\boytest'
spath = 'C:\\Users\\yxg\\Desktop\\boytests'
i = get_face_from_photo(i,path,spath) #将人脸图片转化为28*28的灰度图片
path = 'C:\\Users\\yxg\\Desktop\\boytests'
spath = 'C:\\Users\\yxg\\Desktop\\boytests'
change_photo_size28(path,spath) #获取图片信息
im = read_photo_for_train(6,spath) #归一化
immin = im.min()
immax = im.max()
im = (im-immin)/(immax-immin) x_test = im
for i in range(6):
xx = x_test[:,i]
xx = xx.reshape((784,1))
mytest(xx,w,b,w_h,b_h)

测试结果

----------------------开始训练--------------------------------------
mytrain迭代步数:300
学习因子:0.26
隐藏层神经元个数:28
-----------------------训练结束--------------------------------------
--------------------测试女生-----------------------------------------
[[0.00435441]]
hello,girl!
[[0.00160697]]
hello,girl!
[[0.47261838]]
hello,girl!
[[0.00344136]]
hello,girl!
[[0.00057052]]
hello,girl!
[[0.00030406]]
hello,girl!
---------------------测试男生-----------------------------
[[0.27352905]]
hello,girl!
[[0.63632333]]
hello,boy!
[[0.60296128]]
hello,boy!
[[0.68961767]]
hello,boy!
[[0.98755486]]
hello,boy!
[[0.99023972]]
hello,boy!

看结果,发现效果不错:6张女生图片都被识别对了,而男生只有一个被识别错误。。

python手写bp神经网络实现人脸性别识别1.0的更多相关文章

  1. 基于深度学习的人脸性别识别系统(含UI界面,Python代码)

    摘要:人脸性别识别是人脸识别领域的一个热门方向,本文详细介绍基于深度学习的人脸性别识别系统,在介绍算法原理的同时,给出Python的实现代码以及PyQt的UI界面.在界面中可以选择人脸图片.视频进行检 ...

  2. Python语言编写BP神经网络

    Python语言编写BP神经网络 2016年10月31日 16:42:44 ldy944758217 阅读数 3135   人工神经网络是一种经典的机器学习模型,随着深度学习的发展神经网络模型日益完善 ...

  3. 手写BP(反向传播)算法

    BP算法为深度学习中参数更新的重要角色,一般基于loss对参数的偏导进行更新. 一些根据均方误差,每层默认激活函数sigmoid(不同激活函数,则更新公式不一样) 假设网络如图所示: 则更新公式为: ...

  4. C++开发人脸性别识别总结

    历时一个月,最终在昨天把<C++开发人脸性别识别总结>系列博客完毕了,第一篇博客发表在2015年12月29日,截止昨天2016年2月29日最后一篇完毕,去除中间一个月的寒假,正好一个月,首 ...

  5. C++开发人脸性别识别教程(3)——OpenCv配置和ImageWatch插件介绍

    OpenCv是C++图像处理的重要工具.这个人脸性别识别的项目就是借助OpenCv进行开发的. 尽管网上已经有了非常多关于OpenCv的配置教程,但出于教程完整性考虑.这里还是用专门的一篇博客来介绍O ...

  6. C++开发人脸性别识别教程(16)——视频人脸性别识别

    在之前的博文中我们已经可以顺利驱动摄像头来採集源图像.在这篇博文中将正式为其加入性别识别的代码,实现摄像头视频的人脸性别识别. 一.人脸检測 在得到摄像头採集的源图像之后,首先要做的就是对其进行人脸检 ...

  7. C++开发人脸性别识别教程(12)——加入性别识别功能

    经过之前几篇博客的解说,我们已经成功搭建了MFC应用框架,并实现了主要的图像显示和人脸检測程序,在这篇博文中我们要向当中加入性别识别代码. 关于性别识别,之前已经专门拿出两篇博客的篇幅来进行解说.这里 ...

  8. C++开发人脸性别识别教程(19)——界面美化

    在这篇博文中将完毕<C++开发人脸性别识别>的收尾工作.主要内容分为两部分:加入视频暂定功能.界面规范化. 一 视频暂停功能 严格来说这个视频暂定功能算是视频人脸性别识别的一个遗留问题,本 ...

  9. C++开发人脸性别识别教程(10)——加入图片的人脸检測程序

    现在我们的MFC框架已经初具规模,能够读取并显示目录下的图片.在这篇博文中我们将向当中加入人脸检測的程序. 一.人脸检測算法 这里我们使用OpenCv封装的Adaboost方法来进行人脸检測,參见:C ...

随机推荐

  1. 标签响应javascript的href处理[转载]

    为了给一个<a />标签绑定javascript,但又不让它跳转链接,大家习惯上用的都是 <a href="javascript:;" onclick=" ...

  2. OAuth认证协议原理分析及同步消息到Twitter和Facebook使用方法

    OAuth有什么用?为什么要使用OAuth? twitter或豆瓣用户一定会发现,有时候,在别的网站,点登录后转到 twitter登录,之后转回原网站,你会发现你已经登录此网站了,这种网站就是这个效果 ...

  3. 【BZOJ】2179: FFT快速傅立叶(fft)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2179 fft裸题.... 为嘛我的那么慢....1000多ms.. #include <cst ...

  4. 【BZOJ】1061: [Noi2008]志愿者招募(费用流+数学)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1061 好神的一题! 学会了一种建模方式: 当方程组内的任意变量都在其中两个方程出现且一正一负,可以建 ...

  5. 【NLP】新词发现

    http://www.csdn.net/article/2013-05-08/2815186 http://blog.csdn.net/yuyu2223/article/details/7725705 ...

  6. PHP正则表达式 /i, /s, /x,/u, /U, /A, /D, /S等模式修饰符

    i (PCRE_CASELESS) 如果设置了这个修饰符, 模式中的字母会进行大小写不敏感匹配. m (PCRE_MULTILINE) 默认情况下, PCRE认为目标字符串是由单行字符组成的(然而实际 ...

  7. 更改hadoop native库文件后datanode故障

    hadoop是用cloudra的官方yum源安装的,服务器是CentOS6.3 64位操作系统,自己写的mapreduce执行的时候hadoop会提示以下错误: WARN util.NativeCod ...

  8. Kafka+SpringMVC+Maven应用示例

    本文借助主流SpringMVC框架向大家介绍如何在具体应用中简单快捷的使用kafka.kafka.maven以及SpringMVC在现在的企业级应用中都占据着非常重要的地位,所以本文将三者结合起来也可 ...

  9. js 匿名函数-立即调用的函数表达式

    先提个问题, 单独写匿名函数为什么报错?return 匿名函数 为什么不报错? 如图: 第二种情况在 f 还没有执行的时候,就报错了,,,当然这得归因于函数声明语句声明提前(发生在代码执行之前)的原因 ...

  10. Hadoop伪分布安装详解(三)

    目录: 1.修改主机名和用户名 2.配置静态IP地址 3.配置SSH无密码连接 4.安装JDK1.7 5.配置Hadoop 6.安装Mysql 7.安装Hive 8.安装Hbase 9.安装Sqoop ...