最近,物体识别已经成为计算机视觉和AI最令人激动的领域之一。即时地识别出场景中所有的物体的能力似乎已经不再是秘密。随着卷积神经网络架构的发展,以及大型训练数据集和高级计算技术的支持,计算机现在可以在某些特定设置(例如人脸识别)的任务中超越人类的识别能力。
分类: 神经网络
Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
目前为止发现的性能最好,效果最好的人脸探测以及对齐的论文就是MTCNN了。
完整论文如下
继续阅读Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
Ubuntu 16.04开启dlib对于AVX或者CUDA的支持
最近在使用openface来测试人脸识别,实际过程中发现识别速度非常缓慢,平均每帧的识别速度达到了秒级水平,这个是不可接受的。跟踪代码性能,发现是dlib部分非常缓慢。
根据dlib的文档,默认使用
| 1 | $ sudo pip install dlib | 
安装的dlib库,由于对具体硬件的要求(CPU需要支持AVX指令集),是没有开启AVX指令加速的,另外由于显卡的要求,也是默认不开启CUDA的支持。
如果想要开启这部分加速,需要手工编译安装才可以,具体操作如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $ cd ~ $ mkdir dlib $ sudo pip download dlib $ tar -zxvf tar -zxvf dlib-*.tar.gz $ cd dlib* #安装依赖的库 $ sudo apt-get -y install libopenblas-dev #移除我们以前安装过的dlib $ sudo pip uninstall dlib #开启AVX指令集支持 $ sudo python setup.py install --yes USE_AVX_INSTRUCTIONS | 
上面的命令是使用AVX指令加速功能的,如果机器上安装了CUDA,则需要正确安装cuDNN 5.0以上的版本,否在编译的时候会报告
| 1 2 3 4 | -- Checking if you have the right version of cuDNN installed. -- *** Found cuDNN, but it looks like the wrong version so dlib will not use it. *** -- *** cuDNN V5.0 OR GREATER NOT FOUND.  DLIB WILL NOT USE CUDA. *** -- *** If you have cuDNN then set CMAKE_PREFIX_PATH to include cuDNN's folder. | 
对于使用
| 1 | $ sudo apt install nvidia-cuda-toolkit | 
安装的CUDA-7.5来说,可以从这里下载cuDNN v6.0 (April 27, 2017), for CUDA 7.5,下载完成后,整个目录中的include目录中的文件解压缩到/usr/local/include/目录下,lib64目录中的内容整个解压缩到/usr/lib/目录下,并且在/usr/local/lib/目录下建立libcudnn.so的软链接
| 1 | $ sudo ln -s /usr/lib/libcudnn.so /usr/local/lib/libcudnn.so | 
都配置正确后,使用如下编译命令安装:
| 1 | $ sudo python setup.py install --yes DLIB_USE_CUDA | 
参考链接
Easily Create High Quality Object Detectors with Deep Learning
执行"luarocks install cutorch"发生错误"error: implicit declaration of function 'THLongStorage_calculateExpandGeometry'"
执行
| 1 | $ luarocks install cutorch | 
发生如下错误:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | [ 88%] Building C object lib/THC/CMakeFiles/THC.dir/THCStorageCopy.c.o In file included from generic/THCTensor.c:1:0,                  from /tmp/luarocks_cutorch-scm-1-8069/cutorch/lib/THC/THCGenerateAllTypes.h:17,                  from /tmp/luarocks_cutorch-scm-1-8069/cutorch/lib/THC/THCTensor.c:7: /tmp/luarocks_cutorch-scm-1-8069/cutorch/lib/THC/generic/THCTensor.c: In function ‘THCudaByteTensor_newExpand’: /tmp/luarocks_cutorch-scm-1-8069/cutorch/lib/THC/generic/THCTensor.c:304:3: error: implicit declaration of function ‘THLongStorage_calculateExpandGeometry’ [-Werror=implicit-function-declaration]    THLongStorage_calculateExpandGeometry(tensor->size,    ^ [ 90%] Building C object lib/THC/CMakeFiles/THC.dir/THCThreadLocal.c.o cc1: some warnings being treated as errors lib/THC/CMakeFiles/THC.dir/build.make:686: recipe for target 'lib/THC/CMakeFiles/THC.dir/THCTensor.c.o' failed make[2]: *** [lib/THC/CMakeFiles/THC.dir/THCTensor.c.o] Error 1 CMakeFiles/Makefile2:172: recipe for target 'lib/THC/CMakeFiles/THC.dir/all' failed make[1]: *** [lib/THC/CMakeFiles/THC.dir/all] Error 2 Makefile:127: recipe for target 'all' failed make: *** [all] Error 2 Error: Build error: Failed building. | 
解决方法为:
| 1 2 | $ luarocks install torch $ luarocks install cutorch | 
参考链接
error: implicit declaration of function ‘THLongStorage_calculateExpandGeometry’
编译Torch 7时遇到错误"make[2]: *** [lib/THNN/CMakeFiles/THNN.dir/init.c.o] Error 1"
编译Torch 7时执行
| 1 | $ sudo luarocks install nn | 
遇到如下错误信息:
| 1 | make[2]: *** [lib/THNN/CMakeFiles/THNN.dir/init.c.o] Error | 
原因是缺少依赖包torch导致的,在安装nn之前需要先安装torch即可解决问题。
如下方式执行:
| 1 2 | $ sudo luarocks install torch $ sudo luarocks install nn | 
参考链接
编译Torch 7时执行luarocks install提示"Error: No results matching query were found."
编译Torch 7时执行luarocks install 提示错误信息:
| 1 | Error: No results matching query were found. | 
这个是由于系统上安装了多个luarocks而执行安装命令的并不是Torch 7代码目录下自带的luarocks导致的。
修正的办法就是设置搜索路径,把Torch 7代码目录下的install/bin/放到搜索目录(PATH)的最前面。
参考链接
luarocks install *错误之Error: No results matching query were found.
ubuntu 16.04 LTS使用开源面部识别库Openface
Openface是一个基于深度神经网络的开源人脸识别系统。该系统基于谷歌的文章FaceNet: A Unified Embedding for Face Recognition and Clustering。Openface是卡内基梅隆大学的Brandon Amos主导的。
1.准备系统环境
如果是服务器版本的ubuntu,可能默认Python都没有安装
| 1 2 3 4 5 6 7 8 9 10 11 12 | #如果没有安装python的话,执行最小安装命令即可,目前我们需要的是Python2 $ sudo apt-get install python-minimal $ sudo apt-get install python-pip $ sudo pip install --upgrade pip #如果没有安装git的话,此处需要手工安装 $ sudo apt-get install git #编译dlib时候需要 $ sudo apt-get install cmake $ sudo apt-get install libboost-dev $ sudo apt-get install libboost-python-dev | 
2.下载代码
| 1 | $ git clone https://github.com/cmusatyalab/openface.git | 
3.安装opencv
		| 1 2 | $ sudo apt-get install libopencv-dev $ sudo apt-get install python-opencv | 
4.安装依赖的python库
		| 1 2 3 4 | $ cd openface $ pip install -r requirements.txt $ sudo pip install dlib $ sudo pip install matplotlib | 
5.安装Torch7
参考链接 ubuntu 16.04 LTS上安装Torch7
编译完成后,路径变量被加入了.bashrc,我们需要刷新一下Shell的环境变量
| 1 2 | # 使 torch7 设置的刚刚的环境变量生效 source ~/.bashrc | 
6.安装依赖的lua库
		| 1 2 3 4 5 6 7 8 | $ luarocks install dpnn #下面的为选装,有些函数或方法可能会用到 $ luarocks install image $ luarocks install nn $ luarocks install graphicsmagick $ luarocks install torchx $ luarocks install csvigo | 
7.编译代码
| 1 2 | $ python setup.py build $ sudo python setup.py install | 
8.下载预训练后的数据
| 1 2 3 | $ sh models/get-models.sh #参考 https://cmusatyalab.github.io/openface/models-and-accuracies/ 下载对应的模型 $ wget https://storage.cmusatyalab.org/openface-models/nn4.v1.t7 -O models/openface/nn4.v1.t7 | 
9.执行测试Demo
执行的脚本face_detect.py代码如下:
| 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | #!/usr/bin/env python2 import argparse import cv2 import os import dlib import numpy as np np.set_printoptions(precision=2) import openface from matplotlib import cm fileDir = os.path.dirname(os.path.realpath(__file__)) modelDir = os.path.join(fileDir, '..', 'models') dlibModelDir = os.path.join(modelDir, 'dlib') if __name__ == '__main__':     parser = argparse.ArgumentParser()     parser.add_argument(         '--dlibFacePredictor',         type=str,         help="Path to dlib's face predictor.",         default=os.path.join(             dlibModelDir,             "shape_predictor_68_face_landmarks.dat"))     parser.add_argument(         '--networkModel',         type=str,         help="Path to Torch network model.",         default='models/openface/nn4.v1.t7')     # Download model from:     # https://storage.cmusatyalab.org/openface-models/nn4.v1.t7     parser.add_argument('--imgDim', type=int,                         help="Default image dimension.", default=96)     # parser.add_argument('--width', type=int, default=640)     # parser.add_argument('--height', type=int, default=480)     parser.add_argument('--width', type=int, default=1280)     parser.add_argument('--height', type=int, default=800)     parser.add_argument('--scale', type=int, default=1.0)     parser.add_argument('--cuda', action='store_true')     parser.add_argument('--image', type=str,help='Path of image to recognition')     args = parser.parse_args()     if (None == args.image) or (not os.path.exists(args.image)): 	print '--image not set or image file not exists' 	exit()     align = openface.AlignDlib(args.dlibFacePredictor)     net = openface.TorchNeuralNet(         args.networkModel,         imgDim=args.imgDim,         cuda=args.cuda)     cv2.namedWindow('video', cv2.WINDOW_NORMAL)     frame = cv2.imread(args.image)       bbs = align.getAllFaceBoundingBoxes(frame)     for i, bb in enumerate(bbs): 	# landmarkIndices set  "https://cmusatyalab.github.io/openface/models-and-accuracies/"         alignedFace = align.align(96, frame, bb,                                       landmarkIndices=openface.AlignDlib.OUTER_EYES_AND_NOSE)         rep = net.forward(alignedFace)         center = bb.center()         centerI = 0.7 * center.x * center.y / \                 (args.scale * args.scale * args.width * args.height)         color_np = cm.Set1(centerI)         color_cv = list(np.multiply(color_np[:3], 255))         bl = (int(bb.left() / args.scale), int(bb.bottom() / args.scale))         tr = (int(bb.right() / args.scale), int(bb.top() / args.scale))         cv2.rectangle(frame, bl, tr, color=color_cv, thickness=3)     cv2.imshow('video', frame)     cv2.waitKey (0)       cv2.destroyAllWindows() | 
在Shell中如下执行代码:
| 1 | $ python demos/face_detect.py --image=xx.jpeg | 
识别完成后会弹出识别到的面部图片。
ubuntu 16.04 LTS上安装Torch7
1.安装luarocks
| 1 | $ sudo apt-get install luarocks | 
2.安装torch
| 1 2 3 | $ git clone https://github.com/torch/distro.git ~/torch --recursive $ cd ~/torch; bash install-deps; $ ./install.sh | 
如果要使用NVIDIA CUDA加速版本的Torch7则使用如下方法
1.安装luarocks
| 1 | $ sudo apt-get install luarocks | 
2.下载NVIDIA CUDA适配的代码
| 1 | $ git clone https://github.com/torch/cutorch.git | 
3.安装编译依赖的库
| 1 | $ sudo apt install nvidia-cuda-toolkit | 
4.编译代码
| 1 2 3 4 5 | $ cd cutorch $ mkdir build $ cd build $ cmake .. $ make | 
参考链接
macOS Sierra (10.12.4)系统上Caffe借助现有的模型训练自己的数据集
Caffe代码中自带一些模型的例子,这些例子在源代码的models目录下,这些都是其他项目中用来训练的配置文件,学习的时候,我们没有必要完全自己从头到尾搭建自己的网络模型,而是直接使用例子中的模型,后期在这些模型上简单调整一下,一般可以满足大多数的需求。
下面我们以models/bvlc_alexnet目录下的模型配置文件为例子,训练我们自己的神经网络。
Caffe用训练好的caffemodel来进行分类
caffe程序自带有一张小猫图片,存放路径为caffe根目录下的examples/images/cat.jpg, 如果我们想用一个训练好的caffemodel来对这张图片进行分类,那该怎么办呢? 如果不用这张小猫图片,换一张别的图片,又该怎么办呢?如果学会了小猫图片的分类,那么换成其它图片,程序实际上是一样的。
开发caffe的贾大牛团队,利用imagenet图片和caffenet模型训练好了一个caffemodel,供大家下载。要进行图片的分类,这个caffemodel是最好不过的了。所以,不管是用C++来进行分类,还是用python接口来分类,我们都应该准备这样三个文件:
1. caffemodel文件
可以直接在浏览器里输入地址下载,也可以运行脚本文件下载。下载地址:http://dl.caffe.berkeleyvision.org/bvlc_reference_caffenet.caffemodel
文件名称为:bvlc_reference_caffenet.caffemodel,文件大小为230M左右,为了代码的统一,将这个caffemodel文件下载到caffe根目录下的models/bvlc_reference_caffenet/文件夹下面。也可以运行脚本文件进行下载:
| 1 | $ ./scripts/download_model_binary.py models/bvlc_reference_caffenet | 
2. 均值文件
有了caffemodel文件,就需要对应的均值文件,在测试阶段,需要把测试数据减去均值。这个文件我们用脚本来下载,在caffe根目录下执行:
| 1 | $ sh ./data/ilsvrc12/get_ilsvrc_aux.sh | 
执行并下载后,均值文件放在 data/ilsvrc12/ 文件夹里。
3. synset_words.txt文件
在调用脚本文件下载均值的时候,这个文件也一并下载好了。里面放的是1000个类的名称。
数据准备好了,我们就可以开始分类了,我们给大家提供两个版本的分类方法:
一. C++方法
在caffe根目录下的examples/cpp-classification/文件夹下面,有个classification.cpp文件,就是用来分类的。当然编译后,放在/build/examples/cpp_classification/下面
我们就直接运行命令:
| 1 2 3 4 5 6 | # sudo ./build/examples/cpp_classification/classification.bin \   models/bvlc_reference_caffenet/deploy.prototxt \   models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel \   data/ilsvrc12/imagenet_mean.binaryproto \   data/ilsvrc12/synset_words.txt \   examples/images/cat.jpg | 
命令很长,用了很多的\符号来换行。可以看出,从第二行开始就是参数,每行一个,共需要4个参数
运行成功后,输出top-5结果:
| 1 2 3 4 5 6 | ---------- Prediction for examples/images/cat.jpg ---------- 0.3134 - "n02123045 tabby, tabby cat" 0.2380 - "n02123159 tiger cat" 0.1235 - "n02124075 Egyptian cat" 0.1003 - "n02119022 red fox, Vulpes vulpes" 0.0715 - "n02127052 lynx, catamount" | 
即有0.3134的概率为tabby cat, 有0.2380的概率为tiger cat ......
二. python方法
python接口可以使用jupyter notebook来进行可视化操作,因此推荐使用这种方法。
在这里我就不用可视化了,编写一个py文件,命名为py-classify.py
| 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 | #coding=utf-8 #加载必要的库 import numpy as np import sys,os #设置当前目录 caffe_root = '/home/xxx/caffe/'  sys.path.insert(0, caffe_root + 'python') import caffe os.chdir(caffe_root) net_file=caffe_root + 'models/bvlc_reference_caffenet/deploy.prototxt' caffe_model=caffe_root + 'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel' mean_file=caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy' net = caffe.Net(net_file,caffe_model,caffe.TEST) transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) transformer.set_transpose('data', (2,0,1)) transformer.set_mean('data', np.load(mean_file).mean(1).mean(1)) transformer.set_raw_scale('data', 255)  transformer.set_channel_swap('data', (2,1,0)) im=caffe.io.load_image(caffe_root+'examples/images/cat.jpg') net.blobs['data'].data[...] = transformer.preprocess('data',im) out = net.forward() imagenet_labels_filename = caffe_root + 'data/ilsvrc12/synset_words.txt' labels = np.loadtxt(imagenet_labels_filename, str, delimiter='\t') top_k = net.blobs['prob'].data[0].flatten().argsort()[-1:-6:-1] for i in np.arange(top_k.size):     print top_k[i], labels[top_k[i]] | 
对于macOS Sierra (10.12.3)来说,需要设置python环境,(参考源代码中的python/requirements.txt),如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #切换到我们自己安装的python版本,系统自带版本会在安装插件时候由于权限问题而失败 $ brew install python #安装必要的python包 $ sudo pip install Cython $ sudo pip install numpy $ sudo pip install scipy #只能安装编译好的包,源代码安装失败 $ sudo pip install scikit-image $ sudo pip install matplotlib $ sudo pip install ipython $ sudo pip install h5py $ sudo pip install leveldb $ sudo pip install networkx $ sudo pip install nose $ sudo pip install pandas $ sudo pip install python-dateutil $ sudo pip install protobuf $ sudo pip install python-gflags $ sudo pip install pyyaml $ sudo pip install Pillow $ sudo pip install six | 
执行这个文件,输出:
| 1 2 3 4 5 | 281 n02123045 tabby, tabby cat 282 n02123159 tiger cat 285 n02124075 Egyptian cat 277 n02119022 red fox, Vulpes vulpes 287 n02127052 lynx, catamount | 
caffe开发团队实际上也编写了一个python版本的分类文件,路径为 python/classify.py
运行这个文件必需两个参数,一个输入图片文件,一个输出结果文件。而且运行必须在python目录下。假设当前目录是caffe根目录,则运行:
| 1 2 | $ cd python $ sudo python classify.py ../examples/images/cat.jpg result.npy | 
分类的结果保存为当前目录下的result.npy文件里面,是看不见的。而且这个文件有错误,运行的时候,会提示
| 1 | Mean shape incompatible with input shape | 
的错误。因此,要使用这个文件,我们还得进行修改:
1.修改均值计算:
定位到
| 1 | mean = np.load(args.mean_file) | 
这一行,在下面加上一行:
| 1 | mean=mean.mean(1).mean(1) | 
则可以解决报错的问题。
2.修改文件,使得结果显示在命令行下:
定位到
| 1 2 3 4 | # Classify.     start = time.time()     predictions = classifier.predict(inputs, not args.center_only)     print("Done in %.2f s." % (time.time() - start)) | 
这个地方,在后面加上几行,如下所示:
| 1 2 3 4 5 6 7 8 9 |   # Classify.     start = time.time()     predictions = classifier.predict(inputs, not args.center_only)     print("Done in %.2f s." % (time.time() - start))     imagenet_labels_filename = '../data/ilsvrc12/synset_words.txt'     labels = np.loadtxt(imagenet_labels_filename, str, delimiter='\t')     top_k = predictions.flatten().argsort()[-1:-6:-1]     for i in np.arange(top_k.size):         print top_k[i], labels[top_k[i]] | 
就样就可以了。运行不会报错,而且结果会显示在命令行下面。