每次一把辛酸泪的配置过程都忍不住写成博客想要分享给大家,花了我周末整整一天半什么别的事都没干从早上起床到晚上睡前都在整才搞定,不是为了比惨,而是想着方便后来的朋友们(虽然可能并不会有多少人看到),以及多年以后回顾一下还是会别有一番滋味在心头。这篇博客的定位是图文并茂的纯小白配置+使用教程,主要参考了这篇文章,在这基础之上加了一些出错处理并且细化了后面的运行教程。不废话了时间宝贵。
首先声明一下配置环境,请大家一定要注意自己各种软件的版本,根据自己的实际情况选择,不要盲从配置教程。
这个就真的帮不了了,上学期因为课程需要所以下载了OpenCV2.4.13,虽然配置过程也一把辛酸泪但是忘记记载下来了,上面提到的本文的参考博客也有写,可以作为参考。
下载地址:https://sourceforge.net/projects/boost/files/boost-binaries/1.58.0/
请一定要按照自己的VC版本下载对应的文件!按照自己的VC版本下载对应的文件!按照自己的VC版本下载对应的文件!重要的话说三遍。(才不会告诉大家我一路踩坑一共下了四个版本的boost)
安装过程中没什么需要注意的,就记住安装目录就好,花了挺长时间才安装完成。
然后需要添加环境变量:
看参考博客说好像是分为已编译版和未编译版,我其实也分不太清。刚开始以为下载的这个是已编译版,后来在运行代码的时候出错:
才发现依旧要自己编译一遍,具体方法如下:
1. 打开VS2013的开发者命令提示符,切换到boost的目录,运行bootstrap.bat:
2. 下一步的话在网上看到好多教程不同的方法,有些挺复杂的。我斗胆直接按照最简单粗暴的方式运行了.\b2,然后开始了漫长的等待,可能花了差不多三十分钟吧,等了十分钟还没好就出去吃了个饭,回来就编译好了。
3. 最后编译完成的截图:
下载地址:http://eigen.tuxfamily.org/index.php?title=Main_Page#Download
迷茫的我不知道该选啥,就直接选了个最新的:
下载后解压后重命名文件夹为eigen3,然后我把它放到了:C:\Program Files\eigen3
为了想测试一下eigen能不能用,于是试着使用了一下,参考:https://blog.csdn.net/houjixin/article/details/8477522
1. 首先在VS里设置项目属性包含eigen3,方法:项目属性->C/C++->常规->附加包含目录中添加C:\Program Files\eigen3
2. 输入了一段测试代码,运行成功:
代码如下:
#include "stdafx.h"
#include
#include
#include
using Eigen::MatrixXd;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
system("pause");
return 0;
}
下载地址:https://www.stack.nl/~dimitri/doxygen/download.html
这个在我参考的教程里面说是可选的,但是如果在后面cmake时按照那个教程把能勾的都勾上的话是需要Doxygen来生成说明文档的(看不懂没关系,等做到cmake的时候就懂了,最好还是下着吧)。Doxygen的功能就是能把代码里按照固定格式写的注释抽取出来生成说明文档。
我选的是这个:
下载下来以后安装就一路按照默认的next就好了,没什么要注意的,也很快就安装好了。
这里再提一下,搜Doxygen的安装方法,各种教程里都搭配了什么graphviz之类的感觉非常麻烦,但是这里只需要做到这儿就够了。
安装过程中出现问你要不要加入环境变量,默认是否,但我还是选了是:
以及请记住安装路径:
安装好像花了一段时间才装好,然后我们就要开始激动人心的编译SDM的过程了!
1. 进入cmake安装目录下的bin,找到cmake.gui:
2. 把SDM源码放在一个位置下,我放在了D盘里,路径:D:\superviseddescent-master,然后新建一个子文件夹build用来放cmake后的文件
3. 打开cmake的gui以后,where is the source code中填写SDM的路径,where to build the binaries填写刚刚新建的build的路径,然后点下面的Configure,如图:
4. 出现让你选编译器,请根据自己的实际情况选择。图中是我第一次踩坑选错的,实际上我应该选Visual Studio 12 2013 Win64(好像是这样的)
5. Finish以后,开始出现第一次错误(这是正常的错误):
图中红框部分刚开始显示NOT_FOUND还是啥的,需要把它改成你自己的opencv下build目录的路径,如上图所示。
6. 第二个错误出现,这里是不正常的错误,如图:
错误原因:我用的opencv 2.4.13的build底下只有vc11和vc12,而此时我用的VS2017是vc14,于是就不匹配了。刚开始搜错误原因的时候还看到一些说改cmakelist把opencv_found改成1的之类的,反正都不是我这个的错误原因。由于我电脑里有VS2012和VS2017,想着那我可以用VS2012了,于是File->clear cache以后重新用VS2012编译,嗯,终于找得到opencv了。
7. 于是就出现了第三个错误——找不到boost了,然后就想到了大概是因为boost下载的是vc12的版本,于是重新下载了vc11的版本。经过漫长的等待,终于装好了,竟然不需要对之前的版本进行卸载或者什么其他操作。然后直接重新Configure一下,终于踏马的成功了,啊!(好吧这里直接复制粘贴了当时的随手记下来的心得,感受一下我当时开心的心情,为后面的一连串错误做铺垫)
8. 然后呢就会发现上面多出来两个没打勾的小方框,打上勾以后点击Generate进行第一次生成,如图是生成中:
然而很不幸,又双叒出错了,因为没有安装Doxygen,错误如图:
然后呢就有了上面装Doxygen的步骤,装完以后重新Configure和第一次Generate,终于没有报错:
9. 发现上面又多了一些没打勾的方框,打勾以后进行第二次Generate:
此时此刻,终于的终于,Generate完了!太感动了!(然而感动得太早了)
这里又是无穷无尽的踩坑史,一把辛酸泪。一切都由我一如既往地打开了VS2017说起……
1. 新建项目以后,添加包含目录:项目属性->VC++目录->包含目录。另外说明一下,这里的包含目录刚开始我是只加了前五行的(就是opencv和SDM的),后面几行是我根据编译时的错误提示新加的,由于后面又加了些其他的所以不太确定是否全部都要加上,但这么做是肯定没问题就对了。
C:\Program Files (x86)\opencv\build\include\opencv
C:\Program Files (x86)\opencv\build\include
C:\Program Files (x86)\opencv\build\include\opencv2
D:\superviseddescent-master\include
D:\superviseddescent-master\3rdparty\cereal-1.1.1\include
C:\local\boost_1_58_0
C:\Program Files\eigen3
然后添加库目录:项目属性->VC++目录->库目录
C:\Program Files (x86)\opencv\build\x86\vc12\lib
以及附加依赖项:项目属性->链接器->附加依赖项
opencv_ml2413d.lib
opencv_calib3d2413d.lib
opencv_contrib2413d.lib
opencv_core2413d.lib
opencv_features2d2413d.lib
opencv_flann2413d.lib
opencv_gpu2413d.lib
opencv_highgui2413d.lib
opencv_imgproc2413d.lib
opencv_legacy2413d.lib
opencv_objdetect2413d.lib
opencv_ts2413d.lib
opencv_video2413d.lib
opencv_nonfree2413d.lib
opencv_ocl2413d.lib
opencv_photo2413d.lib
opencv_stitching2413d.lib
opencv_superres2413d.lib
opencv_videostab2413d.lib
这些是debug模式下的附加依赖项,release下只需要去掉上面这些末尾的d就好。
还要加入boost相关的:(不要问我为什么这里变成了英文版,这是意识到错误以后改过自新以后才发现要新加的QAQ)
C/C++->General->Additional Include Directories加入Boost的目录:C:\local\boost_1_58_0
还有:Linker->General->Additional Library Dependencies里加入:C:\local\boost_1_58_0\stage\lib
2. 使用SDM源码中examples/landmark_detection.cpp来测试,需要把opencv路径中的haarcascade_frontalface_alt2.xml文件复制粘贴一下到自己喜欢的目录(我就直接放到examples下面了),然后如图修改第370-380行附近的代码,把default_value们设为绝对路径。这里的意思就是命令行参数的默认参数,注意一下facedetector那里本来是没有默认值的,复制粘贴的时候需要注意一下。
desc.add_options()
("help,h",
"display the help message")
("data,d", po::value(&trainingset)->required()->default_value("D:\\superviseddescent-master\\examples\\data\\ibug_lfpw_trainset"),
"path to ibug LFPW example images and landmarks")
("mean,m", po::value(&meanfile)->required()->default_value("D:\\superviseddescent-master\\examples\\data\\mean_ibug_lfpw_68.txt"),
"pre-calculated mean from ibug LFPW")
("facedetector,f", po::value(&facedetector)->required()->default_value("D:\\superviseddescent-master\\examples\\haarcascade_frontalface_alt2.xml"),
"full path to OpenCV's face detector (haarcascade_frontalface_alt2.xml)")
;
3. 试着第一次运行,产生错误:
检查原因,是Boost库出错。解决方法:
在工程属性->C/C++->命令行->其他选项 中添加:_SCL_SECURE_NO_WARNINGS(注意图是错的,不需要前面的-D!!)
结果又出错了:
嗯,就是我之前提到过的,不过这里是我在VS2017下运行时的截图。看到网上有说调整多线程MDd为MTd的,然而并没有什么卵用。最后才发觉应该是VC14的问题,毕竟看着错误提示上面写的清清楚楚找不到什么vc140……
4. 想着电脑里有VS2012于是我熟练地切换了VS2012,结果又双叒出错了,忘了截图,反正大概意思就是VS2012不支持C++11的一些语法,而SDM这个用的C++11的语法,就不行了。于是无奈之下只好重新下载VS2013,又重新用vc12 cmake了一下上面的步骤,然后又回来运行了。
5. 下面是使用VS2013的部分,运行首先报错:
和之前用2017一样的错误,结果这时候忘了前一天的错误记录了于是搜了一下发现另一款解决方案,或许都行吧:C/C++->Preprocessor->Preprocessor Definitions设置为_SCL_SECURE_NO_WARNINGS
嗯,新下的VS2013是英文版,不过反正按钮顺序都是一样的,对应一下应该很方便。
然后在VS2013下依旧还是找不到boost的问题,试着修改了多线程那个也还是不行,后面才发现是要自己编译一遍boost,就是上面已经写了的步骤里的那样。重新编译boost以后又把boost加入了项目属性(上面也写过了)。然后终于可以成功编译了,一口老血喷出来。
6. 当我以为build完以后可以高兴地运行的时候,发现在VS里面直接运行却会出现:
回想起当年做opencv作业的时候也是经常出现这个毛病,当时没有记录也忘了是怎么解决的了,反正就是dll的问题。这次也是上网查了好久好久翻阅了无数博客论坛都没能解决,准备放弃的时候无意间直接从VS里这个project的目录里面双击exe文件结果就打!开!了!!!当时真是心情复杂因为又激动又开心又疑惑又生气,虽然还是不知道是什么毛病但是能运行了我就谢天谢地了阿弥陀佛。
7. 好的接下来讲一下landmark_detection.cpp这个文件。它读入了examples/data里的五张图片和它们对应的landmark以及一个mean position,这些拿来做训练。看了作者在github issues里面提到的,本来应该是输出68个特征点,但是这个example呢是一个拿来让大家知道这玩意儿怎么用的一个tutorial,而训练68个特征点需要消耗一个多小时(根据issue里面大家的提问得出的),于是作者修改了一下就只训练五个特征点——双眼、鼻子和嘴唇的左右两边。文件的运行时效果如图:
最终的输出:
在apps文件夹里有rcr_train.cpp,应该是用于训练模型的代码,但这个我没自己试过,感觉就是上面所说的像landmark_detection.cpp那样用吧,但是自己要收集好图片、landmark并计算出那个平均值mean,可以直接从iBug里面下载LFPW之类的数据集(就是SDM原论文里使用到的数据集),好像是自带landmark的?没去看过不清楚。计算mean的方法我也没仔细看,但github repo里的issue里面有好多提到的可以参考一下。
对应的代码为apps/rcr/rcr-detect.cpp,这个也是我主要用它的部分。作者在apps/rcr/data里给出了22和29个特征点的模型,如果需要68个特征点的模型可以在 http://www.patrikhuber.ch/files/models/face_landmarks_model_rcr_68.bin下载。同样的需要改命令行参数的默认值,或者其实自己从cmd里执行这个文件并带上参数也是可以的,用法:[exe文件名] -i或-image [要检测的文件路径] -o或-output [输出的文件路径] -m或-model [使用的模型路径]
用了68个特征点检测出来的效果如下:
感觉还行,但是下嘴唇的上面部分迷之跑到牙齿中间的舌头那里了,试了好几张图都有点这个问题。
同时,也可以对代码进行一番操作让它只输出几个特征点。底下这行代码返回的是一个类型为rcr::Landmark
每个特征点对应的index如下:
同样的也可以取到对应的坐标值,Landmark类有两个属性,name和coordinate,比如要获得上面那行代码里的landmarks里的第一个元素的坐标,就直接landmarks[0].coordinates即可取到,类型为Vec2f。
对应的代码为apps/rcr/rcr-track.cpp,使用方法和上面的一样,只是命令行参数减少到只有-m和-i,其中-i是输入的视频,如果不设置的话默认为使用电脑摄像头。我就自己用摄像头试了一下,用的也是68个点的模型,效果的话第一印象就是一个字——卡!真的要卡成PPT了估计用少一点特征点的模型会好一些。然后嘴唇部分的问题和上面提到的一样,尤其是当嘴巴张开的时候上下嘴唇的特征点都快重合了……不知道是什么毛病,嘴巴张开很大的时候嘴部的跟踪结果真是不忍直视。由于人丑就不放图在这里以免吓到大家,大家自个儿试试就好。