目录
基于 BP 神经网络算法的性别识别 1
目录 1
1.背景介绍 2
2. OpenCV 的介绍 3
3.安装 OpenCV 4
4. BP 神经网络算法介绍和实践 4
4.1 BP 神经网络结构 4
4.2 BP 算法原理 5
𝜕𝜕𝑛𝑛𝑢𝑢𝑡𝑡 6
2. 修正权值 8
4.3 BP 算法收敛性 8
5.结果展示 8
2.OpenCV 的介绍

OpenCV 是一个基于 BSD 许可(开源)发行的跨平台计算机视觉库,可以运行在 Linux、
Windows、Android 和 Mac OS 操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了 Python、Ruby、MATLAB 等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV 用 C++语言编写,它的主要接口也是 C++语言,但是依然保留了大量的 C 语言接口。该库也有大量的 Python、Java and MATLAB/OCTAVE(版本 2.5)的接口。这些语言的 API 接口函数可以通过在线文档获得。如今也提供对于 C#、Ch、Ruby,GO 的支持。
OpenCV 具有模块化结构,这就意味着开发包里面包含多个共享库或者静态库。下面是可使用的模块:
1.核心功能(Core functionality):一个紧凑的模块,定义了基本的数据结构,包括密集的多维 Mat 数组和被其他模块使用的基本功能。
2.图像处理(Image processing):一个图像处理模块,它包括线性和非线性图像滤波,几何图形转化(重置大小,放射和透视变形,通用基本表格重置映射),色彩空间转 换,直方图等。
3.影像分析(video):一个影像分析模块,它包括动作判断,背景弱化和目标跟踪算法。
4.3D 校准(calib3d):基于多视图的几何算法,平面和立体摄像机校准,对象姿势判断,立体匹配算法,和 3D 元素的重建。
5.平面特征(features2d):突出的特征判断,特征描述和对特征描述的对比。
6.对象侦查(objdetect):目标和预定义类别实例化的侦查(例如:脸、眼睛、杯子、人、汽车等等)。

7.highgui:一个容易使用的用户功能界面。
8.视频输入输出(videoio):一个容易使用的视频采集和视频解码器。
9.GPU:来自不同 OpenCV 模块的 GPU 加速算法。
10.一些其他的辅助模块,比如 FLANN 和谷歌的测试封装,Python 绑定和其他。

3.安装 OpenCV

我们利用 python 里面已有的库来安装 OpenCV。Python 是一种计算机程序设计语言。是一种动态的、面向对象的脚本语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。
我们只需要通过 pip 或者 anaconda 安装 OpenCV 包就可以通过导入包并使用。

4.BP 神经网络算法介绍和实践

BP 神经网络通常是指基于误差反向传播算法( Back Propagation, 简称 BP 算法)的多层前向神经网络 ( Multi-laye Feed-forward Neural Networks, MFNN),它最初是由 Paul
Werboss 在 1974 年提 出, 但未在传播,直到 20 世纪 80 年代中期 Rumelhart、Hinton 和Williams, David Parker 和 Yann Le Cun 重新发现了 BP 算法,同时因此算法被包括在《并行分布处理》(Parallel Distributed Processing),此算法才广为人知。本文转载自http://www.biyezuopin.vip/onews.asp?id=14996目前 BP 算法已成为应用最广泛的神经网络学习算法,据统计有近 90%的神经网络应用是基于 BP 算法的。BP 网络的神经元采用的传递函数通常是 Sigmoid 型可微函数,所以可以实现输入和输出间的任意非线性映射,这使得它在诸如信号处理、计算机网络、过程控制、语音识别、函数逼近、模式识别及数据压缩等领域均取得了成功的应用。

from PIL import Image
import dlib
import cv2
import os.path
import PIL.Image
from pylab import *
import os
import numpy as np
import shutil
'''
    通过BP神经网络学习图片并检测性别
'''
'''参数选择'''
picture_show=0          #是否显示照片
pixel=40                #像素大小
pixel_mat=pixel*pixel   #像素总个数
file_num=0              #文件数量
photonum=0              #照片总数量
boy_photonum=0          #男生照片总数量
girl_photonum=0         #女生照片总数量

'''路径选择'''
girlpath = '../beauty'      #女孩照片路径,用于训练
boypath = '../nan'          #男孩照片路径,用于训练
photopath = '../faces'      #截取彩色照片路径
graypath = '../grayfaces'   #黑白照片路径
numpath= '../faces'         #用于读取照片数量路径

def deletphoto(dir):
    delList = os.listdir(dir)
    for f in delList:
        filePath = os.path.join(dir, f)
        if os.path.isfile(filePath):
            os.remove(filePath)
            print(filePath + " was removed!")
        elif os.path.isdir(filePath):
            shutil.rmtree(filePath, True)
            print('Directory: " + filePath +"was removed!')

'''
    利用别人写好的人脸分类器来截取图片中的人脸,并保存到spath中
    i:截取图片保存名
    path:原图片路径
    spath:处理过后图片路径
'''

def get_face_from_photo(i,path,spath):
    detector = dlib.get_frontal_face_detector()     #获取人脸分类,采用dlib进行人脸识别,dlib更多的人脸识别模型,可以检测脸部68甚至更多的特征点
    filenames = os.listdir(path)                    # 读取path路径下的图片,获得所有的图片名字
    for f1 in filenames:
        f = os.path.join(path,f1)
        img = cv2.imread(f, cv2.IMREAD_COLOR)
        iimag = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))       #转换文件格式
        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)                 #保存裁切后的图片
            if(picture_show==0):
                print(i)
            i +=1
            cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 3)
            if(picture_show==1):
                cv2.namedWindow(f, cv2.WINDOW_AUTOSIZE)
                cv2.imshow(f, img)

    print("read_ok")
    if(picture_show==1):
        k = cv2.waitKey(0)
        cv2.destroyAllWindows()
    return i

'''
    将人脸图片转化为pixel*pixel的灰度图片
    path:人脸图片
    spath:灰度图片
'''
def change_photo_size(path,spath):
    filenames = os.listdir(path)
    for filename in filenames:
        f = os.path.join(path,filename)
        iimag = PIL.Image.open(f).convert('L').resize((pixel,pixel))
        savepath = os.path.join(spath,filename)
        iimag.save(savepath)

'''
    读取训练图片
    k:照片数量
    photo_path:照片保存的路径
'''
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'))
        im1 = im1.reshape((pixel_mat,1))
        if i == 0:                              #把所有的图片灰度值放到一个矩阵中,一列代表一张图片的信息
            im = im1
        else:
            im = np.hstack((im,im1))
    return im

'''
    sigmoid函数实现
'''
def layerout(w,b,x):
    y = np.dot(w,x) + b
    t = -1.0*y
    y = 1.0/(1+exp(t))
    return y

'''
    训练样本:百度的图片。女生标签为0,男生标签为1.
    训练方法:简单的梯度下降法
    参考:https://blog.csdn.net/yunyunyx/article/details/80539222
'''

'''
设置一个隐藏层,为每张照片像素值-->pixel_mat    隐藏层神经元个数-->1
输入为每张图片的灰度像素矩阵
x_train:训练样本的像素数据
y_train:训练样本的标签
w:输出层权重
b:输出层偏置
w_h:隐藏层权重
b_h:隐藏层偏置
step:循环步数

'''
def mytrain(x_train,y_train):

    step=int(input('mytrain迭代步数:'))
    a=double(input('学习因子:'))
    inn = pixel_mat                                 #输入神经元个数
    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(photonum)
        x_train = x_train[:,r]
        y_train = y_train[:,r]
        for j in range(photonum):
            x = np.mat(x_train[:,j])
            x = x.reshape((pixel_mat,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))                        #计算输出单元误差项,y->tk
            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))                                                #从隐藏层到输出层的dw
            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
'''
    预测结果pre大于0.5,为男;预测结果小于或等于0.5为女
'''
def mytest(x_test,w,b,w_h,b_h):

    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!")
    return  pre



'''主函数'''
deletphoto(photopath)
deletphoto(graypath)
#框出人脸,并保存到faces中,i为保存的名字
i = 0
i = get_face_from_photo(i,girlpath,photopath)       #女孩
girl_photonum=i
print(girl_photonum)
i = get_face_from_photo(i,boypath,photopath)        # 男孩
boy_photonum=i-girl_photonum
print(boy_photonum)
change_photo_size(photopath,graypath)               #将人脸图片转化为28*28的灰度图片
photonum=(len([lists for lists in os.listdir(numpath) if os.path.isfile(os.path.join(numpath, lists))]))      #获取图片数量
print(photonum)
im = read_photo_for_train(photonum,graypath)

#归一化
immin = im.min()
immax = im.max()
im = (im-immin)/(immax-immin)
x_train = im

#制作标签,女生为0,男生为1
y1 = np.zeros((1,girl_photonum))
y2 = np.ones((1,boy_photonum))
y_train = np.hstack((y1,y2))

#开始训练
print("----------------------开始训练-----------------------------------------")
w,b,w_h,b_h = mytrain(x_train,y_train)
print("-----------------------训练结束------------------------------------------")

# 测试
print("--------------------视频测试-----------------------------------------")
camera= cv2.VideoCapture(0)
while(True):
    ret, f = camera.read()                                          #图片来自视频中读取的内容
    detector = dlib.get_frontal_face_detector()                     #获取人脸分类,采用dlib进行人脸识别,dlib更多的人脸识别模型,可以检测脸部68甚至更多的特征点
    iimag = Image.fromarray(cv2.cvtColor(f, cv2.COLOR_BGR2RGB))     #把灰度处理后的图片进行处理,把OpenCV转换成PIL.Image格式
    counts = detector(f, 1)                                         # 人脸检测
    for index, face in enumerate(counts):                           # 在图片中标注人脸,并显示
        left = face.left()
        top = face.top()
        right = face.right()
        bottom = face.bottom()
        region = (left, top, right, bottom)
        cropImg = iimag.crop(region)                                #将识别出的人脸提取出来
        finaImg=cropImg.convert('L').resize((pixel,pixel))          #把大小统一转换成28*28像素
        im1 = array(finaImg)
        im1 = im1.reshape((pixel_mat, 1))
        im = im1
        #归一化
        immin = im.min()
        immax = im.max()
        im = (im - immin) / (immax - immin)
        i=0
        x_test = im
        xx = x_test[:, i]
        xx = xx.reshape((pixel_mat, 1))
        mytest(xx, w, b, w_h, b_h)
        pre=mytest(xx, w, b, w_h, b_h)
        font = cv2.FONT_HERSHEY_SIMPLEX                             # 使用默认字体
        if pre > 0.5:
            img = cv2.putText(f, 'man', (left, top - 30), font, 1.2, (255, 255, 255),2)  # 添加文字,1.2表示字体大小,(0,40)是初始的位置,
            # 保存

        else:
            img = cv2.putText(f, 'girl', (left, top - 30), font, 1.2, (255, 255, 255), 2)  # 添加文字,1.2
        cv2.rectangle(f, (left, top), (right, bottom), (0, 255, 0), 2)
    cv2.imshow("camera", f)
    if cv2.waitKey(1) & 0xff == ord("q"):
        break
camera.release()
cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐