remove leveldb dependency, using Input/OutputArray for feature extraction, add the newest model, format fix for OpenCV
parent
4fe5498a45
commit
b831fc3bad
14 changed files with 509 additions and 1118 deletions
@ -1,3 +1,3 @@ |
|||||||
set(the_description "CNN for 3D object recognition and pose estimation including a completed Sphere View on 3D objects") |
set(the_description "CNN for 3D object recognition and pose estimation including a completed Sphere View on 3D objects") |
||||||
ocv_define_module(cnn_3dobj opencv_core opencv_imgproc opencv_viz opencv_highgui caffe protobuf leveldb glog OPTIONAL WRAP python) |
ocv_define_module(cnn_3dobj opencv_core opencv_imgproc opencv_viz opencv_highgui caffe protobuf glog OPTIONAL WRAP python) |
||||||
target_link_libraries(opencv_cnn_3dobj caffe protobuf leveldb glog) |
target_link_libraries(opencv_cnn_3dobj caffe protobuf glog) |
||||||
|
@ -1,112 +0,0 @@ |
|||||||
/*
|
|
||||||
* Software License Agreement (BSD License) |
|
||||||
* |
|
||||||
* Copyright (c) 2009, Willow Garage, Inc. |
|
||||||
* All rights reserved. |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions |
|
||||||
* are met: |
|
||||||
* |
|
||||||
* * Redistributions of source code must retain the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer. |
|
||||||
* * Redistributions in binary form must reproduce the above |
|
||||||
* copyright notice, this list of conditions and the following |
|
||||||
* disclaimer in the documentation and/or other materials provided |
|
||||||
* with the distribution. |
|
||||||
* * Neither the name of Willow Garage, Inc. nor the names of its |
|
||||||
* contributors may be used to endorse or promote products derived |
|
||||||
* from this software without specific prior written permission. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|
||||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE. |
|
||||||
* |
|
||||||
*/ |
|
||||||
#include <opencv2/cnn_3dobj.hpp> |
|
||||||
#include <iomanip> |
|
||||||
using namespace cv; |
|
||||||
using namespace std; |
|
||||||
using namespace cv::cnn_3dobj; |
|
||||||
int main(int argc, char** argv) |
|
||||||
{ |
|
||||||
const String keys = "{help | | this demo will convert a set of images in a particular path into leveldb database for feature extraction using Caffe.}" |
|
||||||
"{src_dir | ../data/images_all/ | Source direction of the images ready for being converted to leveldb dataset.}" |
|
||||||
"{src_dst | ../data/dbfile | Aim direction of the converted to leveldb dataset. }" |
|
||||||
"{attach_dir | ../data/dbfile | Path for saving additional files which describe the transmission results. }" |
|
||||||
"{channel | 1 | Channel of the images. }" |
|
||||||
"{width | 64 | Width of images}" |
|
||||||
"{height | 64 | Height of images}" |
|
||||||
"{caffemodel | ../data/3d_triplet_iter_10000.caffemodel | caffe model for feature exrtaction.}" |
|
||||||
"{network_forDB | ../data/3d_triplet_galleryIMG.prototxt | Network definition file used for extracting feature from levelDB data, causion: the path of levelDB training samples must be wrotten in in .prototxt files in Phase TEST}" |
|
||||||
"{save_feature_dataset_names | ../data/feature/feature_iter_10000.bin | Output of the extracted feature in form of binary files together with the vector<cv::Mat> features as the feature.}" |
|
||||||
"{extract_feature_blob_names | feat | Layer used for feature extraction in CNN.}" |
|
||||||
"{num_mini_batches | 4 | Batches suit for the batches defined in the .proto for the aim of extracting feature from all images.}" |
|
||||||
"{device | CPU | Device: CPU or GPU.}" |
|
||||||
"{dev_id | 0 | ID of GPU.}" |
|
||||||
"{network_forIMG | ../data/3d_triplet_testIMG.prototxt | Network definition file used for extracting feature from a single image and making a classification}" |
|
||||||
"{mean_file | ../data/images_mean/triplet_mean.binaryproto | The mean file generated by Caffe from all gallery images, this could be used for mean value substraction from all images.}" |
|
||||||
"{label_file | ../data/dbfileimage_filename | A namelist including all gallery images.}" |
|
||||||
"{target_img | ../data/images_all/2_13.png | Path of image waiting to be classified.}" |
|
||||||
"{num_candidate | 6 | Number of candidates in gallery as the prediction result.}"; |
|
||||||
cv::CommandLineParser parser(argc, argv, keys); |
|
||||||
parser.about("Demo for Sphere View data generation"); |
|
||||||
if (parser.has("help")) |
|
||||||
{ |
|
||||||
parser.printMessage(); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
string src_dir = parser.get<string>("src_dir"); |
|
||||||
string src_dst = parser.get<string>("src_dst"); |
|
||||||
string attach_dir = parser.get<string>("attach_dir"); |
|
||||||
int channel = parser.get<int>("channel"); |
|
||||||
int width = parser.get<int>("width"); |
|
||||||
int height = parser.get<int>("height"); |
|
||||||
string caffemodel = parser.get<string>("caffemodel"); |
|
||||||
string network_forDB = parser.get<string>("network_forDB"); |
|
||||||
string save_feature_dataset_names = parser.get<string>("save_feature_dataset_names"); |
|
||||||
string extract_feature_blob_names = parser.get<string>("extract_feature_blob_names"); |
|
||||||
int num_mini_batches = parser.get<int>("num_mini_batches"); |
|
||||||
string device = parser.get<string>("device"); |
|
||||||
int dev_id = parser.get<int>("dev_id"); |
|
||||||
string network_forIMG = parser.get<string>("network_forIMG"); |
|
||||||
string mean_file = parser.get<string>("mean_file"); |
|
||||||
string label_file = parser.get<string>("label_file"); |
|
||||||
string target_img = parser.get<string>("target_img"); |
|
||||||
int num_candidate = parser.get<int>("num_candidate"); |
|
||||||
cv::cnn_3dobj::DataTrans transTemp; |
|
||||||
transTemp.convert(src_dir,src_dst,attach_dir,channel,width,height); |
|
||||||
std::vector<cv::Mat> feature_reference = transTemp.feature_extraction_pipeline(caffemodel, network_forDB, save_feature_dataset_names, extract_feature_blob_names, num_mini_batches, device, dev_id); |
|
||||||
////start another demo
|
|
||||||
cv::cnn_3dobj::Classification classifier(network_forIMG, caffemodel, mean_file, label_file); |
|
||||||
|
|
||||||
std::cout << std::endl << "---------- Prediction for " |
|
||||||
<< target_img << " ----------" << std::endl; |
|
||||||
|
|
||||||
cv::Mat img = cv::imread(target_img, -1); |
|
||||||
// CHECK(!img.empty()) << "Unable to decode image " << target_img;
|
|
||||||
std::cout << std::endl << "---------- Featrue of gallery images ----------" << std::endl; |
|
||||||
std::vector<std::pair<string, float> > prediction; |
|
||||||
for (unsigned int i = 0; i < feature_reference.size(); i++) |
|
||||||
std::cout << feature_reference[i] << endl; |
|
||||||
cv::Mat feature_test = classifier.feature_extract(img, false); |
|
||||||
std::cout << std::endl << "---------- Featrue of target image: " << target_img << "----------" << endl << feature_test.t() << std::endl; |
|
||||||
prediction = classifier.Classify(feature_reference, img, num_candidate, false); |
|
||||||
// Print the top N prediction.
|
|
||||||
std::cout << std::endl << "---------- Prediction result(distance - file name in gallery) ----------" << std::endl; |
|
||||||
for (size_t i = 0; i < prediction.size(); ++i) { |
|
||||||
std::pair<string, float> p = prediction[i]; |
|
||||||
std::cout << std::fixed << std::setprecision(2) << p.second << " - \"" |
|
||||||
<< p.first << "\"" << std::endl; |
|
||||||
} |
|
||||||
return 0; |
|
||||||
} |
|
@ -1,94 +0,0 @@ |
|||||||
name: "3d_triplet" |
|
||||||
layer { |
|
||||||
name: "data" |
|
||||||
type: "Data" |
|
||||||
top: "data" |
|
||||||
top: "label" |
|
||||||
include { |
|
||||||
phase: TEST |
|
||||||
} |
|
||||||
data_param { |
|
||||||
source: "/home/wangyida/Desktop/opencv_contrib/modules/nouse_test/samples/data/dbfile" |
|
||||||
batch_size: 69 |
|
||||||
} |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "conv1" |
|
||||||
type: "Convolution" |
|
||||||
bottom: "data" |
|
||||||
top: "conv1" |
|
||||||
convolution_param { |
|
||||||
num_output: 16 |
|
||||||
kernel_size: 8 |
|
||||||
stride: 1 |
|
||||||
} |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "pool1" |
|
||||||
type: "Pooling" |
|
||||||
bottom: "conv1" |
|
||||||
top: "pool1" |
|
||||||
pooling_param { |
|
||||||
pool: MAX |
|
||||||
kernel_size: 2 |
|
||||||
stride: 2 |
|
||||||
} |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "relu1" |
|
||||||
type: "ReLU" |
|
||||||
bottom: "pool1" |
|
||||||
top: "pool1" |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "conv2" |
|
||||||
type: "Convolution" |
|
||||||
bottom: "pool1" |
|
||||||
top: "conv2" |
|
||||||
convolution_param { |
|
||||||
num_output: 7 |
|
||||||
kernel_size: 5 |
|
||||||
stride: 1 |
|
||||||
} |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "pool2" |
|
||||||
type: "Pooling" |
|
||||||
bottom: "conv2" |
|
||||||
top: "pool2" |
|
||||||
pooling_param { |
|
||||||
pool: MAX |
|
||||||
kernel_size: 2 |
|
||||||
stride: 2 |
|
||||||
} |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "relu2" |
|
||||||
type: "ReLU" |
|
||||||
bottom: "pool2" |
|
||||||
top: "pool2" |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "ip1" |
|
||||||
type: "InnerProduct" |
|
||||||
bottom: "pool2" |
|
||||||
top: "ip1" |
|
||||||
inner_product_param { |
|
||||||
num_output: 256 |
|
||||||
} |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "relu3" |
|
||||||
type: "ReLU" |
|
||||||
bottom: "ip1" |
|
||||||
top: "ip1" |
|
||||||
} |
|
||||||
layer { |
|
||||||
name: "feat" |
|
||||||
type: "InnerProduct" |
|
||||||
bottom: "ip1" |
|
||||||
top: "feat" |
|
||||||
inner_product_param { |
|
||||||
num_output: 4 |
|
||||||
} |
|
||||||
} |
|
Binary file not shown.
Binary file not shown.
@ -1,64 +0,0 @@ |
|||||||
/*
|
|
||||||
* Software License Agreement (BSD License) |
|
||||||
* |
|
||||||
* Copyright (c) 2009, Willow Garage, Inc. |
|
||||||
* All rights reserved. |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions |
|
||||||
* are met: |
|
||||||
* |
|
||||||
* * Redistributions of source code must retain the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer. |
|
||||||
* * Redistributions in binary form must reproduce the above |
|
||||||
* copyright notice, this list of conditions and the following |
|
||||||
* disclaimer in the documentation and/or other materials provided |
|
||||||
* with the distribution. |
|
||||||
* * Neither the name of Willow Garage, Inc. nor the names of its |
|
||||||
* contributors may be used to endorse or promote products derived |
|
||||||
* from this software without specific prior written permission. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|
||||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE. |
|
||||||
* |
|
||||||
*/ |
|
||||||
#include <opencv2/cnn_3dobj.hpp> |
|
||||||
using namespace cv; |
|
||||||
using namespace std; |
|
||||||
using namespace cv::cnn_3dobj; |
|
||||||
int main(int argc, char* argv[]) |
|
||||||
{ |
|
||||||
const String keys = "{help | | this demo will convert a set of images in a particular path into leveldb database for feature extraction using Caffe.}" |
|
||||||
"{src_dir | ../data/images_all | Source direction of the images ready for being converted to leveldb dataset.}" |
|
||||||
"{src_dst | ../data/dbfile | Aim direction of the converted to leveldb dataset. }" |
|
||||||
"{attach_dir | ../data/dbfile | Path for saving additional files which describe the transmission results. }" |
|
||||||
"{channel | 1 | Channel of the images. }" |
|
||||||
"{width | 64 | Width of images}" |
|
||||||
"{height | 64 | Height of images}"; |
|
||||||
cv::CommandLineParser parser(argc, argv, keys); |
|
||||||
parser.about("Demo for Sphere View data generation"); |
|
||||||
if (parser.has("help")) |
|
||||||
{ |
|
||||||
parser.printMessage(); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
string src_dir = parser.get<string>("src_dir"); |
|
||||||
string src_dst = parser.get<string>("src_dst"); |
|
||||||
string attach_dir = parser.get<string>("attach_dir"); |
|
||||||
int channel = parser.get<int>("channel"); |
|
||||||
int width = parser.get<int>("width"); |
|
||||||
int height = parser.get<int>("height"); |
|
||||||
cv::cnn_3dobj::DataTrans Trans; |
|
||||||
Trans.convert(src_dir,src_dst,attach_dir,channel,width,height); |
|
||||||
std::cout << std::endl << "All featrues of images in: " << std::endl << src_dir << std::endl << "have been converted to levelDB data in: " << std::endl << src_dst << std::endl << "for extracting feature of gallery images in classification efficiently, this convertion is not needed in feature extraction of test image" << std::endl; |
|
||||||
} |
|
@ -1,99 +0,0 @@ |
|||||||
/*
|
|
||||||
* Software License Agreement (BSD License) |
|
||||||
* |
|
||||||
* Copyright (c) 2009, Willow Garage, Inc. |
|
||||||
* All rights reserved. |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions |
|
||||||
* are met: |
|
||||||
* |
|
||||||
* * Redistributions of source code must retain the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer. |
|
||||||
* * Redistributions in binary form must reproduce the above |
|
||||||
* copyright notice, this list of conditions and the following |
|
||||||
* disclaimer in the documentation and/or other materials provided |
|
||||||
* with the distribution. |
|
||||||
* * Neither the name of Willow Garage, Inc. nor the names of its |
|
||||||
* contributors may be used to endorse or promote products derived |
|
||||||
* from this software without specific prior written permission. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|
||||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
||||||
* POSSIBILITY OF SUCH DAMAGE. |
|
||||||
* |
|
||||||
*/ |
|
||||||
#include <opencv2/cnn_3dobj.hpp> |
|
||||||
#include <stdio.h> // for snprintf |
|
||||||
#include <tr1/memory> |
|
||||||
#include <string> |
|
||||||
#include <vector> |
|
||||||
#include "google/protobuf/text_format.h" |
|
||||||
#include <opencv2/opencv.hpp> |
|
||||||
#include <opencv2/core/core.hpp> |
|
||||||
#define CPU_ONLY |
|
||||||
#include "caffe/blob.hpp" |
|
||||||
#include "caffe/common.hpp" |
|
||||||
#include "caffe/net.hpp" |
|
||||||
#include "caffe/proto/caffe.pb.h" |
|
||||||
#include "caffe/util/io.hpp" |
|
||||||
#include "caffe/vision_layers.hpp" |
|
||||||
using caffe::Blob; |
|
||||||
using caffe::Caffe; |
|
||||||
using caffe::Datum; |
|
||||||
using caffe::Net; |
|
||||||
//using boost::shared_ptr;
|
|
||||||
using std::string; |
|
||||||
//namespace db = caffe::db;
|
|
||||||
using namespace cv; |
|
||||||
using namespace std; |
|
||||||
using namespace cv::cnn_3dobj; |
|
||||||
int main(int argc, char* argv[]) |
|
||||||
{ |
|
||||||
const String keys = "{help | | this demo will convert a set of images in a particular path into leveldb database for feature extraction using Caffe.}" |
|
||||||
"{src_dir | ../data/images_all/ | Source direction of the images ready for being converted to leveldb dataset.}" |
|
||||||
"{src_dst | ../data/dbfile | Aim direction of the converted to leveldb dataset. }" |
|
||||||
"{attach_dir | ../data/dbfile | Path for saving additional files which describe the transmission results. }" |
|
||||||
"{channel | 1 | Channel of the images. }" |
|
||||||
"{width | 64 | Width of images}" |
|
||||||
"{height | 64 | Height of images}" |
|
||||||
"{pretrained_binary_proto | ../data/3d_triplet_iter_10000.caffemodel | caffe model for feature exrtaction.}" |
|
||||||
"{feature_extraction_proto | ../data/3d_triplet_train_test.prototxt | network definition in .prototxt the path of the training samples must be wrotten in in .prototxt files in Phase TEST}" |
|
||||||
"{save_feature_dataset_names | ../data/feature/feature_iter_10000.bin | the output of the extracted feature in form of binary files together with the vector<cv::Mat> features as the feature.}" |
|
||||||
"{extract_feature_blob_names | feat | the layer used for feature extraction in CNN.}" |
|
||||||
"{num_mini_batches | 6 | batches suit for the batches defined in the .proto for the aim of extracting feature from all images.}" |
|
||||||
"{device | CPU | device}" |
|
||||||
"{dev_id | 0 | dev_id}"; |
|
||||||
cv::CommandLineParser parser(argc, argv, keys); |
|
||||||
parser.about("Demo for Sphere View data generation"); |
|
||||||
if (parser.has("help")) |
|
||||||
{ |
|
||||||
parser.printMessage(); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
string src_dir = parser.get<string>("src_dir"); |
|
||||||
string src_dst = parser.get<string>("src_dst"); |
|
||||||
string attach_dir = parser.get<string>("attach_dir"); |
|
||||||
int channel = parser.get<int>("channel"); |
|
||||||
int width = parser.get<int>("width"); |
|
||||||
int height = parser.get<int>("height"); |
|
||||||
string pretrained_binary_proto = parser.get<string>("pretrained_binary_proto"); |
|
||||||
string feature_extraction_proto = parser.get<string>("feature_extraction_proto"); |
|
||||||
string save_feature_dataset_names = parser.get<string>("save_feature_dataset_names"); |
|
||||||
string extract_feature_blob_names = parser.get<string>("extract_feature_blob_names"); |
|
||||||
int num_mini_batches = parser.get<int>("num_mini_batches"); |
|
||||||
string device = parser.get<string>("device"); |
|
||||||
int dev_id = parser.get<int>("dev_id"); |
|
||||||
cv::cnn_3dobj::DataTrans transTemp; |
|
||||||
transTemp.convert(src_dir,src_dst,attach_dir,channel,width,height); |
|
||||||
std::vector<cv::Mat> extractedFeature = transTemp.feature_extraction_pipeline(pretrained_binary_proto, feature_extraction_proto, save_feature_dataset_names, extract_feature_blob_names, num_mini_batches, device, dev_id); |
|
||||||
} |
|
@ -1,237 +0,0 @@ |
|||||||
#include "precomp.hpp" |
|
||||||
using std::string; |
|
||||||
using namespace std; |
|
||||||
|
|
||||||
namespace cv |
|
||||||
{ |
|
||||||
namespace cnn_3dobj |
|
||||||
{ |
|
||||||
DataTrans::DataTrans() |
|
||||||
{ |
|
||||||
}; |
|
||||||
void DataTrans::list_dir(const char *path,vector<string>& files,bool r) |
|
||||||
{ |
|
||||||
DIR *pDir; |
|
||||||
struct dirent *ent; |
|
||||||
char childpath[512]; |
|
||||||
pDir = opendir(path); |
|
||||||
memset(childpath, 0, sizeof(childpath)); |
|
||||||
while ((ent = readdir(pDir)) != NULL) |
|
||||||
{ |
|
||||||
if (ent->d_type & DT_DIR) |
|
||||||
{ |
|
||||||
|
|
||||||
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) |
|
||||||
{ |
|
||||||
continue; |
|
||||||
} |
|
||||||
if(r) |
|
||||||
{ |
|
||||||
sprintf(childpath, "%s/%s", path, ent->d_name); |
|
||||||
DataTrans::list_dir(childpath,files,false); |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
files.push_back(ent->d_name); |
|
||||||
} |
|
||||||
} |
|
||||||
sort(files.begin(),files.end()); |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
string DataTrans::get_classname(string path) |
|
||||||
{ |
|
||||||
int index = path.find_last_of('_'); |
|
||||||
return path.substr(0, index); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int DataTrans::get_labelid(string fileName) |
|
||||||
{ |
|
||||||
string class_name_tmp = get_classname(fileName); |
|
||||||
all_class_name.insert(class_name_tmp); |
|
||||||
map<string,int>::iterator name_iter_tmp = class2id.find(class_name_tmp); |
|
||||||
if (name_iter_tmp == class2id.end()) |
|
||||||
{ |
|
||||||
int id = class2id.size(); |
|
||||||
class2id.insert(name_iter_tmp, std::make_pair(class_name_tmp, id)); |
|
||||||
return id; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return name_iter_tmp->second; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void DataTrans::loadimg(string path,char* buffer,const bool is_color) |
|
||||||
{ |
|
||||||
cv::Mat img = cv::imread(path, is_color); |
|
||||||
string val; |
|
||||||
int rows = img.rows; |
|
||||||
int cols = img.cols; |
|
||||||
int pos=0; |
|
||||||
int channel; |
|
||||||
if (is_color == 0) |
|
||||||
{ |
|
||||||
channel = 1; |
|
||||||
}else{ |
|
||||||
channel = 3; |
|
||||||
} |
|
||||||
for (int c = 0; c < channel; c++) |
|
||||||
{ |
|
||||||
for (int row = 0; row < rows; row++) |
|
||||||
{ |
|
||||||
for (int col = 0; col < cols; col++) |
|
||||||
{ |
|
||||||
buffer[pos++]=img.at<cv::Vec3b>(row,col)[c]; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
void DataTrans::convert(string imgdir,string outputdb,string attachdir,int channel,int width,int height) |
|
||||||
{ |
|
||||||
leveldb::DB* db; |
|
||||||
leveldb::Options options; |
|
||||||
options.create_if_missing = true; |
|
||||||
// options.error_if_exists = true;
|
|
||||||
caffe::Datum datum; |
|
||||||
datum.set_channels(channel); |
|
||||||
datum.set_height(height); |
|
||||||
datum.set_width(width); |
|
||||||
int image_size = channel*width*height; |
|
||||||
char buffer[image_size]; |
|
||||||
|
|
||||||
string value; |
|
||||||
CHECK(leveldb::DB::Open(options, outputdb, &db).ok()); |
|
||||||
vector<string> filenames; |
|
||||||
list_dir(imgdir.c_str(),filenames, false); |
|
||||||
string img_log = attachdir+"image_filename"; |
|
||||||
ofstream writefile(img_log.c_str()); |
|
||||||
for(int i=0;i<(int)filenames.size();i++) |
|
||||||
{ |
|
||||||
string path= imgdir; |
|
||||||
path.append(filenames[i]); |
|
||||||
|
|
||||||
loadimg(path,buffer,false); |
|
||||||
|
|
||||||
int labelid = get_labelid(filenames[i]); |
|
||||||
|
|
||||||
datum.set_label(labelid); |
|
||||||
datum.set_data(buffer,image_size); |
|
||||||
datum.SerializeToString(&value); |
|
||||||
snprintf(buffer, image_size, "%05d", i); |
|
||||||
printf("\nclassid:%d classname:%s abspath:%s",labelid,get_classname(filenames[i]).c_str(),path.c_str()); |
|
||||||
db->Put(leveldb::WriteOptions(),string(buffer),value); |
|
||||||
//printf("%d %s\n",i,fileNames[i].c_str());
|
|
||||||
|
|
||||||
assert(writefile.is_open()); |
|
||||||
writefile<<i<<" "<<filenames[i]<<"\n"; |
|
||||||
|
|
||||||
} |
|
||||||
delete db; |
|
||||||
writefile.close(); |
|
||||||
|
|
||||||
img_log = attachdir+"image_classname"; |
|
||||||
writefile.open(img_log.c_str()); |
|
||||||
set<string>::iterator iter = all_class_name.begin(); |
|
||||||
while(iter != all_class_name.end()) |
|
||||||
{ |
|
||||||
assert(writefile.is_open()); |
|
||||||
writefile<<(*iter)<<"\n"; |
|
||||||
//printf("%s\n",(*iter).c_str());
|
|
||||||
iter++; |
|
||||||
} |
|
||||||
writefile.close(); |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
std::vector<cv::Mat> DataTrans::feature_extraction_pipeline(std::string pretrained_binary_proto, std::string feature_extraction_proto, std::string save_feature_dataset_names, std::string extract_feature_blob_names, int num_mini_batches, std::string device, int dev_id) { |
|
||||||
if (strcmp(device.c_str(), "GPU") == 0) { |
|
||||||
LOG(ERROR)<< "Using GPU"; |
|
||||||
int device_id = 0; |
|
||||||
if (strcmp(device.c_str(), "GPU") == 0) { |
|
||||||
device_id = dev_id; |
|
||||||
CHECK_GE(device_id, 0); |
|
||||||
} |
|
||||||
LOG(ERROR) << "Using Device_id=" << device_id; |
|
||||||
Caffe::SetDevice(device_id); |
|
||||||
Caffe::set_mode(Caffe::GPU); |
|
||||||
} else { |
|
||||||
LOG(ERROR) << "Using CPU"; |
|
||||||
Caffe::set_mode(Caffe::CPU); |
|
||||||
} |
|
||||||
boost::shared_ptr<Net<float> > feature_extraction_net( |
|
||||||
new Net<float>(feature_extraction_proto, caffe::TEST)); |
|
||||||
feature_extraction_net->CopyTrainedLayersFrom(pretrained_binary_proto); |
|
||||||
std::vector<std::string> blob_names; |
|
||||||
blob_names.push_back(extract_feature_blob_names); |
|
||||||
std::vector<std::string> dataset_names; |
|
||||||
dataset_names.push_back(save_feature_dataset_names); |
|
||||||
CHECK_EQ(blob_names.size(), dataset_names.size()) << |
|
||||||
" the number of blob names and dataset names must be equal"; |
|
||||||
size_t num_features = blob_names.size(); |
|
||||||
|
|
||||||
for (size_t i = 0; i < num_features; i++) { |
|
||||||
CHECK(feature_extraction_net->has_blob(blob_names[i])) |
|
||||||
<< "Unknown feature blob name " << blob_names[i] |
|
||||||
<< " in the network " << feature_extraction_proto; |
|
||||||
} |
|
||||||
std::vector<FILE*> files; |
|
||||||
for (size_t i = 0; i < num_features; ++i) |
|
||||||
{ |
|
||||||
LOG(INFO) << "Opening file " << dataset_names[i]; |
|
||||||
FILE * temp = fopen(dataset_names[i].c_str(), "wb"); |
|
||||||
files.push_back(temp); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
LOG(ERROR)<< "Extacting Features"; |
|
||||||
|
|
||||||
Datum datum; |
|
||||||
std::vector<cv::Mat> featureVec; |
|
||||||
std::vector<Blob<float>*> input_vec; |
|
||||||
std::vector<int> image_indices(num_features, 0); |
|
||||||
for (int batch_index = 0; batch_index < num_mini_batches; ++batch_index) { |
|
||||||
feature_extraction_net->Forward(input_vec); |
|
||||||
for (size_t i = 0; i < num_features; ++i) { |
|
||||||
const boost::shared_ptr<Blob<float> > feature_blob = feature_extraction_net |
|
||||||
->blob_by_name(blob_names[i]); |
|
||||||
int batch_size = feature_blob->num(); |
|
||||||
int dim_features = feature_blob->count() / batch_size; |
|
||||||
if (batch_index == 0) |
|
||||||
{ |
|
||||||
int fea_num = batch_size*num_mini_batches; |
|
||||||
fwrite(&dim_features, sizeof(int), 1, files[i]); |
|
||||||
fwrite(&fea_num, sizeof(int), 1, files[i]); |
|
||||||
} |
|
||||||
const float* feature_blob_data; |
|
||||||
for (int n = 0; n < batch_size; ++n) { |
|
||||||
|
|
||||||
feature_blob_data = feature_blob->cpu_data() + |
|
||||||
feature_blob->offset(n); |
|
||||||
fwrite(feature_blob_data, sizeof(float), dim_features, files[i]); |
|
||||||
cv::Mat tempfeat = cv::Mat(1, dim_features, CV_32FC1); |
|
||||||
for (int dim = 0; dim < dim_features; dim++) { |
|
||||||
tempfeat.at<float>(0,dim) = *(feature_blob_data++); |
|
||||||
} |
|
||||||
featureVec.push_back(tempfeat); |
|
||||||
++image_indices[i]; |
|
||||||
if (image_indices[i] % 1000 == 0) { |
|
||||||
LOG(ERROR)<< "Extracted features of " << image_indices[i] << |
|
||||||
" query images for feature blob " << blob_names[i]; |
|
||||||
} |
|
||||||
} // for (int n = 0; n < batch_size; ++n)
|
|
||||||
} // for (int i = 0; i < num_features; ++i)
|
|
||||||
} // for (int batch_index = 0; batch_index < num_mini_batches; ++batch_index)
|
|
||||||
// write the last batch
|
|
||||||
for (size_t i = 0; i < num_features; ++i) { |
|
||||||
fclose(files[i]); |
|
||||||
} |
|
||||||
|
|
||||||
LOG(ERROR)<< "Successfully extracted the features!"; |
|
||||||
return featureVec; |
|
||||||
}; |
|
||||||
}} |
|
Loading…
Reference in new issue