BVLC / caffe

Caffe: a fast open framework for deep learning.
http://caffe.berkeleyvision.org/
Other
34.03k stars 18.7k forks source link

how to make a prediction in C++ #499

Closed onauparc closed 10 years ago

onauparc commented 10 years ago

Hi, I'm using caffe and I'm trying to make a prediction in C++ with a pretrained network like this python example http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/imagenet_classification.ipynb. But I don't find a C++ method for prediction and I don't get how to pass an input image and make the prediction. I've seen test_net.cpp but it does not pass any image in input. How can I pass an image or more images in input to the network? How can I make a prediction?

sguada commented 10 years ago

You could use a Image-Data layer to specify which images need to be processed.

On Friday, June 13, 2014, onauparc notifications@github.com wrote:

Hi, I'm using caffe and I'm trying to make a prediction in C++ with a pretrained network like this python example http://nbviewer.ipython.org/github/BVLC/caffe/blob/master/examples/imagenet_classification.ipynb. But I don't find a C++ method for prediction and I don't get how to pass an input image and make the prediction. I've seen test_net.cpp but it does not pass any image in input. How can I pass an image or more image in input to the network? How can I make a prediction?

— Reply to this email directly or view it on GitHub https://github.com/BVLC/caffe/issues/499.

Sergio

onauparc commented 10 years ago

Hi, I think I've found how to make a prediction. I used this code:

Datum datum; ReadImageToDatum("./cat.png", 10, 227, 227, &datum); Blob* blob = new Blob(10, datum.channels(), datum.height(), datum.width()); vector<Blob_> bottom; bottom.pushback(blob); float type = 0.0; const vector<Blob>& result = caffe_test_net.Forward(bottom, &type);

Now I have another doubt. How can I get the predicted class?

Here https://github.com/BVLC/caffe/blob/a34816263c1e5181ac0eb857a20fdaabd07b80e9/tools/test_net.cpp I saw that I can get the accuracy in this way: result[0]->cpu_data()[0]; But I need the predicted class. What does cpu_data() contain?

sguada commented 10 years ago

For doing predictions with just one image, you don't need to create a blob with 10 images. Although you will need to change the prototxt to reflect that. You just need to find the class with the maximum prob, for that you can use argmax layer #421 on top of the prob layer, then result will contain the predicted classes.

What result contains depends on the last layer in the prototxt.

onauparc commented 10 years ago

Ok, perfect. I'll see. Thank you for your answers.

onauparc commented 10 years ago

Hi, I found how to make the predicion in C++, like the python image_net_classification example. Here https://gist.github.com/onauparc/dd80907401b26b602885 you can find my example, and it works! (It is based on this code https://github.com/BVLC/caffe/blob/master/tools/compute_image_mean.cpp.) The predicted class of the cat image is class 274, so it seems like the python example.

The problem is that in my example I did a lot of copy and rounds: I put data into datum, than I put it in in a blobproto, than in a proto, finally I can do the Forward! Since I have a minibatch input made by some opencv Mat, is there any example easier or more direct?

sguada commented 10 years ago

@onauparc I think you are making things a bit complicated. Also you forgot to subtract the mean_image.

I would recommend you use a image_data_layer (which take care of reading a list of images, cropping, resizing, subtracting the mean, ...) at top of your prototxt, and the argmax_layer at the bottom of your prototxt.

That way you will only need to specify a file containing the set of images you want to do prediction for, and you would only to do:

 //get the net
  Net<float> caffe_test_net(argv[1]);
  //get trained net
  caffe_test_net.CopyTrainedLayersFrom(argv[2]);
 // Run ForwardPrefilled 
  float loss;
  vector<Blob<float>*>& result =  caffe_test_net.ForwardPrefilled(&loss);
// Now result will contain the argmax results.
 float* argmaxs = result[0]->cpu_data();
  for (int i = 0; i < result[0]->num(); ++i) {
   LOG(INFO) << " Image: "<< i << " class:" << argmaxs[i];
  }
bhack commented 10 years ago

@onauparc If you have an image list on filesystem the best solution is to plug an image_data layer on top like in this example https://github.com/BVLC/caffe/blob/master/examples/feature_extraction/imagenet_val.prototxt @sguada I think if your mini batch is an in memory vector of opencv Mat there is no fast/direct way to fill the top layer. Probably only trying to take some code from image_data layer could be possibile to fill it with an in memory vector of Mat. Is this correct?

bhack commented 10 years ago

Or probably could be also used memory data layer?

bhack commented 10 years ago

@onauparc if you need in memory fill follow this PR https://github.com/BVLC/caffe/pull/251

sguada commented 10 years ago

@bhack There is not simple way to transform a opencv::Mat into a blob, since they store the data differently internally. Also usually there are several pre-processing steps to do, like mean subtraction, cropping, mirror, ... Once the data layer separates the data source from the data pre-processing #407 one could reuse some parts.

bhack commented 10 years ago

@sguada I.e. try to suppose that your mini batch is a vector of opencv Mat with fixed widht and height coming from candidate ROIs regions selected from a video frame. Why #251 could not work? Probably we cannot avoid to do it with zero copy but generally i think it could work.

sguada commented 10 years ago

@bhack what I meant is that one still need to do the pre-processing steps like Image_Data layers does. That means it is not simply copying pixels or using directly in-memory #196. Once data_source and data_prepocessing are separated then will be easier to add more data sources, including a vector of opencv Mat.

Although #251 was never finished or integrated, one could easily extend #196 or Image_data layer to do this. https://github.com/BVLC/caffe/blob/dev/src/caffe/layers/image_data_layer.cpp

But if you want to do PR for this it will be useful. If you tell me a bit more what do you have in mind I may be able to help more.

bhack commented 10 years ago

@sguada Yes in layers we have pre-processing steps and data mixed. #407 is very interesting but also this one is still not integrated like #251. Probably taking something from #251 could be a little bit easy as inspiration to unwrap opencv Mat structure in the meantime that a more general solution like #407 will be finalized.

bhack commented 10 years ago

@sguada The general idea is that users could have a standard computer vision pipeline with opencv (taking Mat from video or single image), than find (with opencv or using opencv inside caffe) some candidate regions inside the frame with an X algorithm (resulting in a vector of cv::Mat or a vector of Rect). Then do some pre-processing on this regions (still in opencv or in the preprocessing step inside Caffe) and then pass this region as fast as (minimizing copy) to the forward pass. So something from #251 actually could be useful. #407 seems a more general arch change that probably impact many things including the future of #251.

onauparc commented 10 years ago

Hi @sguada , as you suggested I've tried to use data_layer and then argmax layer with your code to make my prediction but I still have strong doubts.

This is the prototxt I used to make the net:

name: "CaffeNet"
layers {
  name: "data"
  type: IMAGE_DATA
  top: "data"
  top: "label"
  image_data_param {
    source: "my_path/examples/_temp/file_list.txt"
    mean_file: "my_path/data/ilsvrc12/imagenet_mean.binaryproto"
    batch_size: 4
    crop_size: 227
    mirror: false
    new_height: 256
    new_width: 256
  }
}
layers {
  name: "conv1"
  type: CONVOLUTION
  bottom: "data"       
  top: "conv1"         
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  convolution_param {
    num_output: 96
    kernel_size: 11
    stride: 4
  }
}
layers {
  name: "relu1"
  type: RELU
  bottom: "conv1"      
  top: "conv1"         
}
layers {
  name: "pool1"
  type: POOLING
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layers {
  name: "norm1"
  type: LRN
  bottom: "pool1"
  top: "norm1"
  lrn_param {
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
}
layers {
  name: "conv2"
  type: CONVOLUTION
  bottom: "norm1"
  top: "conv2"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  convolution_param {
    num_output: 256
    pad: 2
    kernel_size: 5
    group: 2
  }
}
layers {
  name: "relu2"
  type: RELU
  bottom: "conv2"
  top: "conv2"
}
layers {
  name: "pool2"
  type: POOLING
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layers {
  name: "norm2"
  type: LRN
  bottom: "pool2"
  top: "norm2"
  lrn_param {
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
}
layers {
  name: "conv3"
  type: CONVOLUTION
  bottom: "norm2"
  top: "conv3"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  convolution_param {
    num_output: 384
    pad: 1
    kernel_size: 3
  }
}
layers {
  name: "relu3"
  type: RELU
  bottom: "conv3"
  top: "conv3"
}
layers {
  name: "conv4"
  type: CONVOLUTION
  bottom: "conv3"
  top: "conv4"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  convolution_param {
    num_output: 384
    pad: 1
    kernel_size: 3
    group: 2
  }
}
layers {
  name: "relu4"
  type: RELU
  bottom: "conv4"
  top: "conv4"
}
layers {
  name: "conv5"
  type: CONVOLUTION
  bottom: "conv4"
  top: "conv5"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
    group: 2
  }
}
layers {
  name: "relu5"
  type: RELU
  bottom: "conv5"
  top: "conv5"
}
layers {
  name: "pool5"
  type: POOLING
  bottom: "conv5"
  top: "pool5"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layers {
  name: "fc6"
  type: INNER_PRODUCT
  bottom: "pool5"
  top: "fc6"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  inner_product_param {
    num_output: 4096
  }
}
layers {
  name: "relu6"
  type: RELU
  bottom: "fc6"
  top: "fc6"
}
layers {
  name: "drop6"
  type: DROPOUT
  bottom: "fc6"
  top: "fc6"
  dropout_param {
    dropout_ratio: 0.5
  }
}
layers {
  name: "fc7"
  type: INNER_PRODUCT
  bottom: "fc6"
  top: "fc7"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  inner_product_param {
    num_output: 4096
  }
}
layers {
  name: "relu7"
  type: RELU
  bottom: "fc7"
  top: "fc7"
}
layers {
  name: "drop7"
  type: DROPOUT
  bottom: "fc7"
  top: "fc7"
  dropout_param {
    dropout_ratio: 0.5
  }
}
layers {
  name: "fc8"
  type: INNER_PRODUCT
  bottom: "fc7"
  top: "fc8"
  blobs_lr: 1
  blobs_lr: 2
  weight_decay: 1
  weight_decay: 0
  inner_product_param {
    num_output: 1000
  }
}
layers {
  name: "prob"
  type: SOFTMAX
  bottom: "fc8"
  top: "prob"
}
layers {
  name: "output"
  type: ARGMAX
  bottom: "prob"
  top: "output"
}

And the file file_list.txt contains this string: my_path/examples/images/cat.jpg 0

I noticed that argmax returns 0. Actually it returns the number near the image path. It seems it is a label and argmax returns this label. If I change the label with 1, argmax returns 1! I don't know if I'm making some mistakes, but this is not the behavior that I expect. I would like to have a network, train it, (now I'm doing these steps with pretrained examples), than pass to the net new images and make a prediction with this net. Where am I wrong?

sguada commented 10 years ago

Since your prototxt have two free top blobs, label from the image_data layer and output from the argmax layer, then the result will contain two blobs, the first one being the image label and the second output being the predicted label. Currently you are looking at label, that's way when you change it, the result changes.

So you should look at the second blob in result. That way you can also compare if the predicted label is the same as the image label.

Sergio

2014-06-20 3:24 GMT-07:00 onauparc notifications@github.com:

Hi @sguada https://github.com/sguada , as you suggested I've tried to use data_layer and then argmax layer with your code to make my prediction but I still have strong doubts.

This is the prototxt I used to make the net:

name: "CaffeNet"layers { name: "data" type: IMAGE_DATA top: "data" top: "label" image_data_param { source: "my_path/examples/_temp/file_list.txt" mean_file: "my_path/data/ilsvrc12/imagenet_mean.binaryproto" batch_size: 4 crop_size: 227 mirror: false new_height: 256 new_width: 256 }}layers { name: "conv1" type: CONVOLUTION bottom: "data" top: "conv1" blobs_lr: 1 blobs_lr: 2 weight_decay: 1 weight_decay: 0 convolution_param { num_output: 96 kernel_size: 11 stride: 4 }}layers { name: "relu1" type: RELU bottom: "conv1" top: "conv1" }layers { name: "pool1" type: POOLING bottom: "conv1" top: "pool1" pooling_param { pool: MAX kernel_size: 3 stride: 2 }}layers { name: "norm1" type: LRN bottom: "pool1" top: "norm1" lrn_param { local_size: 5 alpha: 0.0001 beta: 0.75 }}layers { name: "conv2" type: CONVOLUTION bottom: "norm1" top: "conv2" blobs_lr: 1 blobs_lr: 2 weight_decay: 1 weight_decay: 0 convolution_param { num_output: 256 pad: 2 kernel_size: 5 group: 2 }}layers { name: "relu2" type: RELU bottom: "conv2" top: "conv2"}layers { name: "pool2" type: POOLING bottom: "conv2" top: "pool2" pooling_param { pool: MAX kernel_size: 3 stride: 2 }}layers { name: "norm2" type: LRN bottom: "pool2" top: "norm2" lrn_param { local_size: 5 alpha: 0.0001 beta: 0.75 }}layers { name: "conv3" type: CONVOLUTION bottom: "norm2" top: "conv3" blobs_lr: 1 blobs_lr: 2 weight_decay: 1 weight_decay: 0 convolution_param { num_output: 384 pad: 1 kernel_size: 3 }}layers { name: "relu3" type: RELU bottom: "conv3" top: "conv3"}layers { name: "conv4" type: CONVOLUTION bottom: "conv3" top: "conv4" blobs_lr: 1 blobs_lr: 2 weight_decay: 1 weight_decay: 0 convolution_param { num_output: 384 pad: 1 kernel_size: 3 group: 2 }}layers { name: "relu4" type: RELU bottom: "conv4" top: "conv4"}layers { name: "conv5" type: CONVOLUTION bottom: "conv4" top: "conv5" blobs_lr: 1 blobs_lr: 2 weight_decay: 1 weight_decay: 0 convolution_param { num_output: 256 pad: 1 kernel_size: 3 group: 2 }}layers { name: "relu5" type: RELU bottom: "conv5" top: "conv5"}layers { name: "pool5" type: POOLING bottom: "conv5" top: "pool5" pooling_param { pool: MAX kernel_size: 3 stride: 2 }}layers { name: "fc6" type: INNER_PRODUCT bottom: "pool5" top: "fc6" blobs_lr: 1 blobs_lr: 2 weight_decay: 1 weight_decay: 0 inner_product_param { num_output: 4096 }}layers { name: "relu6" type: RELU bottom: "fc6" top: "fc6"}layers { name: "drop6" type: DROPOUT bottom: "fc6" top: "fc6" dropout_param { dropout_ratio: 0.5 }}layers { name: "fc7" type: INNER_PRODUCT bottom: "fc6" top: "fc7" blobs_lr: 1 blobs_lr: 2 weight_decay: 1 weight_decay: 0 inner_product_param { num_output: 4096 }}layers { name: "relu7" type: RELU bottom: "fc7" top: "fc7"}layers { name: "drop7" type: DROPOUT bottom: "fc7" top: "fc7" dropout_param { dropout_ratio: 0.5 }}layers { name: "fc8" type: INNER_PRODUCT bottom: "fc7" top: "fc8" blobs_lr: 1 blobs_lr: 2 weight_decay: 1 weight_decay: 0 inner_product_param { num_output: 1000 }}layers { name: "prob" type: SOFTMAX bottom: "fc8" top: "prob"}layers { name: "output" type: ARGMAX bottom: "prob" top: "output"}

And the file file_list.txt contains this string: my_path/examples/images/cat.jpg 0

I noticed that argmax returns 0. Actually it returns the number near the image path. It seems it is a label and argmax returns this label. If I change the label with 1, argmax returns 1! I don't know if I'm making some mistakes, but this is not the behavior that I expect. I would like to have a network, train it, (now I'm doing these steps with pretrained examples), than pass to the net new images and make a prediction with this net. Where am I wrong?

— Reply to this email directly or view it on GitHub https://github.com/BVLC/caffe/issues/499#issuecomment-46664676.

onauparc commented 10 years ago

Fatastic!!! It works :) Thank you so much!!! Now my next challenge is to take in input a series of opencv Mat :)

shuokay commented 10 years ago

Hi, @sguada , I find the image_data_param have not define a 'channel' varible that specify the input image is color or gray. How can I specify whether the input image is grayscale or color?

kloudkl commented 10 years ago

@onauparc, I tried the ImageDataLayer as you asked in #251 using the code snippet of @sguada and your prototxt. It turns out that passing in a vector of cv::Mat can get exactly the same prediction results as loading the images from disk.

The predicted class label of the cat.jpg is 281 which corresponds to "n02120505 grey fox, gray fox, Urocyon cinereoargenteus" in the data/ilsvrc12/synset_words.txt. The fish-bike.jpg is predicted as 770 "n04118776 rule, ruler". If we want multiple top predictions, new parameters such as num_of_output_results need to be added to the ArgMaxLayer.

  //get the net
  Net<float> caffe_test_net(feature_extraction_proto);
  //get trained net
  caffe_test_net.CopyTrainedLayersFrom(pretrained_binary_proto);

  // Run ForwardPrefilled
  float loss;
//  const vector<Blob<float>*>& result = caffe_test_net.ForwardPrefilled(&loss);

// Run AddImagesAndLabels and Forward
  cv::Mat image = cv::imread("/path/to/caffe-fork/examples/images/fish-bike.jpg"); // or cat.jpg
  vector<cv::Mat> images(4, image);
  vector<int> labels(4, 0);
  const shared_ptr<ImageDataLayer<float> > image_data_layer =
      boost::static_pointer_cast<ImageDataLayer<float> >(
          caffe_test_net.layer_by_name("data"));
  image_data_layer->AddImagesAndLabels(images, labels);
  vector<Blob<float>* > dummy_bottom_vec;
  const vector<Blob<float>*>& result = caffe_test_net.Forward(dummy_bottom_vec, &loss);

  LOG(INFO)<< "Output result size: "<< result.size();
  // Now result will contain the argmax results.
  const float* argmaxs = result[1]->cpu_data();
  for (int i = 0; i < result[1]->num(); ++i) {
    LOG(INFO)<< " Image: "<< i << " class:" << argmaxs[i];
  }
onauparc commented 10 years ago

Ok, thank you @kloudki, it prefectly works! :) Though the creation of the net still depends on the "source" defined in the prototxt, though in this case it is not necessary. (I tried to remove it from the prototxt, or from file_list.txt but it doesn't work).

kloudkl commented 10 years ago

You're right in that it's not reliable to create a net without the "source" field of the ImageDataLayer. The ConvolutionLayer or more generally any layer in the network depends on the size of the bottom blob that is set up by the layer below.

  num_ = bottom[0]->num();
  channels_ = bottom[0]->channels();
  height_ = bottom[0]->height();
  width_ = bottom[0]->width();
  num_output_ = this->layer_param_.convolution_param().num_output();
  CHECK_GT(num_output_, 0);
  CHECK_EQ(channels_ % group_, 0);
  // The im2col result buffer would only hold one image at a time to avoid
  // overly large memory usage.
  int height_out = (height_ + 2 * pad_ - kernel_size_) / stride_ + 1;
  int width_out = (width_ + 2 * pad_ - kernel_size_) / stride_ + 1;
  col_buffer_.Reshape(
      1, channels_ * kernel_size_ * kernel_size_, height_out, width_out);

In this case, the images listed in the source file_list.txt actually initialize the blob but are not used in the Forward method of the ImageDataLayer. They are overridden by the images added by AddImagesAndLabels.

If it works for your purpose right now, then just use it. No need to wait for a more meticulously designed solution that separates the data sources and pre-processing steps.

anguyen8 commented 10 years ago

@onauparc : Could you share how you retrieve the list of probabilities/classes when you feed a list of in memory images (more than 1)? I really appreciate it!

Currently, I'm feeding one by one, and calling net.forward for each. However, I figure this might not very optimal performance-wise.

onauparc commented 10 years ago

@anguyen8 : To make a prediction of more images I use a prototoxt like that I posted above, the first layer (IMAGE_DATA) allows to take a list of images by a file (file_list.txt). Than I used the code posted above by sguada to make the forward on all the images (ForwardPrefilled) and get the results. Pay attention to the top free blobs that you have in your prototxt, for example in my prototxt I have two free blobs so the result of ForwardPrefilled will contain two blobs.

I hope this helps.

anguyen8 commented 10 years ago

@onauparc : Thanks so much, sir! Now I know that ForwardPrefilled is the one to call!

ChelaruViorel commented 10 years ago

Hi, I tried the same example explained above but in my file_text.txt I've put 2 files and in the prototxt there is batch_size: 4; the code works, but I get 4 image classifications, when I said in the file_text.txt to classify only 2; same for batch_size: 100...I get 100 classifications... of WHAT IMAGES ? I use caffe/examples/imagenet/caffe_reference_imagenet_mode pretrained net, and exactly the same prototxt posted above.

thanks a lot, Viorel

ChelaruViorel commented 10 years ago

after reading the code I saw that if the batch size > nr of files in file_text.txt it resets the line id to 0 and starts iterating the image list from the beginning.... so for my 2 images I put batch size = 2 and it takes my 2 images only once.

I replaced the image data layer with this one : name: "CaffeNet" layers { name: "data" type: IMAGE_DATA top: "data" top: "label" image_data_param { source: "file_list.txt" batch_size: 2 crop_size: 0 mirror: false new_height: 0 new_width: 0 } }

and it works, but every time I get a different classifier result.....so a different class number every time I run the classification for the 2 images.

does anyone know what I'm doing wrong ? thanks a lot, Viorel

shelhamer commented 10 years ago

Right: Caffe always processes a batch_size amount of data even if fewer instances than batch_size are provided. Depending on the data layer the other instances are either zero or looped.

To fix the variable results you need to set the phase to TEST. By default Caffe models are instantiated in TRAIN phase, which means that dropout is done and the result is therefore nondeterministic.

See #192 for context.

p.s. Please ask further questions on the caffe-users mailing list. As of the latest release we prefer to keep issues reserved for Caffe development. Thanks!

ChelaruViorel commented 10 years ago

I set phase to TEST and now the classification is deterministic indeed. THANKS, Viorel

mlcv-ai commented 10 years ago

@kloudki: I couldn't seem to find the method AddImagesAndLabels in the image_data_layer.cpp. Could you please let me know where it is implemented? I'm currently on the dev branch. Thanks.

anguyen8 commented 10 years ago

@hhuytho : the method AddImagesAndLabels is available in this branch https://github.com/BVLC/caffe/pull/251

mlcv-ai commented 10 years ago

@anguyen8: thanks. I just got it from the fork!

mlcv-ai commented 10 years ago

In #251, it seems like that it's not necessary to include "source" in the prototxt anymore. However, when I removed it, I got a segmentation fault as a result of not being able to inititalize the ImageDataLayer due to no bottom blobs. So do we still need a list of images in the "source" field? Thanks.

anguyen8 commented 10 years ago

@hhuytho : yes you still need the "source" field. Please see the comment above https://github.com/BVLC/caffe/issues/499#issuecomment-46975281

mlcv-ai commented 10 years ago

Thanks @anguyen8. I have made some changes to this implementation to handle the case where there is no source.

jasonustc commented 9 years ago

I follow the code offered by @kloudkl :

  const shared_ptr<ImageDataLayer<float> > image_data_layer =
      boost::static_pointer_cast<ImageDataLayer<float> >(
          caffe_test_net.layer_by_name("data"));
  image_data_layer->AddImagesAndLabels(images, labels);

But the problem is image_data_layer does't have the member function AddImagesAndLabels(), was it deleted by the latest version? how to solve this problem?

bhack commented 9 years ago

@jasonustc You need to try to use this https://github.com/BVLC/caffe/pull/1068

jasonustc commented 9 years ago

@bhack I've read #1068 , do you mean that the support for opencv mat as input is not supported currently?

bhack commented 9 years ago

Yes you need to try to use with this PR. The old one was closed without merge.

jasonustc commented 9 years ago

@bhack got it, I will add these changes to my code manually, thanks a lot!

billychasen commented 9 years ago

@bhack on your opencv_io branch, I tried compiling and got

tools/test.cpp:42:21: error: ‘class caffe::ImageDataLayer<float>’ has no member named ‘AddImagesAndLabels’
   image_data_layer->AddImagesAndLabels(images, labels);

I tried using MemoryDataLayer and it compiled, but got this at runtime "pure virtual method called"

joeupwu commented 9 years ago

Try to use MemoryData layer as input to prevent fake image list.

// fragment of input net:
layer {
  name: "input"
  type: "MemoryData"
  top: "data"
  top: "label"

  transform_param {
    mirror: false
    crop_size: 227
    mean_file: "d:/project/caffe/data/ilsvrc12/imagenet_mean.binaryproto"  
  }

  memory_data_param {
    batch_size: 1
    channels: 3
    height: 227
    width: 227
  }  
}

// fragment of C++ code:
float loss;
Net<float> caffe_net(NETMODELFILE, caffe::TEST);
caffe_net.CopyTrainedLayersFrom(TRAINEDFILE);

// load image files, resize and added to vector
cv::Mat image = cv::imread(INIMAGEFILE);
cv::Mat rszimage;

// The mean file image size is 256x256, need to resize the input image to 256x256
cv::resize(image, rszimage, cv::Size(256, 256));

std::vector<cv::Mat> images(1, rszimage);
std::vector<int> labels(1, 0);

shared_ptr<MemoryDataLayer<float>> md_layer =
    boost::dynamic_pointer_cast <MemoryDataLayer<float>>(caffe_net.layers()[0]);
if (!md_layer) {
    std::cout << "The first layer is not a MemoryDataLayer!\n";
    return -1;
}

md_layer->AddMatVector(images, labels);

caffe_net.ForwardPrefilled(&loss);
std::cout << "loss: " << loss << "\n";
    // read the 'prob' layer and get the result
shared_ptr<Blob<float>> prob = caffe_net.blob_by_name("prob");
float maxval= 0;
int   maxinx= 0;
for (int i = 0; i < prob->count(); i++)
{
    float val= prob->cpu_data()[i];
    if (val> maxval)
    {
        maxval= val;
        maxinx= i;
    }
    std::cout << "[" << i << "]" << val<< "\n";
}
std::cout << "Max value = " << maxval<< ", Max index = " << maxinx<< "\n";
anukuppan commented 8 years ago

How to test the trained MNIST data sets .Can any one suggest any tutorials for training the data sets. Thanks in advance.

Regards, Anu kuppan

antran89 commented 8 years ago

What do you mean training on test data?

On Monday, October 26, 2015, anukuppan notifications@github.com wrote:

How to train the MINST test data .Can any one suggest any tutorials for training the data sets ? Thanks in advance.

Regards, Anu kuppan

— Reply to this email directly or view it on GitHub https://github.com/BVLC/caffe/issues/499#issuecomment-151114018.


Full name: Tran Lam An NUS graduate student Email: tranlaman at gmail dot com

Homepage: http://antran89.github.io/

anukuppan commented 8 years ago

How to test caffe classifier trained by MNIST data sets?

cmanders commented 8 years ago

Hello, if my input is: name: "ZF" input: "data" input: "im_info" state { phase: TEST } input_shape { dim: 1 dim: 3 dim: 224 dim: 224 } input_shape { dim: 1 dim: 3 }

how do I push-back the needed blobs before calling forward?

Thanks! Corey

Arieal-zz commented 8 years ago

How to implement caffe into my C++ application an example?How to run classfication.cpp ?

antran89 commented 8 years ago

@Arieal You can refer to the example documents http://caffe.berkeleyvision.org/gathered/examples/cpp_classification.html.

Arieal-zz commented 8 years ago

@antran89 Thanks very much! what I meant is how to link caffe as library and call functions in my own project not modify the example already configured and build successfully in caffe.

antran89 commented 8 years ago

@Arieal I think it is not difficult, link again libcaffe.so and include some .h files should be enough.