MTCNN简单实践(Windows下happynear代码)
我的相关博客:
《Windows 7+Visual Studio 2015下Caffe安装(CPU/非GPU)》
《Windows 7+Visual Studio 2015下Caffe安装(GPU+Cuda 9.0+cuDNN 7.3)》
在初步安装好Caffe-CPU后,准备尝试实践一下MTCNN。
本机环境:笔记本、GTX970M的GPU、windows 7、VS2015、python 2.7、MATLAB R2015b。
参考博客从happynear的github上下载测试程序进行测试。
打开code/codes/vs/下的vs工程,一共有四个项目:MatMTCNN(生成可在Matlab中调用的库),PyCascadeFaceDetection(生成可在python中调用的库),TestCascadeCNN(生成exe可执行文件),testPyCascadeCNN(py文件,测试PyCascadeFaceDetection,vs中无法加载,可以删掉或不管)。
先试一下生成(Debug模式)前3个,都失败了。
一个一个来,matlab调用、python调用先不管,主要关注TestCascadeCNN,参考博客里的,将各个库、包含文件的路径进行配置。方便一下大家Copy。
TestCascadeCNN添加包含目录和库目录如下:
Include Directories
E:\study\ML\caffe-windows-ms\include
E:\study\ML\caffe-windows-ms\src
E:\study\ML\caffe-windows-ms\src\caffe
E:\study\ML\caffe-windows-ms\windows\caffe.binding
E:\study\ML\caffe-windows-ms\windows\thirdparty\Boost
E:\study\ML\caffe-windows-ms\windows\thirdparty\OpenCV\include
E:\study\ML\caffe-windows-ms\windows\thirdparty\OpenCV\include\opencv
E:\study\ML\caffe-windows-ms\windows\thirdparty\OpenCV\include\opencv2
E:\study\ML\caffe-windows-ms\windows\thirdparty\GFlags\Include
E:\study\ML\caffe-windows-ms\windows\thirdparty\GLog\include
E:\study\ML\caffe-windows-ms\windows\thirdparty\HDF5\include
E:\study\ML\caffe-windows-ms\windows\thirdparty\LEVELDB\include
E:\study\ML\caffe-windows-ms\windows\thirdparty\LMDB\include
E:\study\ML\caffe-windows-ms\windows\thirdparty\OpenBLAS\include
E:\study\ML\caffe-windows-ms\windows\thirdparty\Protobuf\include
Library Directories
E:\study\ML\caffe-windows-ms\windows\thirdparty\OpenCV\x64\vc14\lib
Additional Include Directories
E:\study\ML\caffe-windows-ms\windows\caffe.binding
E:\study\ML\caffe-windows-ms\windows\thirdparty\HDF5\include
E:\study\ML\caffe-windows-ms\windows\thirdparty\Boost
E:\study\ML\caffe-windows-ms\Build\x64\Release
E:\study\ML\caffe-windows-ms\windows\thirdparty\OpenCV\x64\vc14\bin
Additional Library Directories
E:\study\ML\caffe-windows-ms\windows\thirdparty\HDF5\lib
E:\study\ML\caffe-windows-ms\windows\thirdparty\OpenCV\x64\vc14\lib
Additional Dependencies
hdf5_tools.lib
hdf5_hl_fortran.lib
hdf5_fortran.lib
hdf5_hl_f90cstub.lib
hdf5_f90cstub.lib
hdf5_cpp.lib
hdf5_hl_cpp.lib
hdf5_hl.lib
hdf5.lib
E:\study\ML\caffe-windows-ms\Build\x64\Release\caffe.binding.lib
这里提一下,我一开始不是很懂设置这些目录的含义,看了一下这篇博文稍懂,主要关键的就是在写项目时,若要调用一个现成函数,首先,要在代码中include头文件(其中有函数调用声明),此时就需要设置在附加包含目录(包含目录)中设置头文件所在路径,其次,头文件中一般只有函数声明,函数实现在库文件(.lib)中(这里我的表述可能不完全专业,又涉及库的一些知识),因此,还要在链接过程中把lib加进去(将库文件完整名加入附加依赖项,将所在目录加入附加库目录),此时才可在代码中调用函数功能。
配置完后尝试生成TestCascadeCNN,碰到的其他问题是:
1、"This function or variable may be unsafe."。
解决方法:
在项目属性设置中找到选项卡配置属性→C/C++→预处理器;
在右侧的参数中找到预处理器定义,编辑其参数;
在参数的末尾添加定义_CRT_SECURE_NO_WARNINGS。
2、“模块计算机类型“x64”与目标计算机类型“X86”冲突。
解决方法:
将项目属性中的链接器->高级->目标计算机项设置为"MachineX64 (/MACHINE:X64)"即可。
3、build成功后运行出现了“计算机中丢失caffe.binding.dll”的问题。
按照博客的方案将...\caffe-windows-ms\Build\x64\Release目录加入系统环境变量Path中重启vs重新build即可。
4、但再次运行还是出错:“F0929 00:31:11.872000 11788 common.cpp:100] Cannot use GPU in CPU-only Caffe: check mode.”
之前考虑笔记本用GPU搞不动,现在到这里算是没办法了,可能不用GPU不行了,之前安装caffe时没有安装cuda,并不支持GPU。
下面在成功安装Caffe-GPU后继续。
再次安装好Caffe-GPU后,再次尝试实践MTCNN。
打开项目CascadeCNN.sln,生成TestCascadeCNN。
生成成功,但运行后会出现错误。在vs中中断调试,发现错误出现在
CHECK_NE(fd, -1) << "File not found: " << filename;
查看递归调用,问题出在运行caffe环境中的CaffeBinding.cpp中的AddNet函数时:
int CaffeBinding::AddNet(string model_definition, string weights, int gpu_id)
其中,变量model_definition中保存的是网络模型在机器上的所在路径,weights是对应权值的路径,此函数应该是读取参数添加一层网络。在进入此函数之前中,上述2个参数值没问题,参数内容为对应路径的字符串表示,关键是进入此函数后,两个string类型值中的字符串内容变为了空。
此错误令我很烦,仔细检查包含目录、库目录、附件依赖项等是否出错,无果。网上搜索求解基本无果。
至此,已经耗时已久,本打算放弃,但还是没有。接着烦恼了一会,发现我生成时用的是Debug模式,这会不会是问题呢?
试试便知,改为Release模式,重新配置包含目录、库目录、附件依赖项等内容,生成,OK。运行!还是失败了。。。出现了新的问题:
OpenCV Error: Assertion failed (ssize.area() > 0) in cv::resize
次日调试发现是跑到这一句时出现了错误
Mat image = imread("E:\\study\\ML\MTCNN_happy\\code\\codes\\vs\\test.jpg");
将其中“\\”改为“/”后终于生成并运行成功了,哭晕。。其实细心的朋友应该发现了,上面错误代码中有一处双斜杠打成了单斜杠(输入个路径都打错,怪自己眼瞎呀,这里顺便提示小白,别拿着代码就跑啊,至少里面的输入输出文件路径得改成自己机器对应的哟),后面测试“\\”或“/”都是ok的。
至此happynear的MTCNN vs版总算是跑通了,简单测试结果如下。
事后想想为什么Release模式成功了,Debug就不行,实在是令人费解,为什么参数值到函数里就没了,在网上查找中文资料收获不大,其中看起来比较相关的回答是这个,这里就不继续研究了,如有大神清楚,烦请指点。
在之前提到打算放弃后的一小段时间,尝试跑了跑官方的matlab版MTCNN,happynear的代码中也有(MTCNNv1、MTCNNv2、camera_demo)
除Matlab+caffe环境外,还需要装一个matlab工具包pdollar_toolbox,安装比较简单。直接在matlab中运行MTCNNv1、MTCNNv2中的demo.m代码及camera_demo中的test.m代码。其中MTCNNv1、MTCNNv2成功,camera_demo失败,原因是MATLAB无法跟摄像头连上,需要装一些支持,而下载要MATLAB账号,我嫌麻烦就没弄了,见谅。(这里提示代码中的caffe路径、pdollar路径都要设置为自己机器上的文件路径)
最后再尝试build另外两个项目:MatMTCNN(生成可在Matlab中调用的库),PyCascadeFaceDetection(生成可在python中调用的库)。
MatMTCNN:
原项目属性中配置了包含目录、附件包含目录、库目录、附件库目录、附加依赖项等,其中各项的值需要按照自己机器相应改动(主要是caffe-windows及matlab相关的目录),改完后即可生成成功,生成MatMTCNN.mexw64可在MATLAB中调用,这里没有继续深入进行具体测试。
PyCascadeFaceDetection:
同样,原项目属性中配置了包含目录、附件包含目录、库目录、附件库目录、附加依赖项等,其中各项的值需要按照自己机器相应改动(主要是caffe-windows及python相关的目录)。
改完后生成失败,具体问题有2个问题。
第一个报语法错误:
...\pycascadefacedetection\CascadeFaceDetection.h(31): error C2061: 语法错误: 标识符“vector”
...\pycascadefacedetection\CascadeFaceDetection.h(31): error C2143: 语法错误: 缺少“)”(在“{”的前面)
...\pycascadefacedetection\CascadeFaceDetection.h(31): error C2059: 语法错误:“,”
...\pycascadefacedetection\CascadeFaceDetection.h(31): error C2059: 语法错误:“)”
...\pycascadefacedetection\CascadeFaceDetection.h(31): error C2238: 意外的标记位于“;”之前
...\pycascadefacedetection\CascadeFaceDetection.h(31): error C2143: 语法错误: 缺少“;”(在“}”的前面)
原因是CascadeFaceDetection.h头文件中没有#include <vector>,加入如下代码即可:
#include <vector>
using std::vector;
第二个错误:
错误:
python_module.cpp(40): error C2440: “初始化”: 无法从“overloaded-function”转换为“std::vector<FaceInception::FaceInformation,std::allocator<_Ty>> (__cdecl FaceInception::CascadeFaceDetection::* )(cv::Mat &,double,double)”
1> with
1> [
1> _Ty=FaceInception::FaceInformation
1> ]
1> python_module.cpp(40): note: 在匹配目标类型的范围内没有具有该名称的函数
所在代码:
std::vector<FaceInformation>(CascadeFaceDetection::*Predict_func0)(cv::Mat&, double, double) = &CascadeFaceDetection::Predict;
看代码意思是要定义一个函数指针向量,参数类型为生成(cv::Mat&, double, double),再看一下等号右边CascadeFaceDetection::Predict函数的声明:
std::vector<FaceInformation> Predict(cv::Mat& input_image, vector<double> thresholds = {0.6, 0.6, 0.7}, double min_face = 24.0);
PyObject* Predict(PyObject* input);
PyObject* Predict(PyObject* input, PyObject * confidence_threshold, PyObject * min_face);
可以看到Predict函数的参数类型应该是(cv::Mat&, vector<double>, double),因此会报错上述错误。
所以做如下改动:
std::vector<FaceInformation>(CascadeFaceDetection::*Predict_func0)(cv::Mat&, double, double) = &CascadeFaceDetection::Predict;
改为
std::vector<FaceInformation>(CascadeFaceDetection::*Predict_func0)(cv::Mat&, vector<double>, double) = &CascadeFaceDetection::Predict;
再次build,成功。
将PyCascadeFaceDetection.pyd改名为CascadeFaceDetection.pyd,修改testPyCascadeCNN.py中的模型路径及测试图片路径,运行对CascadeFaceDetection.pyd进行测试,如果没有正确安装opencv支持python的库,会报以下错误:
from .cv2 import *
ImportError: DLL load failed: 找不到指定的模块。
选择合适的cv库进行安装,pip install opencv-contrib-python安装即可,但还是可能报以上错误,这时可能是系统缺少某些dll文件导致的,参考这篇博客使用Dependency Walker打开安装的cv.pyd文件进行分析,发现缺少api-ms-win-downlevel-shlwapi-l1-1-0.dll,网上下载后将dll文件安装注册。
运行testPyCascadeCNN.py成功,但预测结果很奇怪,估计此代码也是未完成品。
总的来说,将happynear的MTCNN代码实际就算完成了。官方代码MTCNNv1、MTCNNv2测试成功,happynear的MTCNNc语言版TestCascadeCNN测试成功,python调用测试效果不佳,不知是不是我的操作问题。
内容、表述如有不当之处,望批评指正。
参考:
https://blog.****.net/chenyj92/article/details/53401555
https://github.com/happynear/MTCNN_face_detection_alignment
https://blog.****.net/u012043391/article/details/54972127
https://www.cnblogs.com/405845829qq/p/4108450.html
https://blog.****.net/u012534008/article/details/54602774
https://blog.****.net/u014805066/article/details/78143091
https://blog.****.net/qq_15987459/article/details/79533125
https://zhidao.baidu.com/question/1240291558950184859.html
https://blog.****.net/baidu_32173921/article/details/63252077
https://blog.****.net/jacke121/article/details/78205605
http://www.dependencywalker.com/
https://blog.****.net/yahstudio/article/details/81479462