! * \brief The base transform for wrapping the Caffe deep learning library. This transform expects the input to a given Caffe model to be a MemoryDataLayer. * The output of the forward pass of the Caffe network is stored in dst as a list of matrices, the size of which is equal to the batch_size of the network. * Children of this transform should process dst to acheieve specifc use cases. * \au
| 61 | * \br_link Caffe website http://caffe.berkeleyvision.org |
| 62 | */ |
| 63 | class CaffeBaseTransform : public UntrainableMetaTransform |
| 64 | { |
| 65 | Q_OBJECT |
| 66 | |
| 67 | public: |
| 68 | Q_PROPERTY(QString model READ get_model WRITE set_model RESET reset_model STORED false) |
| 69 | Q_PROPERTY(QString weights READ get_weights WRITE set_weights RESET reset_weights STORED false) |
| 70 | Q_PROPERTY(int gpuDevice READ get_gpuDevice WRITE set_gpuDevice RESET reset_gpuDevice STORED false) |
| 71 | BR_PROPERTY(QString, model, "") |
| 72 | BR_PROPERTY(QString, weights, "") |
| 73 | BR_PROPERTY(int, gpuDevice, -1) |
| 74 | |
| 75 | Resource<CaffeNet> caffeResource; |
| 76 | |
| 77 | protected: |
| 78 | void init() |
| 79 | { |
| 80 | caffeResource.setResourceMaker(new CaffeResourceMaker(model, weights, gpuDevice)); |
| 81 | } |
| 82 | |
| 83 | bool timeVarying() const |
| 84 | { |
| 85 | return gpuDevice < 0 ? false : true; |
| 86 | } |
| 87 | |
| 88 | void project(const Template &src, Template &dst) const |
| 89 | { |
| 90 | CaffeNet *net = caffeResource.acquire(); |
| 91 | |
| 92 | if (net->layers()[0]->layer_param().type() != "MemoryData") |
| 93 | qFatal("OpenBR requires the first layer in the network to be a MemoryDataLayer"); |
| 94 | |
| 95 | MemoryDataLayer<float> *dataLayer = static_cast<MemoryDataLayer<float> *>(net->layers()[0].get()); |
| 96 | |
| 97 | if (src.size() != dataLayer->batch_size()) |
| 98 | qFatal("src should have %d (batch size) mats. It has %d mats.", dataLayer->batch_size(), src.size()); |
| 99 | |
| 100 | dataLayer->AddMatVector(src.toVector().toStdVector(), std::vector<int>(src.size(), 0)); |
| 101 | |
| 102 | net->ForwardPrefilled(); |
| 103 | Blob<float> *output = net->blobs().back().get(); |
| 104 | |
| 105 | int dimFeatures = output->count() / dataLayer->batch_size(); |
| 106 | for (int n = 0; n < dataLayer->batch_size(); n++) |
| 107 | dst += Mat(1, dimFeatures, CV_32FC1, output->mutable_cpu_data() + output->offset(n)); |
| 108 | |
| 109 | caffeResource.release(net); |
| 110 | } |
| 111 | }; |
| 112 | |
| 113 | /*! |
| 114 | * \brief This transform treats the output of the network as a feature vector and appends it unchanged to dst. Dst will have |
| 115 | * length equal to the batch size of the network. |
| 116 | * \author Jordan Cheney \cite JordanCheney |
| 117 | * \br_property QString model path to prototxt model file |
| 118 | * \br_property QString weights path to caffemodel file |
| 119 | * \br_property int gpuDevice ID of GPU to use. gpuDevice < 0 runs on the CPU only. |
| 120 | */ |