Commit dff3e093aaf2c596d4220c2cc34769c46e2edcdd

Authored by Jordan Cheney
1 parent 5c945c17

Update to Caffe framework

openbr/plugins/classification/caffe.cpp
1 1 #include <openbr/plugins/openbr_internal.h>
  2 +#include <openbr/core/opencvutils.h>
  3 +#include <openbr/core/qtutils.h>
2 4  
  5 +#include <opencv2/imgproc/imgproc.hpp>
3 6 #include <caffe/caffe.hpp>
4 7  
5 8 using caffe::Caffe;
6   -using caffe::Solver;
7 9 using caffe::Net;
  10 +using caffe::MemoryDataLayer;
8 11 using caffe::Blob;
9 12 using caffe::shared_ptr;
10   -using caffe::vector;
  13 +
  14 +using namespace cv;
11 15  
12 16 namespace br
13 17 {
14 18  
15 19 /*!
16   - * \brief A transform that wraps the Caffe Deep learning library
  20 + * \brief A transform that wraps the Caffe deep learning library. This transform expects the input to a given Caffe model to be a MemoryDataLayer.
  21 + * The output of the Caffe network is treated as a feature vector and is stored in dst. Batch processing is possible. For a given batch size set in
  22 + * the memory data layer, src is expected to have an equal number of mats. Dst will always have the same size (number of mats) as src and the ordering
  23 + * will be preserved, so dst[1] is the output of src[1] after it passes through the
17 24 * \author Jordan Cheney \cite jcheney
18   - * \br_property QString modelFile path to prototxt model file
19   - * \br_property QString solverFile path to prototxt solver file
20   - * \br_property QString weightsFile path to caffemodel file
  25 + * \br_property QString model path to prototxt model file
  26 + * \br_property QString weights path to caffemodel file
21 27 * \br_property int gpuDevice ID of GPU to use. gpuDevice < 0 runs on the CPU only.
22 28 * \br_link Caffe Integration Tutorial ../tutorials.md#caffe
23 29 * \br_link Caffe website http://caffe.berkeleyvision.org
24 30 */
25   -class CaffeTransform : public Transform
  31 +class CaffeFVTransform : public UntrainableTransform
26 32 {
27 33 Q_OBJECT
28 34  
29   - Q_PROPERTY(QString modelFile READ get_modelFile WRITE set_modelFile RESET reset_modelFile STORED false)
30   - Q_PROPERTY(QString solverFile READ get_solverFile WRITE set_solverFile RESET reset_solverFile STORED false)
31   - Q_PROPERTY(QString weightsFile READ get_weightsFile WRITE set_weightsFile RESET reset_weightsFile STORED false)
  35 + Q_PROPERTY(QString model READ get_model WRITE set_model RESET reset_model STORED false)
  36 + Q_PROPERTY(QString weights READ get_weights WRITE set_weights RESET reset_weights STORED false)
32 37 Q_PROPERTY(int gpuDevice READ get_gpuDevice WRITE set_gpuDevice RESET reset_gpuDevice STORED false)
33   - BR_PROPERTY(QString, modelFile, "")
34   - BR_PROPERTY(QString, solverFile, "")
35   - BR_PROPERTY(QString, weightsFile, "")
  38 + BR_PROPERTY(QString, model, "")
  39 + BR_PROPERTY(QString, weights, "")
36 40 BR_PROPERTY(int, gpuDevice, -1)
37 41  
  42 + QSharedPointer<Net<float> > net;
  43 +
38 44 void init()
39 45 {
40 46 if (gpuDevice >= 0) {
... ... @@ -43,47 +49,31 @@ class CaffeTransform : public Transform
43 49 } else {
44 50 Caffe::set_mode(Caffe::CPU);
45 51 }
  52 +
  53 + net.reset(new Net<float>(model.toStdString(), caffe::TEST));
  54 + net->CopyTrainedLayersFrom(weights.toStdString());
46 55 }
47 56  
48   - void train(const TemplateList &data)
  57 + void project(const Template &src, Template &dst) const
49 58 {
50   - (void) data;
  59 + MemoryDataLayer<float> *data_layer = static_cast<MemoryDataLayer<float> *>(net->layers()[0].get());
51 60  
52   - caffe::SolverParameter solver_param;
53   - caffe::ReadProtoFromTextFileOrDie(solverFile.toStdString(), &solver_param);
  61 + if (src.size() != data_layer->batch_size())
  62 + qFatal("src should have %d (batch size) mats. It has %d mats.", data_layer->batch_size(), src.size());
54 63  
55   - shared_ptr<Solver<float> > solver(caffe::GetSolver<float>(solver_param));
56   - solver->Solve();
57   - }
  64 + dst.file = src.file;
58 65  
59   - void project(const Template &src, Template &dst) const
60   - {
61   - (void)src; (void)dst;
62   - Net<float> net(modelFile.toStdString(), caffe::TEST);
63   - net.CopyTrainedLayersFrom(weightsFile.toStdString());
64   -
65   - vector<Blob<float> *> bottom_vec; // perhaps src data should go here?
66   - vector<int> test_score_output_id;
67   - vector<float> test_score;
68   -
69   - float loss;
70   - const vector<Blob<float> *> &result = net.Forward(bottom_vec, &loss);
71   -
72   - int idx = 0;
73   - for (int i = 0; i < (int)result.size(); i++) {
74   - const float *result_data = result[i]->cpu_data();
75   - for (int j = 0; j < result[i]->count(); j++, idx++) {
76   - test_score.push_back(result_data[j]);
77   - test_score_output_id.push_back(i);
78   -
79   - if (Globals->verbose)
80   - qDebug("%s = %f", net.blob_names()[net.output_blob_indices()[i]].c_str(), result_data[j]);
81   - }
82   - }
  66 + data_layer->AddMatVector(src.toVector().toStdVector(), std::vector<int>(src.size(), 0));
  67 +
  68 + Blob<float> *output = net->ForwardPrefilled()[1]; // index 0 is the labels from the data layer (in this case the 0 array we passed in above).
  69 + // index 1 is the ouput of the final layer, which is what we want
  70 + int dim_features = output->count() / data_layer->batch_size();
  71 + for (int n = 0; n < data_layer->batch_size(); n++)
  72 + dst += Mat(1, dim_features, CV_32FC1, output->mutable_cpu_data() + output->offset(n));
83 73 }
84 74 };
85 75  
86   -BR_REGISTER(Transform, CaffeTransform)
  76 +BR_REGISTER(Transform, CaffeFVTransform)
87 77  
88 78 } // namespace br
89 79  
... ...
openbr/plugins/cmake/lmdbGallery.cmake deleted
1   -set(BR_WITH_CAFFE OFF CACHE BOOL "Build with Caffe")
2   -
3   -if (${BR_WITH_CAFFE})
4   - find_package(Caffe)
5   - set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${Caffe_LIBRARIES})
6   - include_directories(${Caffe_INCLUDE_DIRS})
7   -else()
8   - set(BR_EXCLUDED_PLUGINS ${BR_EXCLUDED_PLUGINS} plugins/gallery/lmdbGallery.cpp)
9   -endif()
10   -
openbr/plugins/imgproc/pad.cpp 0 → 100644
  1 +#include <openbr/plugins/openbr_internal.h>
  2 +
  3 +using namespace cv;
  4 +
  5 +namespace br
  6 +{
  7 +
  8 +class PadTransform : public UntrainableTransform
  9 +{
  10 + Q_OBJECT
  11 +
  12 + Q_PROPERTY(int padSize READ get_padSize WRITE set_padSize RESET reset_padSize STORED false)
  13 + Q_PROPERTY(int padValue READ get_padValue WRITE set_padValue RESET reset_padValue STORED false)
  14 + BR_PROPERTY(int, padSize, 0)
  15 + BR_PROPERTY(int, padValue, 0)
  16 +
  17 + void project(const Template &src, Template &dst) const
  18 + {
  19 + dst.file = src.file;
  20 +
  21 + foreach (const Mat &m, src) {
  22 + Mat padded = padValue * Mat::ones(m.rows + 2*padSize, m.cols + 2*padSize, m.type());
  23 + padded(Rect(padSize, padSize, padded.cols - padSize, padded.rows - padSize)) = m;
  24 + dst += padded;
  25 + }
  26 + }
  27 +};
  28 +
  29 +BR_REGISTER(Transform, PadTransform)
  30 +
  31 +} // namespace br
  32 +
  33 +#include "imgproc/pad.moc"
... ...
openbr/plugins/imgproc/roi.cpp
... ... @@ -26,12 +26,16 @@ namespace br
26 26 * \ingroup transforms
27 27 * \brief Crops the rectangular regions of interest.
28 28 * \author Josh Klontz \cite jklontz
  29 + * \br_property QString propName Optional property name for a rectangle in metadata. If no propName is given the transform will use rects stored in the file.rects field or build a rectangle using "X", "Y", "Width", and "Height" fields if they exist.
  30 + * \br_property bool copyOnCrop If true make a clone of each crop before appending the crop to dst. This guarantees that the crops will be continuous in memory, which is an occasionally useful property. Default is false.
29 31 */
30 32 class ROITransform : public UntrainableTransform
31 33 {
32 34 Q_OBJECT
33 35 Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
  36 + Q_PROPERTY(bool copyOnCrop READ get_copyOnCrop WRITE set_copyOnCrop RESET reset_copyOnCrop STORED false)
34 37 BR_PROPERTY(QString, propName, "")
  38 + BR_PROPERTY(bool, copyOnCrop, false)
35 39  
36 40 void project(const Template &src, Template &dst) const
37 41 {
... ... @@ -52,6 +56,10 @@ class ROITransform : public UntrainableTransform
52 56 qWarning("No rects present in file.");
53 57 }
54 58 dst.file.clearRects();
  59 +
  60 + if (copyOnCrop)
  61 + for (int i = 0; i < dst.size(); i++)
  62 + dst.replace(i, dst[i].clone());
55 63 }
56 64 };
57 65  
... ...