1.SSD簡介
SSD全稱Single Shot MultiBox Detector,是一個(gè)用于目標(biāo)檢測的深度學(xué)習(xí)框架。
By Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, Scott Reed, Cheng-Yang Fu, Alexander C. Berg.
SSD是一個(gè)單一的網(wǎng)絡(luò)對象檢測的統(tǒng)一框架。你可以使用代碼來訓(xùn)練/評估一個(gè)用于目標(biāo)檢測任務(wù)的網(wǎng)絡(luò)。(http://arxiv.org/abs/1512.02325).
作者的Github上https://github.com/weiliu89/caffe
只給出了linux下的代碼,下面內(nèi)容是將代碼移植到windows上的實(shí)現(xiàn)步驟。本文參考了samylee的博文Windows-SSD配置與測試,在此表示感謝。
2. 配置環(huán)境
windows7 + vs2013 + Cuda8.0
3. 所需文件
vs2013,windows-caffe,ubuntu-ssd,libboost,cudnn,OpenCV(可選)ssd_detect.cpp,io.cpp
windows-caffe地址: 鏈接:http://pan.baidu.com/s/1hrGRu1A
密碼:j82r
或 https://github.com/conner99/caffe
,推薦使用后者。
ubuntu-ssd地址: 鏈接:http://pan.baidu.com/s/1mhYuf7y
密碼:3jp2
libboost地址:鏈接:http://pan.baidu.com/s/1pLbBMpP
密碼:41tq
cudnn地址:鏈接:http://pan.baidu.com/s/1o8vWBhw
密碼:kdj4
opencv地址:鏈接:http://pan.baidu.com/s/1eSkHBj0
密碼:nhch
ssd_detect.cpp地址:鏈接:http://pan.baidu.com/s/1nvwECNv
密碼:e3yn
io.cpp地址:鏈接:http://pan.baidu.com/s/1i4CL7QP
密碼:g623
signal_handler地址:鏈接:http://pan.baidu.com/s/1mhYuf7y
密碼:iubq
4. 配置步驟和出現(xiàn)的問題
本人配置的是使用GPU的版本,以下為配置步驟和出現(xiàn)的問題:
從上述網(wǎng)址下載的windows-caffe使用的Cuda版本為7.5,我使用的Cuda版本為8.0,所以將其版本改為8.0,重命名
.\caffe-master\windows\\
路徑下的CommonSettings.props.example
為CommonSettings.props
,修改Cuda配置為<CudaVersion>8.0</CudaVersion>
,此外設(shè)置<CpuOnlyBuild>true</CpuOnlyBuild>
和<UseCuDNN>false</UseCuDNN>
。編譯項(xiàng)目,報(bào)錯(cuò)
“未能生成object文件(視警告為錯(cuò)誤)”
,解決方法:右擊選擇屬性->配置屬性->c/c++->常規(guī)
,將“警告視為錯(cuò)誤”
的選項(xiàng)改為“否”
,若還報(bào)錯(cuò),將math_functions.obj
文件放到路徑caffe-master\Build\Int\libcaffe\x64\[Release|Debug]
下。復(fù)制
.\ssd_new
下所有文件(除build
,data
,example
以及models
之外)至.\windows-caffe
,替換原來文件夾中對應(yīng)的文件。編譯文件,報(bào)錯(cuò)
error C3861: “mkdir”: 找不到標(biāo)識(shí)符
。解決辦法:在db_lmdb.cpp
文件的
CHECK_EQ(mkdir(source.c_str(), 0744), 0) << "mkdir " << source << " failed";
語句上下添加語句,使得:
#ifdef MSC_VER
CHECK_EQ(mkdir(source.c_str(), 0744), 0) << "mkdir " << source << " failed";
#endif
- 編譯文件,報(bào)錯(cuò)
error C2360: “occurrences_32”的初始化操作由“case”標(biāo)簽跳過
。解決辦法:在hdf5.cpp文件中將所有出錯(cuò)的case
語句下的內(nèi)容都括上大括號(hào){ }
,比如,將語句
case H5T_FLOAT:
LOG_FIRST_N(INFO, 1) << "Datatype class: H5T_FLOAT";
break;
改為:
case H5T_FLOAT:
{
LOG_FIRST_N(INFO, 1) << "Datatype class: H5T_FLOAT";
break;
}
選擇解決方案下的
libcaffe
項(xiàng)目,進(jìn)入include/layers
文件夾中,將路徑.\caffe-master\include\caffe\layers
下除了roi_pooling_layer.hpp
的所有hpp
文件添加到include/layers
中。進(jìn)入src/layers
文件夾中,將路徑.\caffe-master\src\caffe\layers
下除了roi_pooling_layers.cpp
的所有cpp
文件添加到src/layers
中。編譯項(xiàng)目,報(bào)錯(cuò)
error C2065: “SIGHUP”: 未聲明的標(biāo)識(shí)符
。解決辦法:在common.cpp
文件最上邊一行添加語句
#include "process.h"
編譯項(xiàng)目,報(bào)了都是關(guān)于
signal_handler.cpp
文件相關(guān)的錯(cuò)誤,在本文章第三部分享文件中下載signal_handler.cpp
文件替換即可。編譯項(xiàng)目,報(bào)錯(cuò)找不到boost庫,在解決方案的
caffe
和classification
項(xiàng)目下的VC++
選項(xiàng)下,在包含目錄
中添加~/boost_1_59_0/
,在庫目錄
中添加~\boost_1_59_0\stage\lib
。選擇解決方案下的
libcaffe
項(xiàng)目,進(jìn)入libcaffe/src/util
文件夾中,將路徑\ssd_new\src\caffe\util
下的bbox_util.cpp
文件添加到libcaffe/src/util
中。編譯項(xiàng)目,報(bào)錯(cuò)
找不到標(biāo)識(shí)符"snprintf"
,解決辦法:在bbox_util
文件中,在標(biāo)識(shí)符snprintf
前面加上下劃線_
,修改為_snprintf
。編譯項(xiàng)目,報(bào)錯(cuò):
error LNK2001: 無法解析的外部符號(hào) "__declspec(dllimport) void __cdecl google::InstallFailureSignalHandler(void)"
采用了粗暴的解決方式,在common.cpp
文件中,將出錯(cuò)的函數(shù)::google::InstallFailureSignalHandler()
注釋掉。
- 選擇解決方案下的
classification
項(xiàng)目,將ssd_detect.cpp
文件添加到項(xiàng)目中,去除注釋,修改相應(yīng)的模型文件和網(wǎng)絡(luò)結(jié)構(gòu)定義文件的路徑。
至此,SSD目標(biāo)檢測的CPU版本,已經(jīng)可以在windows下運(yùn)行,接下來配置 SSD的GPU加速版本。
在路徑
.\caffe-master\windows\\
下進(jìn)入CommonSettings.props
配置文件中,設(shè)置<CpuOnlyBuild>false</CpuOnlyBuild>
和<UseCuDNN>true</UseCuDNN>
。進(jìn)入
.\caffe-master\windows\\
路徑下,啟動(dòng)Caffe
工程,編譯工程,報(bào)錯(cuò):
error MSB3721: 命令“……”已退出,返回代碼為1。
修改.\caffe-master\windows\\
路徑下的CommonSettings.props
文件,修改對應(yīng)內(nèi)容為:
<CudaArchitecture>compute_30,sm_30;compute_50,sm_50</CudaArchitecture>
- 之后編譯工程,報(bào)錯(cuò):
無法打開cudnn.h文件
,從本博客第二部分下載cudnn,之后在項(xiàng)目工程的屬性中的vc++包含目錄
中添加~/cuda/include
路徑。在庫目錄
中添加~/cuda/lib/x64
路徑。 - 編譯工程,報(bào)錯(cuò):
error : declaration is incompatible with "const char *cudnnGetErrorString(cudnnStatus_t)"
,解決方法:修改cudnn.hpp
文件中
inline const char* cudnnGetErrorString(cudnnStatus_t status)
為
inline const char* CUDNNWINAPI cudnnGetErrorString(cudnnStatus_t status)
- 編譯工程,報(bào)錯(cuò):
"::caffe::kBNLL_THRESHOLD" is undefined in device code"
,解決方法:修改bnll_layer.cu
中
Dtype expval = exp(min(in_data[index], Dtype(kBNLL_THRESHOLD)));
為
Dtype expval = exp(min(in_data[index], Dtype(50)));
- 編譯工程,報(bào)錯(cuò):
error : too few arguments in function call. conv_layer.cu
。修改conv_layer.cu
文件中
this->forward_gpu_gemm(bottom_data + n * this->bottom_dim_, weight, top_data + n * this->top_dim_);
為
this->forward_gpu_gemm(bottom_data + n * this->bottom_dim_, weight, top_data + n * this->top_dim_, false);
編譯項(xiàng)目,報(bào)錯(cuò)
error MSB3073
,解決辦法:進(jìn)入項(xiàng)目libcaffe
的屬性設(shè)置,設(shè)置生成事件 -> 預(yù)先生成事件 -> 在生成中使用 -> 否
,設(shè)置生成事件 -> 后期生成事件 -> 在生成中使用 -> 否
。編譯項(xiàng)目,報(bào)與boost相關(guān)的regex正則表達(dá)式庫出現(xiàn)問題,在項(xiàng)目中我們不需要正則表達(dá)式,所以將相關(guān)語句注釋掉即可。進(jìn)入項(xiàng)目
libcaffe
中,進(jìn)入detection_output_layer.cu
文件,將所有出現(xiàn)regex
和rv
的語句注釋掉。進(jìn)入detection_output_layer.cpp
文件,將所有出現(xiàn)regex
和rv
的語句注釋掉。進(jìn)入detection_output_layer.hpp
中,將語句#include <boost/regex.hpp>
注釋掉。編譯項(xiàng)目,報(bào)錯(cuò):
找不到".\caffe\3rdparty\hungarian.h"文件
,在路徑.\caffe-master\include\caffe\3rdparty\\
下添加hungarian.h
文件。編譯項(xiàng)目,報(bào)錯(cuò):找不到".\src\caffe\3rdparty\hungarian.cpp"文件
,在路徑.\caffe-master\\src\caffe\3rdparty\\
下添加hungarian.cpp
文件。編譯項(xiàng)目,報(bào)與
thrust
相關(guān)的錯(cuò)誤,進(jìn)入項(xiàng)目libcaffe
中,注釋掉
#include "thrust/functional.h"
#include "thrust/sort.h"
……
thrust::sort_by_key(&confidences[0], &confidences[0] + num_remain, &idx[0],
thrust::greater<Dtype>());
這些語句。
- 進(jìn)入解決方案下的
classification
項(xiàng)目的ssd_detect.cpp
文件中,去除注釋,修改相應(yīng)的模型文件和網(wǎng)絡(luò)結(jié)構(gòu)定義文件的路徑。
至此,SSD目標(biāo)檢測的GPU版本,已經(jīng)可以在windows下運(yùn)行。
5. 感謝
感謝一直踩雷的婦老師,解決了上面提到的大部分錯(cuò)誤。希望本篇文章可以給想要在windows環(huán)境下運(yùn)行SSD的程序員們一些幫助。