@@ -25,14 +25,14 @@ class Classifier {
25
25
const string& mean_file,
26
26
const string& label_file);
27
27
28
- std::vector<Prediction> Classify (const cv::Mat& img , int N = 5 );
28
+ std::vector<std::vector< Prediction> > Classify (const std::vector< cv::Mat>& imgs , int N = 5 );
29
29
30
30
private:
31
31
void SetMean (const string& mean_file);
32
32
33
- std::vector<float > Predict (const cv::Mat& img );
33
+ std::vector<std::vector< float > > Predict (const std::vector< cv::Mat>& imgs );
34
34
35
- void WrapInputLayer (std::vector<cv::Mat>* input_channels);
35
+ void WrapInputLayer (std::vector<cv::Mat>* input_channels, int n );
36
36
37
37
void Preprocess (const cv::Mat& img,
38
38
std::vector<cv::Mat>* input_channels);
@@ -102,18 +102,24 @@ static std::vector<int> Argmax(const std::vector<float>& v, int N) {
102
102
}
103
103
104
104
/* Return the top N predictions. */
105
- std::vector<Prediction> Classifier::Classify (const cv::Mat& img, int N) {
106
- std::vector<float > output = Predict (img);
107
-
108
- N = std::min<int >(labels_.size (), N);
109
- std::vector<int > maxN = Argmax (output, N);
110
- std::vector<Prediction> predictions;
111
- for (int i = 0 ; i < N; ++i) {
112
- int idx = maxN[i];
113
- predictions.push_back (std::make_pair (labels_[idx], output[idx]));
114
- }
115
-
116
- return predictions;
105
+ std::vector<std::vector<Prediction> > Classifier::Classify (const std::vector<cv::Mat>& imgs, int N) {
106
+ std::vector<std::vector<float > > outputs = Predict (imgs);
107
+
108
+ std::vector<std::vector<Prediction> > all_predictions;
109
+ for (int j = 0 ; j < outputs.size (); ++j) {
110
+ std::vector<float > output = outputs[j];
111
+
112
+ N = std::min<int >(labels_.size (), N);
113
+ std::vector<int > maxN = Argmax (output, N);
114
+ std::vector<Prediction> predictions;
115
+ for (int i = 0 ; i < N; ++i) {
116
+ int idx = maxN[i];
117
+ predictions.push_back (std::make_pair (labels_[idx], output[idx]));
118
+ }
119
+ all_predictions.push_back (predictions);
120
+ }
121
+
122
+ return all_predictions;
117
123
}
118
124
119
125
/* Load the mean file in binaryproto format. */
@@ -147,42 +153,48 @@ void Classifier::SetMean(const string& mean_file) {
147
153
mean_ = cv::Mat (input_geometry_, mean.type (), channel_mean);
148
154
}
149
155
150
- std::vector<float > Classifier::Predict (const cv::Mat& img ) {
156
+ std::vector<std::vector< float > > Classifier::Predict (const std::vector< cv::Mat>& imgs ) {
151
157
Blob<float >* input_layer = net_->input_blobs ()[0 ];
152
- input_layer->Reshape (1 , num_channels_,
158
+ input_layer->Reshape (imgs. size () , num_channels_,
153
159
input_geometry_.height , input_geometry_.width );
154
160
/* Forward dimension change to all layers. */
155
161
net_->Reshape ();
156
162
157
- std::vector<cv::Mat> input_channels;
158
- WrapInputLayer (& input_channels) ;
159
-
160
- Preprocess (img , &input_channels);
161
-
163
+ for ( int i = 0 ; i < imgs. size (); ++i) {
164
+ std::vector<cv::Mat> input_channels;
165
+ WrapInputLayer (&input_channels, i);
166
+ Preprocess (imgs[i] , &input_channels);
167
+ }
162
168
net_->ForwardPrefilled ();
163
169
164
- /* Copy the output layer to a std::vector */
170
+ std::vector<std::vector<float > > outputs;
171
+
165
172
Blob<float >* output_layer = net_->output_blobs ()[0 ];
166
- const float * begin = output_layer->cpu_data ();
167
- const float * end = begin + output_layer->channels ();
168
- return std::vector<float >(begin, end);
173
+ for (int i = 0 ; i < output_layer->num (); ++i) {
174
+ const float * begin = output_layer->cpu_data () + i * output_layer->channels ();
175
+ const float * end = begin + output_layer->channels ();
176
+ /* Copy the output layer to a std::vector */
177
+ outputs.push_back (std::vector<float >(begin, end));
178
+ }
179
+ return outputs;
169
180
}
170
181
171
182
/* Wrap the input layer of the network in separate cv::Mat objects
172
183
* (one per channel). This way we save one memcpy operation and we
173
184
* don't need to rely on cudaMemcpy2D. The last preprocessing
174
185
* operation will write the separate channels directly to the input
175
186
* layer. */
176
- void Classifier::WrapInputLayer (std::vector<cv::Mat>* input_channels) {
187
+ void Classifier::WrapInputLayer (std::vector<cv::Mat>* input_channels, int n ) {
177
188
Blob<float >* input_layer = net_->input_blobs ()[0 ];
178
189
179
190
int width = input_layer->width ();
180
191
int height = input_layer->height ();
181
- float * input_data = input_layer->mutable_cpu_data ();
182
- for (int i = 0 ; i < input_layer->channels (); ++i) {
183
- cv::Mat channel (height, width, CV_32FC1, input_data);
184
- input_channels->push_back (channel);
185
- input_data += width * height;
192
+ int channels = input_layer->channels ();
193
+ float * input_data = input_layer->mutable_cpu_data () + n * width * height * channels;
194
+ for (int i = 0 ; i < channels; ++i) {
195
+ cv::Mat channel (height, width, CV_32FC1, input_data);
196
+ input_channels->push_back (channel);
197
+ input_data += width * height;
186
198
}
187
199
}
188
200
@@ -221,13 +233,15 @@ void Classifier::Preprocess(const cv::Mat& img,
221
233
* objects in input_channels. */
222
234
cv::split (sample_normalized, *input_channels);
223
235
236
+ /*
224
237
CHECK(reinterpret_cast<float*>(input_channels->at(0).data)
225
238
== net_->input_blobs()[0]->cpu_data())
226
239
<< "Input channels are not wrapping the input layer of the network.";
240
+ */
227
241
}
228
242
229
243
int main (int argc, char ** argv) {
230
- if (argc != 6 ) {
244
+ if (argc < 6 ) {
231
245
std::cerr << " Usage: " << argv[0 ]
232
246
<< " deploy.prototxt network.caffemodel"
233
247
<< " mean.binaryproto labels.txt img.jpg" << std::endl;
@@ -242,20 +256,27 @@ int main(int argc, char** argv) {
242
256
string label_file = argv[4 ];
243
257
Classifier classifier (model_file, trained_file, mean_file, label_file);
244
258
245
- string file = argv[ 5 ] ;
246
-
247
- std::cout << " ---------- Prediction for "
248
- << file << " ---------- " << std::endl ;
249
-
250
- cv::Mat img = cv::imread (file, - 1 );
251
- CHECK (!img. empty ()) << " Unable to decode image " << file;
252
- std::vector<Prediction> predictions = classifier.Classify (img );
259
+ std::vector<cv::Mat> imgs ;
260
+ for ( int i = 5 ; i < argc; ++i)
261
+ {
262
+ cv::Mat img = cv::imread (argv[i], - 1 ) ;
263
+ CHECK (!img. empty ()) << " Unable to decode image " << argv[i];
264
+ imgs. push_back (img );
265
+ }
266
+ std::vector<std::vector< Prediction> > all_predictions = classifier.Classify (imgs );
253
267
254
268
/* Print the top N predictions. */
255
- for (size_t i = 0 ; i < predictions.size (); ++i) {
256
- Prediction p = predictions[i];
257
- std::cout << std::fixed << std::setprecision (4 ) << p.second << " - \" "
258
- << p.first << " \" " << std::endl;
269
+ for (size_t i = 0 ; i < all_predictions.size (); ++i) {
270
+ std::cout << " ---------- Prediction for "
271
+ << argv[5 + i] << " ----------" << std::endl;
272
+
273
+ std::vector<Prediction>& predictions = all_predictions[i];
274
+ for (size_t j = 0 ; j < predictions.size (); ++j) {
275
+ Prediction p = predictions[j];
276
+ std::cout << std::fixed << std::setprecision (4 ) << p.second << " - \" "
277
+ << p.first << " \" " << std::endl;
278
+ }
279
+ std::cout << std::endl;
259
280
}
260
281
}
261
282
#else
0 commit comments