CaffeFeatExtractor<Dtype>::CaffeFeatExtractor(string _caffemodel_file,
        string _prototxt_file, int _resizeWidth, int _resizeHeight,
        string _blob_names,
        string _compute_mode,
        int _device_id,
        bool _timing) {

    // Setup the GPU or the CPU mode for Caffe
    if (strcmp(_compute_mode.c_str(), "GPU") == 0 || strcmp(_compute_mode.c_str(), "gpu") == 0) {

        std::cout << "CaffeFeatExtractor::CaffeFeatExtractor(): using GPU" << std::endl;

        gpu_mode = true;
        device_id = _device_id;

        Caffe::CheckDevice(device_id);

        std::cout << "CaffeFeatExtractor::CaffeFeatExtractor(): using device_id = " << device_id << std::endl;

        Caffe::set_mode(Caffe::GPU);
        Caffe::SetDevice(device_id);

        // Optional: to check that the GPU is working properly...
        Caffe::DeviceQuery();

    } else
    {
        std::cout << "CaffeFeatExtractor::CaffeFeatExtractor(): using CPU" << std::endl;

        gpu_mode = false;
        device_id = -1;

        Caffe::set_mode(Caffe::CPU);
    }

    // Assign specified .caffemodel and .prototxt files
    caffemodel_file = _caffemodel_file;
    prototxt_file = _prototxt_file;

    // Network creation using the specified .prototxt
    feature_extraction_net = boost::make_shared<Net<Dtype> > (prototxt_file, caffe::TEST);

    // Network initialization using the specified .caffemodel
    feature_extraction_net->CopyTrainedLayersFrom(caffemodel_file);

    // Mean image initialization

    mean_width = 0;
    mean_height = 0;
    mean_channels = 0;

    caffe::shared_ptr<MemoryDataLayer<Dtype> > memory_data_layer = boost::dynamic_pointer_cast<caffe::MemoryDataLayer<Dtype> >(feature_extraction_net->layers()[0]);

    TransformationParameter tp = memory_data_layer->layer_param().transform_param();

    if (tp.has_mean_file())
    {
        const string& mean_file = tp.mean_file();
        std::cout << "CaffeFeatExtractor::CaffeFeatExtractor(): loading mean file from " << mean_file << std::endl;

        BlobProto blob_proto;
        ReadProtoFromBinaryFileOrDie(mean_file.c_str(), &blob_proto);

        Blob<Dtype> data_mean;
        data_mean.FromProto(blob_proto);

        mean_channels = data_mean.channels();
        mean_width = data_mean.width();
        mean_height = data_mean.height();

    } else if (tp.mean_value_size()>0)
    {

        const int b = tp.mean_value(0);
        const int g = tp.mean_value(1);
        const int r = tp.mean_value(2);

        mean_channels = tp.mean_value_size();
        mean_width = _resizeWidth;
        mean_height = _resizeHeight;

        std::cout << "CaffeFeatExtractor::CaffeFeatExtractor(): B " << b << "   G " << g << "   R " << r << std::endl;
        std::cout << "CaffeFeatExtractor::CaffeFeatExtractor(): resizing anysotropically to " << " W: " << mean_width << " H: " << mean_height << std::endl;
    }
    else
    {
        std::cout << "CaffeFeatExtractor::CaffeFeatExtractor(): Error: neither mean file nor mean value in prototxt!" << std::endl;
    }

    // Check that requested blobs exist
    boost::split(blob_names, _blob_names, boost::is_any_of(","));
    for (size_t i = 0; i < blob_names.size(); i++) {
        if (!feature_extraction_net->has_blob(blob_names[i]))
        {
            std::cout << "CaffeFeatExtractor::CaffeFeatExtractor(): unknown feature blob name " << blob_names[i] << " in the network " << prototxt_file << std::endl;
        }
    }

    // Initialize timing flag
    timing = _timing;

}