手头有一个实际的视觉检测的项目,用的是caffe来分类,于是需要用caffe新建自己的项目的例子。在网上找了好久都没有找到合适的,于是自己开始弄。

1 首先是配置caffe的VC++目录中的include和库文件。配置include lib dll都是坑,而且还分debug和release两个版本。添加输入项目需要注意,而且需要把编译好的caffe.lib等等一系列东西拷贝到当前项目下。也就是caffe bulid文件夹下面的东西,包括caffe.lib 、libcaffe.lib、还有很多dll.

这个是debug_include配置图

这个是debug_lib配置图

这个是release_include配置图

这个是release_lib配置图

同时也需要在,项目属性页的链接器输入中,填写相应的lib,其中debug和release是不同的。以下是需要填写的相应lib

//debug
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_ml2413d.lib
opencv_objdetect2413d.lib
opencv_ts2413d.lib
opencv_video2413d.lib
caffe.lib
libcaffe.lib
cudart.lib
cublas.lib
curand.lib
gflagsd.lib
libglog.lib
libopenblas.dll.a
libprotobuf.lib
leveldb.lib
hdf5.lib
hdf5_hl.lib
Shlwapi.lib
//release
opencv_calib3d2413.lib
opencv_contrib2413.lib
opencv_core2413.lib
opencv_features2d2413.lib
opencv_flann2413.lib
opencv_gpu2413.lib
opencv_highgui2413.lib
opencv_imgproc2413.lib
opencv_legacy2413.lib
opencv_ml2413.lib
opencv_objdetect2413.lib
opencv_ts2413.lib
opencv_video2413.lib
caffe.lib
libcaffe.lib
cudart.lib
cublas.lib
curand.lib
gflags.lib
libglog.lib
libopenblas.dll.a
libprotobuf.lib
leveldb.lib
lmdb.lib
hdf5.lib
hdf5_hl.lib
Shlwapi.lib

2 新建一个Classifier的c++类,其中头文件为

#include "stdafx.h"

#include <caffe/caffe.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <algorithm>
#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
#include <vector> #pragma once using namespace caffe; // NOLINT(build/namespaces)
using std::string;
//using namespace boost; 注意不需要添加这个 /* Pair (label, confidence) representing a prediction. */
typedef std::pair<string, float> Prediction; class Classifier
{
public:
Classifier(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 = 5); ~Classifier(); 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:
boost::shared_ptr<Net<float> > net_;
cv::Size input_geometry_;
int num_channels_;
cv::Mat mean_;
std::vector<string> labels_;
};

  c++文件为

#include "stdafx.h"
#include "Classifier.h" Classifier::Classifier(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); /* Load labels. */
std::ifstream labels(label_file.c_str());
CHECK(labels) << "Unable to open labels file " << label_file;
string line;
while (std::getline(labels, line))
labels_.push_back(string(line)); Blob<float>* output_layer = net_->output_blobs()[0];
CHECK_EQ(labels_.size(), output_layer->channels())
<< "Number of labels is different from the output layer dimension.";
} 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], static_cast<int>(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> Classifier::Classify(const cv::Mat& img, int N) {
std::vector<float> output = Predict(img); N = std::min<int>(labels_.size(), N);
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(labels_[idx], output[idx]));
} return predictions;
} /* Load the mean file in binaryproto format. */
void Classifier::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> Classifier::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_->Forward(); /* 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 Classifier::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 Classifier::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::COLOR_BGR2GRAY);
else if (img.channels() == 4 && num_channels_ == 1)
cv::cvtColor(img, sample, cv::COLOR_BGRA2GRAY);
else if (img.channels() == 4 && num_channels_ == 3)
cv::cvtColor(img, sample, cv::COLOR_BGRA2BGR);
else if (img.channels() == 1 && num_channels_ == 3)
cv::cvtColor(img, sample, cv::COLOR_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.";
} Classifier::~Classifier()
{
}

  c++,文件来自于\caffe-master\examples\cpp_classification中的classification.cpp文件

3 直接编译后会出现的问题是F0519 14:54:12.494139 14504 layer_factory.hpp:77] Check failed: registry.count(t ype) == 1 (0 vs. 1) Unknown layer type: Input (known types: Input ),百度后发现是要加头文件!http://blog.csdn.net/fangjin_kl/article/details/50936952#0-tsina-1-63793-397232819ff9a47a7b7e80a40613cfe1

因此安装上面说的新建一个head.h

#include "caffe/common.hpp"
#include "caffe/layers/input_layer.hpp"
#include "caffe/layers/inner_product_layer.hpp"
#include "caffe/layers/dropout_layer.hpp"
#include "caffe/layers/conv_layer.hpp"
#include "caffe/layers/relu_layer.hpp" #include "caffe/layers/pooling_layer.hpp"
#include "caffe/layers/lrn_layer.hpp"
#include "caffe/layers/softmax_layer.hpp" namespace caffe
{ extern INSTANTIATE_CLASS(InputLayer);
extern INSTANTIATE_CLASS(InnerProductLayer);
extern INSTANTIATE_CLASS(DropoutLayer);
extern INSTANTIATE_CLASS(ConvolutionLayer);
REGISTER_LAYER_CLASS(Convolution);
extern INSTANTIATE_CLASS(ReLULayer);
REGISTER_LAYER_CLASS(ReLU);
extern INSTANTIATE_CLASS(PoolingLayer);
REGISTER_LAYER_CLASS(Pooling);
extern INSTANTIATE_CLASS(LRNLayer);
REGISTER_LAYER_CLASS(LRN);
extern INSTANTIATE_CLASS(SoftmaxLayer);
REGISTER_LAYER_CLASS(Softmax); }

注意上述网络可能不全,需要根据实际的网络添加层。参考

 #include<caffe/common.hpp>
#include<caffe/proto/caffe.pb.h>
#include<caffe/layers/batch_norm_layer.hpp>
#include<caffe/layers/bias_layer.hpp>
#include <caffe/layers/concat_layer.hpp>
#include <caffe/layers/conv_layer.hpp>
#include <caffe/layers/dropout_layer.hpp>
#include<caffe/layers/input_layer.hpp>
#include <caffe/layers/inner_product_layer.hpp>
#include "caffe/layers/lrn_layer.hpp"
#include <caffe/layers/pooling_layer.hpp>
#include <caffe/layers/relu_layer.hpp>
#include "caffe/layers/softmax_layer.hpp"
#include<caffe/layers/scale_layer.hpp>
namespace caffe
{
extern INSTANTIATE_CLASS(BatchNormLayer);
extern INSTANTIATE_CLASS(BiasLayer);
extern INSTANTIATE_CLASS(InputLayer);
extern INSTANTIATE_CLASS(InnerProductLayer);
extern INSTANTIATE_CLASS(DropoutLayer);
extern INSTANTIATE_CLASS(ConvolutionLayer);
REGISTER_LAYER_CLASS(Convolution);
extern INSTANTIATE_CLASS(ReLULayer);
REGISTER_LAYER_CLASS(ReLU);
extern INSTANTIATE_CLASS(PoolingLayer);
REGISTER_LAYER_CLASS(Pooling);
extern INSTANTIATE_CLASS(LRNLayer);
REGISTER_LAYER_CLASS(LRN);
extern INSTANTIATE_CLASS(SoftmaxLayer);
REGISTER_LAYER_CLASS(Softmax);
extern INSTANTIATE_CLASS(ScaleLayer);
extern INSTANTIATE_CLASS(ConcatLayer); }

4 出现的第二个问题是有些符号GLOG_NO_ABBREVIATED_SEVERITIES未定义,因此在项目属性页 c++预处理器中添加下面两个:

GLOG_NO_ABBREVIATED_SEVERITIES
_SCL_SECURE_NO_WARNINGS

5 同时需要把

#include <caffe/proto/caffe.pb.h>
#include "head.h"

这两个头文件放到stdafx.h中,必须放到里面。

6 编译通过后,编写测试分类的程序,首先加载caffermodle.

string model_file = "D:\\caffe\\caffe-master\\mypower\\deploy.prototxt";//prototxt 这个必须是depoly,这个是计算输出的类别概率
string trained_file = "D:\\caffe\\caffe-master\\mypower_iter_2000.caffemodel"; //这个是训练好的model
string mean_file = "D:\\caffe\\caffe-master\\mypower\\imagenet_mean.binaryproto";//这个是均值文件
string label_file ="D:\\caffe\\caffe-master\\mypower\\label.txt"; //这个是样本标签 ,如果两类,可以新建一个txt文件,里面写作如下

0 good
1 bad

定义一个指针  Classifier *classifier;
classifier = new Classifier(model_file, trained_file, mean_file, label_file);

分类程序:

   cv::Mat img(roiimage, 0);//加载图像
//CHECK(!img.empty()) << "Unable to decode image " ;
std::vector<Prediction> predictions = classifier->Classify(img);
/* Print the top N predictions. */
string precision_p0="";
for (size_t i = 0; i < predictions.size()-1; ++i)//只输出了概率最大的那一类,通常就是第一类
{
Prediction p = predictions[i];
precision_p0 = p.first;
std::cout << std::fixed << std::setprecision(4) << p.second << " - \""
<< p.first << "\"" << std::endl;
}
char firstc = precision_p0[0];
if (firstc == '0')//第一类正样本 好的
{
//AfxMessageBox("good");
}
else //第二类负样本 存在缺陷
{
//AfxMessageBox("bad");
}

caffe-window搭建自己的小项目例子的更多相关文章

  1. 【vuejs小项目】一、脚手架搭建工作

    一.关于vuejs 这是一个MVVM的前端开发框架,model(数据).viewmode(通讯).view(视图),它吸取了reactjs和angularjs的长处,核心重点在于组件化的设计原则. 我 ...

  2. docker项目——搭建飞机大战小游戏

    项目2:搭建打飞机小游戏,验证数据持久化(最底下有链接) 第一步:拉取镜像 [root@localhost docker-image]# docker load < httpd_img.tar. ...

  3. 跟我一起用node-express搭建一个小项目(mongodb)[二]

    我的小项目主要是会用到MongoDB. 呵呵,我也是现学现卖. 都说小公司十八般武艺样样稀疏,没有办法啊! 兵来兵挡,将来将挡!自己是个兵呢?还是一个将呢! 没有公司培养,就自己培养自己呗.差的远一点 ...

  4. Flask框架的学习与实战(二):实战小项目

    昨天写了一篇flask开发环境搭建,今天继续,进行一个实战小项目-blog系统. blog系统很简单,只有一个页面,然而麻雀虽小五脏俱全.这里目的不是为了做项目而做项目,这篇文章本意是通过这次练习传达 ...

  5. 10分钟掌握Python-机器学习小项目

    学习机器学习相关技术的最好方式就是先自己设计和完成一些小项目. Python 是一种非常流行和强大的解释性编程语言.不像 R 语言,Python 是个很完整的语言和平台,你既可以用来做研发,也可以用来 ...

  6. Andriod小项目——在线音乐播放器

    转载自: http://blog.csdn.net/sunkes/article/details/51189189 Andriod小项目——在线音乐播放器 Android在线音乐播放器 从大一开始就已 ...

  7. 【PHP小项目使用MVC架构】

    小项目名称是雇员管理系统. mvc是一种项目的开发模式,中文名称为模式视图控制器,是强制程序员将数据的输入.处理.输出分开的一种开发模式. 在这个小项目中,控制器使用service作为后缀名. 项目u ...

  8. MOGRE学习笔记(3)--MOGRE小项目练习

    学习OGRE有一段时间了,领导为了检测学习效果,根据已有C++项目,弄一个类似的用c#语言编写的小项目. 配置:win7,DirectX2009,vs2010. 项目要求: 1.有Ogre窗口(尺寸1 ...

  9. Django集成celery实战小项目

    上一篇已经介绍了celery的基本知识,本篇以一个小项目为例,详细说明django框架如何集成celery进行开发. 本系列文章的开发环境: window 7 + python2.7 + pychar ...

随机推荐

  1. [ASE][Daily Scrum]11.27

    View Shilin Liu 设计死亡处理 Yiming Liao 处理tank-子弹碰撞事件     Server Songtao He 修复子弹队列满时的bug Junbei Zhang 服务器 ...

  2. 蛙蛙推荐:WEB安全入门

    信息安全基础 信息安全目标 真实性:对信息的来源进行判断,能对伪造来源的信息予以鉴别, 就是身份认证. 保密性:保证机密信息不被窃听,盗取,或窃听者不能了解信息的真实含义. 完整性:保证数据的一致性, ...

  3. 消息智能路由组件SmartRoute

    消息传递在软件开发过程中是一件很常见的事情,而在不同的场景所使用消息传递方式也有所不同,在对象之间制定相关接口方法和对象结构,对于进程之间可能使用内存共享或一些通讯产品,在不同服务器之的消息通讯则使用 ...

  4. SQL SERVER 2012 只能识别20个CPU的问题

    背景 最近在给客户优化时时候发现客户的虚拟机环境分配了32C 但是只能识别20个,物理机64C,64G内存,本来没什么,CPU利用率在40%左右,但是优化后同时增加了 CPU和内存的分配,CPU32增 ...

  5. 微软四十周年 Microsoft’s 40th anniversary

    比尔-盖茨在4月3日给微软全体员工写了这封邮件,原文是英文,我们翻译了中文.图片是后加上的. 明天将是特殊的一天:微软的40周年纪念日. Tomorrow is a special day: Micr ...

  6. 使用Guava提供的transform批量转换

    实际开发了,为了快速查询,我们会把日期以Long类型的方式存储到数据库中,比如20000000000000L,但显示的时候,要完整的日期,即yyyy-MM-dd的格式显示. 这个时候,我们就可以使用C ...

  7. [异常解决] MPU6050启动异常读出陀螺仪和加速度计的值全为0的解决办法

    在调试一个自己做的手环,每次用keil烧写好程序运行的蓝牙.陀螺仪都是正常的.但是掉电再上电之后蓝牙是好的.陀螺仪可以读出ID但是读出的加速度和角速度数据全为0. 下面是发生问题时main函数的前面部 ...

  8. [异常解决] vmware tools 虚拟机 --> 更新/导入wmwera tools菜单变灰,无法导入问题解决

    在虚拟中的装Ubuntu只要下载一个Ubuntu镜像,按照新建的指示一步一步安装 ,但是安装好之后想从原来系统中复制点东西到虚拟机中的Ubuntu中却有点麻烦.幸好Vmware自带了一个VMware ...

  9. 如何应用Font Awesome矢量字体图标

    Font Awesome 是一套专门为 Twitter Boostrap 设计的图标字体库.这套图标字体集几乎囊括了网页中可能用到的所有图标,除了包括 Twitter Boostrap 的默认图标外, ...

  10. Java8的新特性以及与C#的比较

    函数式接口 VS 委托 在C中,可以使用函数指针来存储函数的入口,从而使得函数可以像变量一样赋值.传递和存储,使得函数的调用变得十分灵活,是实现函数回调的基础.然而函数指针不存在函数的签名信息,甚至可 ...