Caffe: CMake源碼編譯(OpenCV4.2+CUDA)

週六週日在家倒騰了兩天,總算稍微瞭解點pycaffe的一些接口和api設置了,但是針對不同層,還是有很多注意的細節的,所以也準備寫個博客專門總結pycaffe的常見層參數設置,(LZ這個蠢啊,之前居然手寫prototxt,一把辛酸淚,太傻了/(ㄒoㄒ)/~~)

之前已經寫過用Anaconda直接安裝caffe,這樣安裝caffe不香嘛,爲啥非得源碼再來安裝一次呢?

1.項目裏後端是用的tensorflow的接口,前端是要用caffe的接口,caffe的有些參數設置還是源碼查詢比較方便
2.有一些層是比較特殊的,這種定製化的層可能需要使用c寫完之後,再進行源碼編譯

不過源碼編譯還是有很多坑的,且聽LZ一一道來:

首先下載源碼,https://github.com/weiliu89/caffe

按照tutorial安裝依賴項:http://caffe.berkeleyvision.org/installation.html

LZ的小小筆記本是Ubuntu16.04

  1. 所以需要先安裝對應的依賴庫
sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler
sudo apt-get install --no-install-recommends libboost-all-dev

  1. 然後LZ使用的是CMake編譯的,It requires CMake version >= 2.8.7. The basic steps are as follows:
mkdir build
cd build
cmake ..
make all
make install
make runtest

按照教程,好像簡簡單單,10分鐘就能搞定,但是事實卻不是如此。

  1. 當然你得設置下CUDA
# ---[ Options
caffe_option(CPU_ONLY  "Build Caffe without CUDA support" OFF) # TODO: rename to USE_CUDA
caffe_option(USE_CUDNN "Build Caffe with cuDNN library support" ON IF NOT CPU_ONLY)
caffe_option(USE_NCCL "Build Caffe with NCCL library support" OFF)
caffe_option(BUILD_SHARED_LIBS "Build shared libraries" ON)
caffe_option(BUILD_python "Build Python wrapper" ON)
set(python_version "2" CACHE STRING "Specify which Python version to use")
caffe_option(BUILD_matlab "Build Matlab wrapper" OFF IF UNIX OR APPLE)
caffe_option(BUILD_docs   "Build documentation" ON IF UNIX OR APPLE)
caffe_option(BUILD_python_layer "Build the Caffe Python layer" ON)
caffe_option(USE_OPENCV "Build with OpenCV support" ON)
caffe_option(USE_LEVELDB "Build with levelDB" ON)
caffe_option(USE_LMDB "Build with lmdb" ON)
caffe_option(ALLOW_LMDB_NOLOCK "Allow MDB_NOLOCK when reading LMDB files (only if necessary)" OFF)
caffe_option(USE_OPENMP "Link with OpenMP (when your BLAS wants OpenMP and you get linker errors)" OFF)
  1. 首先正常操作:
cmake ..

在這裏插入圖片描述

注意前方高能(ERROR來襲)

  1. 首先第一個坑就到來了,LZ之前爲了編譯tensorflow源碼,已經源碼安裝過protobuf了,也是用了-std=c++11這個標準
    所以在cmake報了一些類似如下的錯誤
error: #error This file requires compiler and library support for the ISO C++ 2011 standard. 
This support is currently experimental, and must be enabled with the -std=c++11 or
 -std=gnu++11 compiler options
error: 'nullptr' was not declared in this scope 這種一長串

所以第一步要添加-std=c++11, cmakel
在這裏插入圖片描述
makefile得這麼改,不過makefile中LZ沒有嘗試,如果嘗試過的小夥伴歡迎指導

CXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) -std=c++11
NVCCFLAGS += -D_FORCE_INLINES -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS) -std=c++11
LINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS) -std=c++11
  1. 第二個可能遇到的錯誤:
nvcc fatal : Unsupported gpu architecture 'compute_20'

這個是CUDA版本決定的,LZ的版本是10.1, 這個文件是在makefile.config裏面的,就順帶說一下

# CUDA architecture setting: going with all of them.
# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.
# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.
# For CUDA >= 9.0, comment the *_20 and *_21 lines for compatibility.
CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \
                -gencode arch=compute_20,code=sm_21 \
                -gencode arch=compute_30,code=sm_30 \
                -gencode arch=compute_35,code=sm_35 \
                -gencode arch=compute_50,code=sm_50 \
                -gencode arch=compute_52,code=sm_52 \
                -gencode arch=compute_60,code=sm_60 \
                -gencode arch=compute_61,code=sm_61 \
                -gencode arch=compute_61,code=compute_61
//註釋掉這兩句:
 -gencode arch=compute_20,code=sm_20 \
 -gencode arch=compute_20,code=sm_21 \
  1. 第三個可能遇到的錯誤:
fatal error: hdf5.h: No such file or directory compilation terminated.

用locate定位你的hdf5.h的位置,在makefile中添加對應的路徑

# Whatever else you find you need goes here.
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/local/include /usr/include/hdf5/serial/
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib  /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial

修改library

LIBRARIES += glog gflags protobuf boost_system boost_filesystem m hdf5_serial_hl hdf5_serial
  1. 第四個可能遇到的錯誤:

這個問題就是OpenCV 4版本接口改變導致的,這個改的就有點多了,需要把caffe源碼涉及到這個 CV_LOAD_IMAGE_COLOR都換掉。

../caffe/src/caffe/layers/window_data_layer.cpp:293:42: error: ‘CV_LOAD_IMAGE_COLOR’ was not declared in this scope
         cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR);

src/caffe/layers/window_data_layer.cpp

          image_database_cache_[window[WindowDataLayer<Dtype>::IMAGE_INDEX]];
        cv_img = DecodeDatumToCVMat(image_cached.second, true);
      } else {
        //cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR);
        cv_img = cv::imread(image.first, cv::IMREAD_COLOR);
        if (!cv_img.data) {
          LOG(ERROR) << "Could not open or find file " << image.first;
          return;

src/caffe/test/test_io.cpp

bool ReadImageToDatumReference(const string& filename, const int label,
    const int height, const int width, const bool is_color, Datum* datum) {
  cv::Mat cv_img;
  //int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
    //CV_LOAD_IMAGE_GRAYSCALE);
  int cv_read_flag = (is_color ? cv::IMREAD_COLOR :
    cv::IMREAD_GRAYSCALE);

  cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag);
  if (!cv_img_origin.data) {

src/caffe/util/io.cpp

void WriteProtoToBinaryFile(const Message& proto, const char* filename) {
cv::Mat ReadImageToCVMat(const string& filename,
   const int height, const int width, const bool is_color) {
 cv::Mat cv_img;
// int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
  // CV_LOAD_IMAGE_GRAYSCALE);
 int cv_read_flag = (is_color ? cv::IMREAD_COLOR :
   cv::IMREAD_GRAYSCALE);
 cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag);
 if (!cv_img_origin.data) {
   LOG(ERROR) << "Could not open or find file " << filename;


cv::Mat DecodeDatumToCVMat(const Datum& datum, bool is_color) {
 CHECK(datum.encoded()) << "Datum not encoded";
 const string& data = datum.data();
 std::vector<char> vec_data(data.c_str(), data.c_str() + data.size());
// int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
  // CV_LOAD_IMAGE_GRAYSCALE);
 int cv_read_flag = (is_color ? cv::IMREAD_COLOR :
   cv::IMREAD_GRAYSCALE);
 cv_img = cv::imdecode(vec_data, cv_read_flag);
 if (!cv_img.data) {
   LOG(ERROR) << "Could not decode datum ";
  1. 第五個可能遇到的錯誤:
    Anaconda的三方庫和本地庫衝突了,那就把Anaconda的環境變量先註釋掉,編譯好了再放出來就好了

最後放張編譯成功的圖。。。
在這裏插入圖片描述
自己踩坑千千萬,跳出一坑,又進了一坑!

據說OpenCV4.1版本之前存在安全隱患問題,所以現在LZ的公司都換成OpenCV4.2版本了。。。

參考地址:
1.https://blog.csdn.net/m_buddy/article/details/88085425
2.https://blog.csdn.net/qq_18649781/article/details/89047437
3.https://github.com/BVLC/caffe/issues/6680
4.https://github.com/BVLC/caffe/pull/6625/files/7f503bd9a19758a173064e299ab9d4cac65ed60f

PS:
LZ已經在自己家隔離20多天了,到工作的地方還得隔離14天,大門不出二門不賣,真希望能夠肆無忌憚的在一個陽關明媚的午後壓馬路O(∩_∩)O~

現在是關鍵時刻,還不能放鬆,越到緊要關頭,越要能忍住!
在這裏插入圖片描述在這裏插入圖片描述

武漢加油!湖北加油!中國加油!↖(ω)↗

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章