基于OpenCV和Keras实现人脸识别系列手记:
项目完整代码参见Github仓库。
本篇是上面这一系列手记的第一篇。原本发表在慕课网上,不知何故现在看不到了,在这里重发一下给需要的人。
最近打算做一个人脸识别的项目来巩固一下卷积神经网络的知识,项目要用到OpenCV,第一次接触OpenCV,一边看已有实现的项目代码一边查文档和教程。学到了很多,也打算写一系列手记记录自己在这个项目中用到和学到的知识点。
这篇手记从OpenCV中对图像的一些基本操作开始。
自己的电脑是笔记本,win10 64位系统,首先安装Anaconda这个用于科学计算和数据处理分析的Python包和环境管理工具,Anaconda自带Spyder这个适合数据科学的Python IDE,同时还有Ananconda Navigator这个图形界面可以很方便地安装和更新Opencv、Tensorflow、Keras、numpy等常用的包。
安装Anaconda也很简单,只要去官方网站下载win10 64位的安装程序即可,注意安装过程中要选择把Anaconda添加到系统环境变量,我试过第一次安装时没有添加,后续使用有问题,后来又重装了一遍。
基本环境:Python 3.6.3、Opencv 3.4.1
小tips:Spyder IDE菜单栏的ToolsPreferenceKeyboard shortcuts里可以找到一些常用的快捷键,加速代码编写。
OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。OpenCV可用于解决如下领域的问题:
- 增强现实
- 人脸识别
- 手势识别
- 人机交互
- 动作识别
- 运动跟踪
- 物体识别
- 图像分区
- 机器人
OpenCV功能强大,内容众多,一口气吃不成个大胖子,我就从最简单的图片操作开始学习。
import cv2 # 首先引入openCV
img = cv2.imread('smile.jpeg',0) # 读取图片
cv2.imread
就是读取图片的函数,这个函数有两个参数,第一个参数是图片名称,注意,图片要在程序的工作目录下,否则就要给出图片文件完整的绝对路径,第二个参数指定图片读取的方式,有1、0、-1三种取值,含义如下:
cv2.IMREAD_COLOR
,默认值,读入彩色图片,忽略透明度cv2.IMREAD_GRAYSCALE
,以灰度模式读取图片cv2.IMREAD_UNCHANGED
,读入彩色图片,并保持透明度信息cv2.namedWindow('smile', cv2.WINDOW_NORMAL) # 创建一个名为smile的窗口,第二个参数,cv2.WINDOW_NORMAL生成一个可以手动缩放的窗口,这个flag默认是cv2.WINDOW_AUTOSIZE,窗口会自动适应图片大小,如果图片太大可能无法完全显示,就最好用cv2.WINDOW_NORMAL。
cv2.imshow('smile',img) # 显示图片在刚创建的窗口里,,两个参数分别是要用来显示图片的窗口的名字和要显示的图片。
注意这里是先创建了一个窗口再将图片显示在这个窗口里,直接用imshow
也会创建一个窗口,但窗口只能自动适应图片大小,无法手动缩放,因此没有先创建窗口再显示灵活。
接下来要注意一个刚开始学OpenCV时很可能会遇到的问题,我也是最近打算修改这篇手记时无意中发现的,如果在这里直接开始运行程序,会发现窗口中显示不出来图片,而且程序无响应。要正常显示图片,需要在后面加上waitkey
语句才行,具体如下:
k = cv2.waitKey(0) # waitKey的功能是等待一定的时间,如果等待时间内有按键操作就继续执行后面的语句,如果没有按键就在等待时间到后继续执行后面的语句。时间以ms为单位
实践发现,waitKey参数为0的时候窗口不会自动关闭,无限等待按键,假如设为10000,也就是10s,不做任何操作的情况下大概15s左右窗口自动关闭,15s内有按键操作窗口也会关闭。
我Google了一下,发现遇到前面的问题是因为highgui没有给予imshow绘制处理的时间,所以图片无法显示出来(这里我作为OpenCV的初学者也还没搞懂),加了waitkey
以后,程序等待按键,从而给了imshow
时间来显示图片。OpenCV官方对这个问题的解释如下:
A common mistake for opencv newcomers is to call cv::imshow() in a loop through video frames, without following up each draw with cv::waitKey(30). In this case, nothing appears on screen, because highgui is never given time to process the draw requests from cv::imshow().
接着给出响应按键后的程序:
if k & 0xFF == 27: # wait for ESC key to exit,注意这里的0xFF是64位系统必须的
cv2.destroyAllWindows() # 关闭所有窗口
如果按了ESC键,就关闭所有窗口。
# ord函数返回字符的ASCII或则和Unicode数值,这里返回的是ASCII值
elif k & 0xFF == ord('s'): # wait for 's' key to save and exit,ord函数返回字符对应的ASCII数值或者 Unicode 数值。
print (k)
cv2.imwrite('smile1.jpg',img)
cv2.destroyAllWindows()
这里在按了‘s’键后会将图片以smile1.jpg为名保存在工作目录下,然后关闭窗口。
在图片的读取、显示和存储的基础上,OpenCV还提供了图片的像素级操作的基本功能,这里选取一些人脸识别项目中可能用上的功能,包括:
numpy.ndarray
所支持的更灵活(相对于Python List)的索引方式访问图片中某个像素值和某个区域:import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('smile.jpeg') # 读入图片返回的是一个numpy的n维数组
print (type(img)) # ,type函数返回对象类型
px = img[100,100] # [4 5 3]
print (px) # 4
# accessing only blue pixel
blue = img[100,100,0]
print (blue)
# modify the pixel values
img[100,100] = [255,255,255]
print (img[100,100]) # [255 255 255]
# 上面的索引方式通常用来选择多行多列组成的区域,比如在图片中单独选择出人脸区域。
# 要获取单独一个像素,用numpy.ndarray.item
# accessing the RED value
print (img.item(10,10,2)) # 3
# modifying RED value
img.itemset((10,10,2),100)
print (img.item(10,10,2)) # 100
print (img.shape) # (4192, 3104, 3)
print(img.size) # 39035904,4192*3104*3
print(img.dtype) # uint8,8位无符号整数
cv2.copyMakeBorder()
函数来实现:# making borders for images(padding)
BLUE = [255,0,0]
# top, bottom, left, right分别是各个边padding的宽度,cv2.BORDER_CONSTANT是一种border type,表示用相同的颜色填充
constant = cv2.copyMakeBorder(img, 100,100,100,100, cv2.BORDER_CONSTANT, value = BLUE)
cv2.imshow('show',constant)
cv2.waitKey(0)
cv2.destroyAllWindows()
以上就是OpenCV中图片的一些基本操作,大家可以在自己的电脑上用自己的图片去尝试以上函数的不同参数会有什么结果,这里主要参考了OpenCV的英文教程,喜欢看官方英文原版的小伙伴可以去参考资料里的链接去看英文原版,那里有更丰富的内容,看英文头疼的就可以参考这篇手记了。
刚接触OpenCV直接看项目代码的时候会有点头大,不过有了官方教程和文档,就能慢慢上手了。
图片操作是视频操作的基础,后续的人脸识别需要用到笔记本电脑的摄像头来捕获人脸,这就涉及到OpenCV中的视频操作,在下一篇手记使用OpenCV通过摄像头捕获实时视频并探测人脸里会介绍OpenCV中视频的基本操作,以及实现从摄像头实时视频流中捕获人脸的功能。
本作品采用知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。要查看该许可协议,可访问 http://creativecommons.org/licenses/by-nc-sa/4.0/ 或者写信到 Creative Commons, PO Box 1866, Mountain View, CA 94042, USA。