机缘巧合下参与了人工智能工作室项目”树莓派进行人脸识别”,因此可以好好研究一下Python了。

对于Python,只能既爱又恨了。爱的是Python的强大,恨的是可惜看了几本书没能学好Python的开发。原因也是有的,不敲代码看书就是没毛用。
不过这次”树莓派进行人脸识别”项目负责软件代码方面,所以必须认真理解代码学习Python。
代码Demo参考
当然第一次接触这个Demo并没有认真理解清楚,所以我进行了以下的工作:

  • 介绍树莓派
  • 手把手教你如何用 OpenCV + Python 实现人脸识别
  • Python OS模块常用功能中文图文详解
  • Python time模块学习
  • Python模块picamera

介绍树莓派

借鉴
树莓派是一个职业信用卡大小的裸露电路板,它也是一个运行linux操作系统的完全可编程的PC系统。
当然在此,我们可以了解到可以完成大部分电脑能完成的事情:编辑office文档浏览网页玩游戏
当然设置它的配件:SD卡(预装系统)USB键盘和鼠标显示器WiFi适配器(USB无线网卡)…..其他就不说了,对硬件不感冒。
当然安装操作系统
准备工作和安装实战百科说的比较好哦!可以借鉴其他的。
启动成功的景象:

启动图片
不要说对树莓派没什么了解,说实话,在写这篇博客之前我也从未接触过它,不过并不担心我们对它的了解。

手把手教你如何用 OpenCV + Python 实现人脸识别

借鉴
这篇文章理解还是较简单的。无非三步:

  • OpenCV的Python环境搭建
  • 相关知识储备
  • 代码的实现人脸识别
OpenCV的Python环境搭建

借鉴
对于菜鸟的我来说,先了解OpenCV要紧,没办法百科了个答案:
大概意思就是OpenCv是一个跨平台计算机视觉库。用C++编写实现的一些功能的。
笼统的说吧就是它可以进行图像处理视觉操作,也就是让计算机有部分视觉功能吧!
当然今天我们主要使用Python来使用它。
首先只能安装OpenCV了,只能使用pip,什么还没安装,我也没有哦,看借鉴吧。

相关知识储备

Haar特征值反映了图像的灰度变化情况。
例如:脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。
opencv api
要想使用opencv,就必须先知道其能干什么,怎么做。于是API的重要性便体现出来了。就本例而言,使用到的函数很少,也就普通的读取图片,灰度转换,显示图像,简单的编辑图像罢了。
读取图片
只需要给出待操作的图片的路径即可。

1
2
import cv2
image = cv2.imread(imagepath)

灰度转换
灰度转换的作用就是:转换成灰度的图片的计算强度得以降低。

1
2
import cv2
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

画图
opencv 的强大之处的一个体现就是其可以对图片进行任意编辑,处理。 下面的这个函数最后一个参数指定的就是画笔的大小。

1
2
import cv2
cv2.rectangle(image,(x,y),(x+w,y+w),(0,255,0),2)

显示图像
编辑完的图像要么直接的被显示出来,要么就保存到物理的存储介质。

1
2
import cv2
cv2.imshow("Image Title",image)

获取人脸识别训练数据
看似复杂,其实就是对于人脸特征的一些描述,这样opencv在读取完数据后很据训练中的样品数据,就可以感知读取到的图片上的特征,进而对图片进行人脸识别。
这里卖弄的这个xml文件,就是opencv在GitHub上共享出来的具有普适的训练好的数据。我们可以直接的拿来使用。

1
2
import cv2
face_cascade = cv2.CascadeClassifier(r'./haarcascade_frontalface_default.xml')

探测人脸
说白了,就是根据训练的数据来对新图片进行识别的过程。

1
2
3
4
5
6
7
8
9
import cv2
# 探测图片中的人脸
faces = face_cascade.detectMultiScale(
gray,
scaleFactor = 1.15,
minNeighbors = 5,
minSize = (5,5),
flags = cv2.cv.CV_HAAR_SCALE_IMAGE
)

我们可以随意的指定里面参数的值,来达到不同精度下的识别。返回值就是opencv对图片的探测结果的体现。

处理人脸探测的结果
结束了刚才的人脸探测,我们就可以拿到返回值来做进一步的处理了。但这也不是说会多么的复杂,无非添加点特征值罢了。

1
2
3
4
import cv2
print "发现{0}个人脸!".format(len(faces))
for(x,y,w,h) in faces:
cv2.rectangle(image,(x,y),(x+w,y+w),(0,255,0),2)

代码的实现人脸识别

图片素材

具体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import cv2
# 待检测的图片路径
imagepath = r'./heat.jpg'
# 获取训练好的人脸的参数数据,这里直接从GitHub上使用默认值
face_cascade = cv2.CascadeClassifier(r'./haarcascade_frontalface_default.xml')
# 读取图片
image = cv2.imread(imagepath)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# 探测图片中的人脸
faces = face_cascade.detectMultiScale(
gray,
scaleFactor = 1.15,
minNeighbors = 5,
minSize = (5,5),
flags = cv2.cv.CV_HAAR_SCALE_IMAGE
)
print "发现{0}个人脸!".format(len(faces))
for(x,y,w,h) in faces:
# cv2.rectangle(image,(x,y),(x+w,y+w),(0,255,0),2)
cv2.circle(image,((x+x+w)/2,(y+y+h)/2),w/2,(0,255,0),2)
cv2.imshow("Find Faces!",image)
cv2.waitKey(0)

输出结果:
输出结果

代码理解:
就个人而言,上述代码在我的IDE里面运行时绝对有错误的。
不过嘛,有幸我还是完成的这个小小案例。
所有先贴上自己代码,然后就不用理解了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# coding:utf-8
import sys
#reload(sys)
#sys.setdefaultencoding('utf8')
type = sys.getfilesystemencoding() #处理字符编码进行修改
import cv2
imagepath = r'./1.jpg'# 待检测的图片路径
# 获取训练好的人脸的参数数据,这里直接从GitHub上使用默认值
face_cascade = cv2.CascadeClassifier(r'./haarcascade_frontalface_default.xml')
# 读取图片
image = cv2.imread(imagepath)
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#灰化
###探测图片中的人脸
faces = face_cascade.detectMultiScale(
gray,#进行检测的图像,这里是转换后的
scaleFactor = 1.15,#距离相机不同的距离
minNeighbors = 5,#对检测点周边多少有效点
minSize = (5,5),#检测点的最小值,或者说就是检测点的最终值
#这个参数在新版的opencv是不需要的,暂时不管了,注释掉同样可以
#flags = cv2.cv.CV_HAAR_SCALE_IMAGE#相反不1注释却有错
)
#设置参数,达到识别。返回值就是opencv对图片的探测结果的体现。
print "发现{0}个人脸!".decode('utf-8').encode(type).format(len(faces)) #记住人脸的数量
for(x,y,w,h) in faces:
cv2.circle(image,((x+x+w)/2,(y+y+h)/2),w/2,(0,255,0),2)
#循环对人脸图片进行描绘
######个人测试数据
#x = 150
#y = 150
#w = 150
#######个人测试数据
#cv2.rectangle(image,(x,y),(x+w,y+w),(0,255,0),2)#
#######个人测试数据
cv2.imshow("find image",image)#展现图片
cv2.waitKey(0)#waitKey(0)表示这一帧在你按下任意键前始终显示

没办法个人代码就是这样,应该可以理解了。
查看可借鉴

Python OS模块常用功能中文图文详解

借鉴
OS模块在我的理解中他就类似于其他语言的文件处理模块吧,无非一些函数接口让你可以操作文件和目录,是不是很酷。
对于os我先不多介绍,只说明程序中需要理解的代码和基础模块而已。

1
2
3
4
5
6
import os #导入os模块
print os.getcwd() #获取当前路径
print os.listdir('/home/wwwroot') #列出目录下所有文件和文件夹
print os.mkdir('heihei') #创建一个heihei的目录
print os.rmdir('abc') #删除一个abc目录
print os.rename('abc.txt','readme.txt') #重命名一个文件

话说和linux命令查这么像呢,不管了。

Python time模块学习

借鉴
time模块是用于管理时间和日期的C库函数,这是因为它绑定到底层C实现,所有一些细节会基于具体的平台而不同。
说时间对于语言的时间我觉得就是烦,所有还是粗略了解。

  • time()
    返回纪元开始的秒数,返回为浮点数。

    1
    2
    3
    >>>import time
    >>>time.time()
    1495020286.013
  • ctime()
    返回友好的人类时间。

    1
    2
    3
    >>>import time
    >>>time.ctime()
    'Wed May 17 19:27:21 2017'
  • struct_time()
    用这个可以分开存储时间的各个部分,感觉对我可爱极了。
    gmtime()用于获取UTC(格林尼治)时间,localtime()用于获取当前时区的当前时间。

  • sleep()
    说实话,这个就相当于定时器,规定间隔多长时间在运行下面代码。
    1
    2
    import time
    time.sleep(5)

Python模块picamera

借鉴
单独理解picamera我还真不知道是什么,也可能就仅仅是一个Python模块吧!而它是用来操作树莓派摄像头的。
它的更多API介绍
当然在此我还是不去深究那强悍的API介绍了。


需修改

最简单的拍照

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[codesyntax lang="python"]
!/usr/bin/python
# from http://surenpi.com
# raspberry camera python example
import picamera
import time
cam = picamera.PiCamera()
cam.vflip = True
cam.capture('a.jpg')
cam.close()
print 'capture done.'

[/codesyntax]

录制视频

可以将视频保存到文件中或者其他地方,默认录制的时候是不会有预览的,可以通过调用start_preview函数来预览 [codesyntax lang=”python”]

1
2
3
4
5
6
7
8
9
10
11
import picamera
with picamera.PiCamera() as camera:
camera.resolution = (640, 480)
camera.start_preview()
camera.start_recording('suren.h264', format='h264', quantization=23, resize=(1024, 768))
camera.wait_recording(60)
camera.stop_recording()
camera.stop_preview()

[/codesyntax] start_recording(output, format=None, resize=None, **options) start_recording的参数只是一个字符串的话,会被当作是文件名;如果是个对象的话,会回调这个实例对象的write方法 录制的文件格式默认为h264。wait_recording函数规定了录制的时长。 要想关闭红灯显示的话,可以设置camera.led = False。

以上就是对人脸识别的小小见解。