Win10_VS2013_CPU_Darknet_YOLOV4编译踩坑
1 踩坑原因
手贱- 使用Darknet;
- 学习Darknet源码;
- 配合VS2013开发项目的需要
这里再梳理一下我的路线:
→
\rightarrow
→编译Darknet(CPU版本/GPU版本)
→
\rightarrow
→使用别人训练的模型进行图片推理
→
\rightarrow
→训练自己的模型
→
\rightarrow
→调试修改Darknet源码
→
\rightarrow
→集成到其他的图像处理项目
→
\rightarrow
→部署项目并使用
编译只是第一步,编译CPU版本是第一步中的第一步。
其实如果使用VS2015以上版本进行编译,会少很多坑。但是截至目前为止仍然有很多开发团队仍在采用VS2013。小白发现在网络上,鲜有详细介绍如何在VS2013下进行no_gpu版本Darknet编译的文章或资料。偶尔有一两篇,可能由于作者自身调试编译水平较高,对一些问题一笔带过。
win10+vs2013+opencv 3.1编译darknet YOLOv3 采坑记录 Windows下 YOLOv3配置教程(YOLOv3项VS2013平台迁移的方法)
以上这两篇是小白读到的比较有参考价值的两篇,但小白进行编译的时候遇上的不少坑,是这两篇博客里都没有提到的。小白在两台电脑上分别编译了两次,第一次编译侥幸成功后,竟然把中间一些细节给忘记了。第二次编译仍然把一些坑重新趟了一遍。因此,第二次编译时,小白把一些问题记录了下来,聊以作为后来者的参考。 限于小白的水平,若有错漏,欢迎指正!敬请见谅!
2 VS工程下载
DarkNet YoloV3及其之前的系列是由pjreddie维护的https://pjreddie.com/darknet/,但这个版本是Linux下的源码版本,如果需要在win10系统下进行VS工程的编译,则需要自己从头去建立工程,这对于像小白一样水平有限的读者来说是困难的。 好在从YoloV4开始,AlexeyAB大神为大家提供了可供VS编译的版本: https://github.com/AlexeyAB/darknet 让我们先从github上把工程和源码下载下来. 从.\darknet-master\build\darknet 路径下可以看到no_gpu版的工程文件.
我们的趟坑之旅就从这里开始.
3 修改VS工程文件
第一个坑来自我们使用的VS版本,AlexeyAB大神提供的工程文件是由VS2015完成的。所以我们需要修改VS工程文件,使工程文件可以为VS2013所用。 鉴于我们要编译的是no_gpu版本,所以我们首先修改工程文件中VS的版本。 这里需要操作的是darknet_no_gpu.sln和darknet_no_gpu.vcxproj这两个文件。 首先我们来看darknet_no_gpu.sln文件:
上图是已经修改好的darknet_no_gpu.sln文件,大家可以跟原先的版本进行比较,可以发现主要是把Visual Studio的版本进行了修改。 VisualStudioVersion改成了12.0.40629
对于darknet_no_gpu.vcxproj,则需要修改的地方更多。
14.0对应的是VS2015,如果是VS2013则需要将其改成12.0;
v140对应的是VS2015,如果是VS2013则需要将其改成v120。
4 配置OpenCV
既然我们是用VS2013来进行编译,那么显然我们也需要能支持VS2013的OpenCV版本,而OpenCV官网已经没有直接可用的VS2013对应版本,需要用源码进行编译。 关于这个问题可以参看小白之前的博客。 OpenCV学习笔记(2)_CMake+Visual Studio 2013 源码编译CPU版本的OpenCV 配置时可以针对darknet_no_gpu.vcxproj文件进行修改。也可以直接在VS里面直接进行配置。以下举例如何在darknet_no_gpu.vcxproj文件中进行修改。
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)$(Platform)\</OutDir>
<IntDir>$(Platform)\nogpu_$(Configuration)\</IntDir>
<LibraryPath>..\..\3rdparty\opencv\x64\vc12\bin;..\..\3rdparty\pthreads\bin;..\..\3rdparty\opencv\x64\vc12\lib;..\..\3rdparty\pthreads\lib;$(LibraryPath)</LibraryPath>
<ReferencePath>$(ReferencePath)</ReferencePath>
<IncludePath>..\..\3rdparty\opencv\include;$(IncludePath)</IncludePath>
</PropertyGroup>
小白是把opencv放在了3rdparty路径下,用的是opencv3.4.16
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\3rdparty\opencv\include;..\..\3rdparty\opencv\include\opencv;..\..\3rdparty\opencv\include\opencv2;..\..\include;..\..\3rdparty\stb\include;..\..\3rdparty\pthreads\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENCV;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CRT_RAND_S;WIN32;NDEBUG;_CONSOLE;_LIB;_XKEYCHECK_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CLanguageStandard>c11</CLanguageStandard>
<CppLanguageStandard>c++1y</CppLanguageStandard>
<PrecompiledHeaderCompileAs>CompileAsCpp</PrecompiledHeaderCompileAs>
<CompileAs>Default</CompileAs>
<UndefinePreprocessorDefinitions>CUDNN</UndefinePreprocessorDefinitions>
<OpenMPSupport>true</OpenMPSupport>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>..\..\3rdparty\opencv\x64\vc12\lib;..\..\3rdparty\pthreads\lib;..\..\3rdparty\opencv\x64\vc12\bin;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>pthreadVC2.lib;opencv_world3416.lib;opencv_world3416d.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)\$(TargetName)$(TargetExt)</OutputFile>
</Link>
5 应对各种报错
这一部分其实是很多博客中忽略而过的。 有一位博主如是写道“百度基本上都可以解决”。 小白自己确实也是通过各种百度来解决这些问题,但是其中艰辛。。。咳咳,虽然很有可能小白所遇到的不是各位读者都会遇到的问题,但至少在小白编译过程中遇上了这些问题,在此聊以记录。 小白编译了两次,两次遇上的问题基本上也差不多,但是小白没有把错误的截图截下来,所以只能用文字的方式记述一下大概的问题。 注意我们需要在release x64下进行编译。
-
报错1:error C2065:"__func__":未声明的识别符
- 需要找到utils.h文件,把
__func__ 改成 __FUNCTION__ -
报错2:error C2054: 在“inline”之后应输入“(”
- 问题出在col2im.c,解决方案是把出错行的
inline static 删除掉 - 虽然这么做可能会有隐患,但是,对!就这么做了!还就起效了!
-
报错3:error C2059: 语法错误:“数字上的错误后缀”
- 问题出在gemm.c,把错误行中
0b1111 改写成0x0f 或直接就是15 - 这个问题的原因似乎是VS中不支持二进制数的写法,写成十六进制或者十进制好像都可以
-
报错4:未定义的ct
- 在项目上右键
→
\rightarrow
→属性
→
\rightarrow
→C/C++
→
\rightarrow
→预处理器
→
\rightarrow
→预处理器定义,去掉TIME开头的那个定义
-
报错5:错误名称忘记了,反正记得跟上一个错误的解决方法类似,在预处理器中添加_XKEYCHECK_H -
报错6:error C2065: “bufsiz”: 未声明的标识符
- 解决方法是在httplib.h中,把报错行中的
bufsiz 改写成BUFSIZ -
报错7:error C2664: “int _snprintf_s(char *,size_t,size_t,const char *,...)”: 无法将参数 1 从“std::array<char,0x0800>”转换为“char *”
- 还是在httplib.h文件中,把报错行中的buf改成buf.data()
解决完以上错误之后,语法上的错误基本上就结束了,接下来进入链接器的错误修改:
- 报错8:
error LNK2001: 无法解析的外部符号 snprintf
#if defined(_MSC_VER)
#define snprintf _snprintf_s
#endif
- 报错9:
error MSB8031: Building an MFC project for a non-Unicode character set is deprecated. You must change the project property to Unicode or download an additional library. See http://go.microsoft.com/fwlink/p/?LinkId=286820 for more information.
- 报错10:链接器错误之无法解析的外部符号 this_thread_sleep_for custom_join等
- 问题的原因:VS2013并没有完全支持C++11
- 解决方法:http_stream.c文件中,改写cpp的版本,只需要大于等于199711L即可,即
#if __cplusplus >= 199711L || _MSC_VER >= 1900 - 补充11:因为需要用到多线程,且编译时用到的是lib库文件。所以需要做以下调整:
6 下载yolov4.weights权重文件并测试
如果趟过以上诸坑,那你应该能最终获得编译好的darknet_no_gpu.exe文件。但很遗憾,你还不能立刻进行测试,因为在源码包里,唯独缺了模型的权重文件。 我们可以在github上查看ModelZoo。
可以在这里直接下载yolov4.weights,放到backup文件路径下。 接下来就可以在cmd中用以下命令行测试了:
darknet_no_gpu.exe detector test ./data/coco.data ./cfg/yolov4.cfg ./backup/yolov4.weights dog.jpg
因为是cpu版本,所以自然是比较慢的,耐心等待。。。
到此时,小白泪牛满面。终于把这个坑都踩过去了。不容易啊。 希望读者也能成功趟坑,开启我们的深度学习之旅。
|