日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

封装caffe-windows-master为动态链接库

發(fā)布時(shí)間:2024/9/21 windows 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 封装caffe-windows-master为动态链接库 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2016.12.14:

代碼已知bug:

由于類(lèi)中有全局變量,聲明多個(gè)對(duì)象時(shí),全局變量指向會(huì)改變,造成結(jié)果錯(cuò)誤并且有內(nèi)存泄漏。因此該份代碼只能聲明一個(gè)Classifier對(duì)象。

新的代碼已經(jīng)重新封裝,并且做成多標(biāo)簽輸出,下載地址:http://download.csdn.net/detail/sinat_30071459/9715053

主要修改:http://blog.csdn.net/sinat_30071459/article/details/53611678

因?yàn)閏affe-windows-master的代碼比較多,看著很亂,所以想到把它封裝成一個(gè)類(lèi)來(lái)調(diào)用做圖像分類(lèi),這里以GPU版本為例,記錄一下自己封裝成DLL和如何使用封裝后的DLL的過(guò)程。


1.打開(kāi)解決方案

首先,需要修改解決方案配置(默認(rèn)是Release),我們新建一個(gè)叫ReleaseGPU,平臺(tái)修改為x64(因?yàn)橛玫降钠渌鸇LL是64位,配置成win32會(huì)出錯(cuò)),如下:



這里我將caffelib的項(xiàng)目名改成了type_recognition_ver2_api_gpu,配置好ReleaseGPU后,右鍵項(xiàng)目type_recognition_ver2_api_gpu——>屬性,配置屬性頁(yè):

(1)配置屬性——常規(guī)


(2)C/C++——常規(guī)——附加包含目錄:

../../3rdparty/include

../../src

../../include

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include

預(yù)處理器——預(yù)處理器定義添加:

TYPE_RECOGNITION_LINK_SHARED
TYPE_RECOGNITION_API_EXPORTS

(3)鏈接器——常規(guī)——附加庫(kù)目錄:

../../3rdparty/lib

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\x64


(4)鏈接器——輸入——附加依賴項(xiàng):

kernel32.lib
user32.lib
gdi32.lib
winspool.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
comdlg32.lib
advapi32.lib
cudart.lib
cublas.lib
curand.lib
libprotobuf.lib
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
zlib.lib
szip.lib
opencv_world300.lib
shlwapi.lib
leveldb.lib
cublas_device.lib
cuda.lib
libglog.lib
lmdb.lib
cudnn.lib
libopenblas.dll.a
libgflags.lib

這樣就配置好了。


2.添加文件

(1)添加classfy.h和classify.cpp

[plain]?view plaincopy
  • //classify.h??
  • #pragma?once??
  • #include?<caffe/caffe.hpp>??
  • #include?<opencv2/core/core.hpp>??
  • #include?<opencv2/highgui/highgui.hpp>??
  • #include?<opencv2/imgproc/imgproc.hpp>??
  • #include?<iosfwd>??
  • #include?<memory>??
  • #include?<utility>??
  • #include?<vector>??
  • #include?<iostream>??
  • #include?<string>??
  • #include?<fstream>??
  • #include?<sstream>??
  • ??
  • using?namespace?caffe;??//?NOLINT(build/namespaces)??
  • //using?namespace?boost::property_tree;??
  • using?std::string;??
  • ??
  • /*?Pair?(number,?confidence)?representing?a?prediction.?*/??
  • typedef?std::pair<int,?float>?Prediction;??
  • ??
  • class?ClassifierImpl?{??
  • public:??
  • ????ClassifierImpl::ClassifierImpl(){};??
  • ????ClassifierImpl(const?string&?model_file,??
  • ????????const?string&?trained_file,??
  • ????????const?string&?mean_file,??
  • ????????const?string&?label_file);??
  • ??
  • ????std::vector<Prediction>?Classify(const?cv::Mat&?img,?int?N?=?2);??
  • ??
  • private:??
  • ????void?SetMean(const?string&?mean_file);??
  • ??
  • ????std::vector<float>?Predict(const?cv::Mat&?img);??
  • ??
  • ????void?WrapInputLayer(std::vector<cv::Mat>*?input_channels);??
  • ??
  • ????void?Preprocess(const?cv::Mat&?img,??
  • ????????std::vector<cv::Mat>*?input_channels);??
  • ??
  • private:??
  • ????shared_ptr<Net<float>?>?net_;??
  • ????cv::Size?input_geometry_;??
  • ????int?num_channels_;??
  • ????cv::Mat?mean_;??
  • };??

  • [plain]?view plaincopy
  • //classify.cpp??
  • #include?"classify.h"??
  • ClassifierImpl::ClassifierImpl(const?string&?model_file,??
  • ????const?string&?trained_file,??
  • ????const?string&?mean_file,??
  • ????const?string&?label_file)??
  • {??
  • #ifdef?CPU_ONLY??
  • ????Caffe::set_mode(Caffe::CPU);??
  • #else??
  • ????Caffe::set_mode(Caffe::GPU);??
  • #endif??
  • ??
  • ????/*?Load?the?network.?*/??
  • ????net_.reset(new?Net<float>(model_file,?TEST));??
  • ????net_->CopyTrainedLayersFrom(trained_file);??
  • ??
  • ????CHECK_EQ(net_->num_inputs(),?1)?<<?"Network?should?have?exactly?one?input.";??
  • ????CHECK_EQ(net_->num_outputs(),?1)?<<?"Network?should?have?exactly?one?output.";??
  • ??
  • ????Blob<float>*?input_layer?=?net_->input_blobs()[0];??
  • ????num_channels_?=?input_layer->channels();??
  • ????CHECK(num_channels_?==?3?||?num_channels_?==?1)??
  • ????????<<?"Input?layer?should?have?1?or?3?channels.";??
  • ????input_geometry_?=?cv::Size(input_layer->width(),?input_layer->height());??
  • ??
  • ????/*?Load?the?binaryproto?mean?file.?*/??
  • ????SetMean(mean_file);??
  • ??
  • ????Blob<float>*?output_layer?=?net_->output_blobs()[0];??
  • ??????
  • }??
  • ??
  • static?bool?PairCompare(const?std::pair<float,?int>&?lhs,??
  • ????const?std::pair<float,?int>&?rhs)?{??
  • ????return?lhs.first?>?rhs.first;??
  • }??
  • ??
  • /*?Return?the?indices?of?the?top?N?values?of?vector?v.?*/??
  • static?std::vector<int>?Argmax(const?std::vector<float>&?v,?int?N)?{??
  • ????std::vector<std::pair<float,?int>?>?pairs;??
  • ????for?(size_t?i?=?0;?i?<?v.size();?++i)??
  • ????????pairs.push_back(std::make_pair(v[i],?i));??
  • ????std::partial_sort(pairs.begin(),?pairs.begin()?+?N,?pairs.end(),?PairCompare);??
  • ??
  • ????std::vector<int>?result;??
  • ????for?(int?i?=?0;?i?<?N;?++i)??
  • ????????result.push_back(pairs[i].second);??
  • ????return?result;??
  • }??
  • ??
  • /*?Return?the?top?N?predictions.?*/??
  • std::vector<Prediction>?ClassifierImpl::Classify(const?cv::Mat&?img,?int?N)?{??
  • ????std::vector<float>?output?=?Predict(img);??
  • ??
  • ????std::vector<int>?maxN?=?Argmax(output,?N);??
  • ????std::vector<Prediction>?predictions;??
  • ????for?(int?i?=?0;?i?<?N;?++i)?{??
  • ????????int?idx?=?maxN[i];??
  • ????????predictions.push_back(std::make_pair(idx,?output[idx]));??
  • ????}??
  • ??
  • ????return?predictions;??
  • }??
  • ??
  • /*?Load?the?mean?file?in?binaryproto?format.?*/??
  • void?ClassifierImpl::SetMean(const?string&?mean_file)?{??
  • ????BlobProto?blob_proto;??
  • ????ReadProtoFromBinaryFileOrDie(mean_file.c_str(),?&blob_proto);??
  • ??
  • ????/*?Convert?from?BlobProto?to?Blob<float>?*/??
  • ????Blob<float>?mean_blob;??
  • ????mean_blob.FromProto(blob_proto);??
  • ????CHECK_EQ(mean_blob.channels(),?num_channels_)??
  • ????????<<?"Number?of?channels?of?mean?file?doesn't?match?input?layer.";??
  • ??
  • ????/*?The?format?of?the?mean?file?is?planar?32-bit?float?BGR?or?grayscale.?*/??
  • ????std::vector<cv::Mat>?channels;??
  • ????float*?data?=?mean_blob.mutable_cpu_data();??
  • ????for?(int?i?=?0;?i?<?num_channels_;?++i)?{??
  • ????????/*?Extract?an?individual?channel.?*/??
  • ????????cv::Mat?channel(mean_blob.height(),?mean_blob.width(),?CV_32FC1,?data);??
  • ????????channels.push_back(channel);??
  • ????????data?+=?mean_blob.height()?*?mean_blob.width();??
  • ????}??
  • ??
  • ????/*?Merge?the?separate?channels?into?a?single?image.?*/??
  • ????cv::Mat?mean;??
  • ????cv::merge(channels,?mean);??
  • ????/*?Compute?the?global?mean?pixel?value?and?create?a?mean?image??
  • ????*?filled?with?this?value.?*/??
  • ????cv::Scalar?channel_mean?=?cv::mean(mean);??
  • ????mean_?=?cv::Mat(input_geometry_,?mean.type(),?channel_mean);??
  • }??
  • std::vector<float>?ClassifierImpl::Predict(const?cv::Mat&?img)?{??
  • ????Blob<float>*?input_layer?=?net_->input_blobs()[0];??
  • ????input_layer->Reshape(1,?num_channels_,??
  • ????????input_geometry_.height,?input_geometry_.width);??
  • ????/*?Forward?dimension?change?to?all?layers.?*/??
  • ????net_->Reshape();??
  • ????std::vector<cv::Mat>?input_channels;??
  • ????WrapInputLayer(&input_channels);??
  • ??
  • ????Preprocess(img,?&input_channels);??
  • ??
  • ????net_->ForwardPrefilled();??
  • ??
  • ????/*?Copy?the?output?layer?to?a?std::vector?*/??
  • ????Blob<float>*?output_layer?=?net_->output_blobs()[0];??
  • ????const?float*?begin?=?output_layer->cpu_data();??
  • ????const?float*?end?=?begin?+?output_layer->channels();??
  • ????return?std::vector<float>(begin,?end);??
  • }??
  • ??
  • /*?Wrap?the?input?layer?of?the?network?in?separate?cv::Mat?objects??
  • *?(one?per?channel).?This?way?we?save?one?memcpy?operation?and?we??
  • *?don't?need?to?rely?on?cudaMemcpy2D.?The?last?preprocessing??
  • *?operation?will?write?the?separate?channels?directly?to?the?input??
  • *?layer.?*/??
  • void?ClassifierImpl::WrapInputLayer(std::vector<cv::Mat>*?input_channels)?{??
  • ????Blob<float>*?input_layer?=?net_->input_blobs()[0];??
  • ??
  • ????int?width?=?input_layer->width();??
  • ????int?height?=?input_layer->height();??
  • ????float*?input_data?=?input_layer->mutable_cpu_data();??
  • ????for?(int?i?=?0;?i?<?input_layer->channels();?++i)?{??
  • ????????cv::Mat?channel(height,?width,?CV_32FC1,?input_data);??
  • ????????input_channels->push_back(channel);??
  • ????????input_data?+=?width?*?height;??
  • ????}??
  • }??
  • ??
  • void?ClassifierImpl::Preprocess(const?cv::Mat&?img,??
  • ????std::vector<cv::Mat>*?input_channels)?{??
  • ????/*?Convert?the?input?image?to?the?input?image?format?of?the?network.?*/??
  • ????cv::Mat?sample;??
  • ????if?(img.channels()?==?3?&&?num_channels_?==?1)??
  • ????????cv::cvtColor(img,?sample,?CV_BGR2GRAY);??
  • ????else?if?(img.channels()?==?4?&&?num_channels_?==?1)??
  • ????????cv::cvtColor(img,?sample,?CV_BGRA2GRAY);??
  • ????else?if?(img.channels()?==?4?&&?num_channels_?==?3)??
  • ????????cv::cvtColor(img,?sample,?CV_BGRA2BGR);??
  • ????else?if?(img.channels()?==?1?&&?num_channels_?==?3)??
  • ????????cv::cvtColor(img,?sample,?CV_GRAY2BGR);??
  • ????else??
  • ????????sample?=?img;??
  • ??
  • ????cv::Mat?sample_resized;??
  • ????if?(sample.size()?!=?input_geometry_)??
  • ????????cv::resize(sample,?sample_resized,?input_geometry_);??
  • ????else??
  • ????????sample_resized?=?sample;??
  • ??
  • ????cv::Mat?sample_float;??
  • ????if?(num_channels_?==?3)??
  • ????????sample_resized.convertTo(sample_float,?CV_32FC3);??
  • ????else??
  • ????????sample_resized.convertTo(sample_float,?CV_32FC1);??
  • ??
  • ????cv::Mat?sample_normalized;??
  • ????cv::subtract(sample_float,?mean_,?sample_normalized);??
  • ??
  • ????/*?This?operation?will?write?the?separate?BGR?planes?directly?to?the??
  • ????*?input?layer?of?the?network?because?it?is?wrapped?by?the?cv::Mat??
  • ????*?objects?in?input_channels.?*/??
  • ????cv::split(sample_normalized,?*input_channels);??
  • ??
  • ????CHECK(reinterpret_cast<float*>(input_channels->at(0).data)??
  • ????????==?net_->input_blobs()[0]->cpu_data())??
  • ????????<<?"Input?channels?are?not?wrapping?the?input?layer?of?the?network.";??
  • }??

  • 然后,我們?cè)賹?xiě)一個(gè)導(dǎo)出類(lèi)即可(如下(2))。

    (2)添加type_recognition_ver2_api_gpu.h和type_recognition_ver2_api_gpu.cpp

    [plain]?view plaincopy
  • //type_recognition_ver2_api_gpu.h??
  • #ifndef?TYPE_RECOGNITION_API_H_??//保證頭文件包含一次??
  • #define?TYPE_RECOGNITION_API_H_??
  • ??
  • #ifdef?TYPE_RECOGNITION_LINK_SHARED??
  • #if?defined(__GNUC__)?&&?__GNUC__?>=?4??
  • #define?TYPE_RECOGNITION_API?__attribute__?((visibility("default")))??
  • #elif?defined(__GNUC__)??
  • #define?TYPE_RECOGNITION_API??
  • #elif?defined(_MSC_VER)??
  • #if?defined?(TYPE_RECOGNITION_API_EXPORTS)??
  • #define?TYPE_RECOGNITION_API?__declspec(dllexport)??
  • #else??
  • #define?TYPE_RECOGNITION_API?__declspec(dllimport)??
  • #endif??
  • #else??
  • #define?TYPE_RECOGNITION_API??
  • #endif??
  • #else??
  • #define?TYPE_RECOGNITION_API??
  • #endif??
  • ??
  • #include?<opencv2/core/core.hpp>??
  • #include?<string>??
  • #include?<vector>??
  • /*?Pair?(label,?confidence)?representing?a?prediction.?*/??
  • typedef?std::pair<int,?float>?Prediction;??
  • class?TYPE_RECOGNITION_API?Classifier?//導(dǎo)出類(lèi)??
  • {??
  • public:??
  • ????Classifier(){};??
  • ????~Classifier();??
  • ????Classifier(const?std::string&?model_file,??
  • ????????const?std::string&?trained_file,??
  • ????????const?std::string&?mean_file,??
  • ????????const?std::string&?label_file);??
  • ????std::vector<Prediction>?Classify(const?cv::Mat&?img,?int?N?=?2);??
  • };??
  • ??
  • #endif??

  • [plain]?view plaincopy
  • //type_recognition_ver2_api_gpu.cpp??
  • #include?"type_recognition_ver2_api_gpu.h"??
  • #include?"classify.h"??
  • ClassifierImpl?*impl?=?NULL;??
  • Classifier::Classifier(const?std::string&?model_file,??
  • ????const?std::string&?trained_file,??
  • ????const?std::string&?mean_file,??
  • ????const?std::string&?label_file)??
  • {??
  • #ifdef?_MSC_VER??
  • #pragma?comment(?linker,?"/subsystem:windows")??
  • #endif??
  • ????impl?=?new?ClassifierImpl(model_file,?trained_file,?mean_file,?label_file);??
  • }??
  • ??
  • Classifier::~Classifier()??
  • {??
  • ????//impl->~ClassifierImpl();??
  • ????if?(impl)??
  • ????????delete?impl;??
  • }??
  • std::vector<Prediction>?Classifier::Classify(const?cv::Mat&?img,?int?N)??
  • {??
  • ????return?impl->Classify(img,?N);??
  • }??
  • 這時(shí),右鍵type_recognition_ver2_api_gpu項(xiàng)目,生成即可,在ReleaseGPU文件夾內(nèi)即可得到如下文件:


    用到的文件是dll和lib文件,使用這些文件方法如下。


    3.使用DLL

    將type_recognition_ver2_api_gpu.dll復(fù)制到caffe-windows-master\3rdparty\bin;

    將type_recognition_ver2_api_gpu.lib復(fù)制到caffe-windows-master\3rdparty\lib;

    將type_recognition_ver2_api_gpu.h復(fù)制到caffe-windows-master\3rdparty\include;

    然后,新建一個(gè)控制臺(tái)項(xiàng)目,配置成x64,

    右鍵項(xiàng)目配置如下:

    C/C++——常規(guī)——附加包含目錄:(這里路徑自己修改)

    ? ? ? ? ? ? ? ********\3rdparty\include

    鏈接器——常規(guī)——附加庫(kù)目錄:

    ? ? ? ? ? ? ?********\3rdparty\lib

    鏈接器——輸入——附加依賴項(xiàng):

    將type_recognition_ver2_api_gpu.lib和opencv_world300.lib加進(jìn)去,


    然后,為項(xiàng)目添加一個(gè)cpp文件:

    [plain]?view plaincopy
  • #include?<iostream>??
  • #include?<string>??
  • #include?<opencv2/core/core.hpp>??
  • #include?<opencv2/highgui/highgui.hpp>??
  • #include?"type_recognition_ver2_api_gpu.h"??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????std::string?model_file("./model/deploy.prototxt");??
  • ????std::string?trained_file("./model/net.caffemodel");??
  • ????std::string?mean_file("./model/type_mean.binaryproto");??
  • ????std::string?label_file("./model/typelabels.txt");??
  • ??
  • ????Classifier?myclassifier(model_file,?trained_file,?mean_file,?label_file);??
  • ??
  • ??????
  • ????cv::Mat?img?=?cv::imread("../image/automobile/000001.jpg",?-1);??
  • ??
  • ????std::vector<Prediction>?result?=?myclassifier.Classify(img);??
  • ????Prediction?p?=?result[0];??
  • ????std::cout?<<"類(lèi)別:"<<?p.first?<<?"確信度:"?<<?p.second?<<?"\n";??
  • ????getchar();??
  • ????return?0;??
  • }??
  • 結(jié)果:


    下面鏈接的代碼有bug,聲明多個(gè)對(duì)象會(huì)出問(wèn)題,新的代碼:http://blog.csdn.net/sinat_30071459/article/details/53735600)

    封裝好的代碼加入了OpenCV顯示圖像,可通過(guò)鏈接下載:http://download.csdn.net/detail/sinat_30071459/9568131? 是一個(gè)txt文件,因?yàn)閏sdn上傳限制,上傳到了百度云,txt里面有百度云鏈接。

    將Classification\CLassificationDLL\bin加入環(huán)境變量后即可。

    效果如下:(把Freetype庫(kù)也加了進(jìn)去,標(biāo)簽可以顯示中文)



    總結(jié)

    以上是生活随笔為你收集整理的封装caffe-windows-master为动态链接库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。