$search
00001 #include <ros/ros.h> 00002 #include <dirent.h> 00003 #include <cmath> 00004 #include <sys/stat.h> 00005 #include <ANN/ANN.h> 00006 #include <math.h> 00007 #include <fstream> 00008 #include <time.h> 00009 #include "rospack/rospack.h" 00010 #include "odu_finder.h" 00011 00013 DocumentInfo::DocumentInfo() : 00014 delete_document(false) { 00015 } 00016 00018 DocumentInfo::DocumentInfo(vt::Document* document, std::string& name) : 00019 delete_document(false), document(document), name(name) { 00020 } 00021 00023 DocumentInfo::~DocumentInfo() { 00024 if (delete_document) 00025 delete[] document; 00026 } 00027 00029 void DocumentInfo::write(std::ostream& out) { 00030 size_t length = name.length(); 00031 out.write((char*) &length, sizeof(size_t)); 00032 out.write(name.c_str(), name.length()); 00033 size_t doc_length = document->size(); 00034 out.write((char*) &doc_length, sizeof(size_t)); 00035 out.write((char*) &(document->at(0)), doc_length * sizeof(vt::Word)); 00036 } 00037 00039 void DocumentInfo::read(std::istream& in) { 00040 size_t length; 00041 in.read((char*) &length, sizeof(size_t)); 00042 char* name = new char[length + 1]; 00043 in.read(name, length); 00044 name[length] = 0; 00045 this->name.assign(name); 00046 size_t doc_length; 00047 in.read((char*) &doc_length, sizeof(size_t)); 00048 document = new vt::Document(doc_length); 00049 in.read((char*) &document->at(0), doc_length * sizeof(vt::Word)); 00050 this->delete_document = true; 00051 delete[] name; 00052 } 00053 00055 ODUFinder::ODUFinder() : 00056 camera_image(NULL), template_image(NULL), image(NULL), tree_builder( 00057 Feature::Zero()), visualization_mode_(FRAMES) { //SEQUENCES) { //FRAMES) { //SEQUENCES 00058 command = std::string("/load"); 00059 database_location = std::string("database/germandeli"); 00060 images_directory = std::string("data/germandeli"); 00061 images_for_visualization_directory = std::string(""); 00062 votes_count = 30; 00063 tree_k = 5; 00064 tree_levels = 5; 00065 min_cluster_size = 30; 00066 unknown_object_threshold = 0.3; 00067 sliding_window_size = 10; 00068 enable_clustering = 1; 00069 enable_incremental_learning = 0; 00070 enable_visualization = 0; 00071 object_id = 700000; 00072 frame_number = 0; 00073 radius_adaptation_r_min = 200.0; 00074 radius_adaptation_r_max = 600.9; 00075 radius_adaptation_A = 800.0; 00076 radius_adaptation_K = 0.02; 00077 count_templates = 0; 00078 // SiftParameters params = GetSiftParameters(); 00079 // params.DoubleImSize = 0; 00080 // SetSiftParameters(params); 00081 00082 // Logger 00083 rospack::ROSPack rp; 00084 char *p[] = { "rospack", "find", "objects_of_daily_use_finder" }; 00085 //std::string p("rospack find objects_of_daily_use_finder"); 00086 rp.run(3, p); 00087 //ROS_INFO("ERROOORR %s",p.c_str()); 00088 //rp.run(p); 00089 char loggerFileName[300]; 00090 //Copy string with char * strcpy ( char * destination, const char * source ); 00091 strcpy(loggerFileName, rp.getOutput().c_str()); 00092 //Get string length 00093 loggerFileName[strlen(loggerFileName) - 1] = 0; 00094 char timeStr[30]; 00095 time_t t = time(NULL); 00096 //Format time to string with size_t strftime ( char * ptr, size_t maxsize, const char * format, const struct tm * timeptr ); 00097 strftime(timeStr, 30, "/stat_%Y%m%d_%H%M%S.txt", localtime(&t)); 00098 //Concatenate strings with char * strcat ( char * destination, const char * source ); 00099 strcat(loggerFileName, timeStr); 00100 00101 //ROS_INFO("Creating statistics file at: %s\n", loggerFileName); 00102 ROS_INFO("Creating statistics file at: %s\n", "test.txt"); 00103 //logger.open(loggerFileName, std::fstream::out); 00104 logger.open ("/home/monica/test.txt", std::ofstream::app); 00105 00106 //color table - used for the visualization only 00107 color_table[0] = cvScalar(255, 0, 0); 00108 color_table[1] = cvScalar(0, 255, 0); 00109 color_table[2] = cvScalar(0, 0, 255); 00110 color_table[3] = cvScalar(255, 255, 0); 00111 color_table[4] = cvScalar(255, 0, 255); 00112 color_table[5] = cvScalar(0, 255, 255); 00113 color_table[6] = cvScalar(255, 255, 255); 00114 color_table[7] = cvScalar(125, 255, 255); 00115 color_table[8] = cvScalar(255, 125, 255); 00116 color_table[9] = cvScalar(255, 255, 125); 00117 color_table[10] = cvScalar(125, 125, 255); 00118 color_table[11] = cvScalar(255, 125, 125); 00119 color_table[12] = cvScalar(125, 255, 125); 00120 } 00121 00123 void ODUFinder::set_visualization(bool enable_visualization_in) { 00124 enable_visualization = enable_visualization_in; 00125 if (enable_visualization) { 00126 cvNamedWindow("visualization", CV_WINDOW_AUTOSIZE); 00127 cvStartWindowThread(); 00128 } 00129 } 00130 00132 ODUFinder::~ODUFinder() { 00133 if (enable_visualization) { 00134 cvReleaseImage(&camera_image); 00135 cvReleaseImage(&template_image); 00136 cvReleaseImage(&image); 00137 cvDestroyWindow("visualization"); 00138 } 00139 delete db; 00140 std::map<int, DocumentInfo*>::iterator iter; 00141 for (iter = documents_map.begin(); iter != documents_map.end(); ++iter) 00142 delete[] iter->second; 00143 logger.close(); 00144 } 00145 00147 std::string ODUFinder::process_image(IplImage* camera_image_in) { 00148 //extract keypoints in the whole image 00149 ROS_INFO("call keypoints extractor!"); 00150 Keypoint keypoints = extract_keypoints(camera_image_in); 00151 Keypoint p = keypoints; 00152 camera_keypoints_count = 0; 00153 //declare vector<T*> vt; 00154 vt::Document full_doc; 00155 //push keypoints in the vocabulary tree document 00156 while (p != NULL) { 00157 Feature f(p->descrip); 00158 full_doc.push_back(tree.quantize(f)); 00159 p = p->next; 00160 ++camera_keypoints_count; 00161 } 00162 ROS_INFO_STREAM(camera_keypoints_count << " keypoints found!"); 00163 00164 // cluster keypoints 00165 //features2d.clear(); 00166 //features2d.resize(camera_keypoints_count); 00167 00168 //double** points = new double*[camera_keypoints_count]; 00169 ANNpointArray points; 00170 points = annAllocPts(camera_keypoints_count, 2); 00171 00172 //initialize a vector of objects of KeypointExt (keypoints extension class) 00173 std::vector<KeypointExt*> camera_keypoints(camera_keypoints_count); 00174 00175 p = keypoints; 00176 //loop over all points and insert keypoints and their quantized words 00177 //into camera_keypoints 00178 for (int i = 0; p != NULL; ++i, p = p->next) { 00179 if (enable_clustering) { 00180 //points[i] = new double[2]; 00181 points[i][0] = p->col; 00182 points[i][1] = p->row; 00183 } 00184 camera_keypoints[i] = new KeypointExt(p, full_doc[i]); 00185 } 00186 00187 size_t cluster_count = 0; 00188 // if clustering enabled - group features in 2D 00189 // according to adaptive radius criterion 00190 if (enable_clustering) { 00191 std::vector<int> membership(camera_keypoints_count); 00192 cluster_count = cluster_points(points, camera_keypoints_count, 00193 membership, radius_adaptation_r_max, radius_adaptation_r_min, 00194 radius_adaptation_A, radius_adaptation_K); 00195 ROS_INFO_STREAM("Clusters found = " << cluster_count); 00196 00197 cluster_sizes.resize(cluster_count, 0); 00198 cluster_sizes.assign(cluster_count, 0); 00199 for (size_t i = 0; i < camera_keypoints_count; ++i) { 00200 camera_keypoints[i]->cluster = membership[i]; 00201 ++cluster_sizes[membership[i]]; 00202 //delete[] points[i]; 00203 } 00204 delete[] points; 00205 } 00206 matches_map.clear(); 00207 // std::map<uint32_t, float>::iterator it; 00208 // for ( it=matches_map.begin() ; it != matches_map.end(); it++ ) 00209 // it->second *= 0.4; 00210 00211 // Search the whole image 00212 // vector of Match-es 00213 vt::Matches matches; 00214 //find #votes_count matches 00215 db->find(full_doc, votes_count + 1, matches); 00216 ROS_INFO("Whole image: "); 00217 00218 //calculate scores over all image 00219 // @TODO - Why is calculation over all image necessary? 00220 //update_matches_map(matches, camera_keypoints_count); 00221 00222 // Calculates and accumulates scores for each cluster 00223 for (size_t c = 0; c < cluster_count; ++c) { 00224 vt::Document cluster_doc; 00225 vt::Matches cluster_matches; 00226 00227 for (size_t i = 0; i < camera_keypoints_count; ++i) 00228 if (camera_keypoints[i]->cluster == c) 00229 cluster_doc.push_back(full_doc[i]); 00230 00231 if (cluster_doc.size() < (size_t) min_cluster_size) 00232 continue; 00233 00234 db->find(cluster_doc, votes_count + 1, cluster_matches); 00235 ROS_INFO_STREAM("Cluster " << c << "(size = " << cluster_doc.size() << "):"); 00236 update_matches_map(cluster_matches, cluster_doc.size()); 00237 } 00238 00239 00240 // Sort the votes 00241 std::vector<std::pair<uint32_t, float> > votes(matches_map.size()); 00242 std::map<uint32_t, float>::iterator iter = matches_map.begin(); 00243 for (int i = 0; iter != matches_map.end(); ++iter, ++i) { 00244 votes[i].first = iter->first; 00245 votes[i].second = iter->second; 00246 } 00247 00248 //print results 00249 ROS_INFO("RESULTS: "); 00250 std::sort(votes.begin(), votes.end(), compare_pairs); 00251 00252 // if object is unknown either skip detection 00253 // or add the template to the database 00254 if (votes.size() > 0 && votes[0].second < unknown_object_threshold) { 00255 ROS_INFO("Unknown object!"); 00256 if (enable_incremental_learning) { 00257 time_t rawtime; 00258 struct tm * timeinfo; 00259 char buffer[25]; 00260 time(&rawtime); 00261 timeinfo = localtime(&rawtime); 00262 //TODO: change this to whatever object appearance are we learning for 00263 strftime(buffer, 25, "Object_%Y%m%d%H%M%S", timeinfo); 00264 std::string object_name(buffer); 00265 add_image_to_database(full_doc, object_name); 00266 ROS_INFO("Object added into database as %s!", object_name.c_str()); 00267 } 00268 } else { 00269 for (uint i = 0; (i < votes.size() && i < (uint) documents_map.size()); ++i) 00270 ROS_INFO("%s, %f", documents_map[votes[i].first]->name.c_str(), votes[i].second); 00271 00272 //int current_id = votes[0].first; 00273 00274 // @TODO: make this a parameter 00275 // classify with the sliding window 00276 std::string name; 00277 DocumentInfo** documents_to_visualize = new DocumentInfo*[templates_to_show]; 00278 for (int i=0; i<templates_to_show; ++i) 00279 documents_to_visualize[i] = NULL; 00280 00281 // if (sliding_window_size == 1) { 00282 // documents_to_visualize[0] = documents_map[current_id]; 00283 // name = documents_map[current_id]->name; 00284 // } else { 00285 // sliding_window.push_back(current_id); 00286 // 00287 // if (sliding_window.size() > sliding_window_size) 00288 // sliding_window.pop_front(); 00289 // 00290 // last_templates.clear(); 00291 // 00292 // std::list<int>::iterator iter = sliding_window.begin(); 00293 // for (int i = 0; iter != sliding_window.end(); ++iter, ++i) { 00294 // if (last_templates.find(*iter) == last_templates.end()) 00295 // last_templates[*iter] = 0; 00296 // 00297 // last_templates[*iter] += sliding_window_size;// + (sliding_windows_size - i); 00298 // } 00299 // 00300 // std::map<int, int>::iterator map_iter = last_templates.begin(); 00301 // 00302 // // Get all pairs in order to sort them later 00303 // std::vector<std::pair<int, int> > pairs(last_templates.size()); 00304 // 00305 // for (; map_iter != last_templates.end(); ++map_iter) 00306 // { 00307 // std::pair<int, int> p; 00308 // p.first = map_iter->first; 00309 // p.second = map_iter->second; 00310 // pairs.push_back(p); 00311 // } 00312 // 00313 // std::sort(pairs.begin(), pairs.end(), compare_pairs); 00314 // 00315 // for (int i=0; i<templates_to_show; ++i) 00316 // documents_to_visualize[i] = documents_map[pairs[i].first]; 00317 // 00318 // name = documents_map[pairs[0].first]->name; 00319 // 00320 // } 00321 00322 00323 // Log the results 00324 //TODO: make this optional and probably distinguish between different types of 00325 //image names 00326 ROS_INFO("Writing to the statistics file\n"); 00327 logger << "FRAME " << frame_number << std::endl; 00328 frame_number++; 00329 00330 std::set<std::string> unique_names; 00331 int added = 0; 00332 // for (uint i = 0; added < templates_to_show && i < votes.size(); ++i) 00333 // { 00334 DocumentInfo* d = documents_map[votes[0].first]; 00335 size_t position = d->name.find('_'); 00336 00337 // int frame_number = 0; 00338 // ROS_INFO("documents_map %s" , d->name.c_str()); 00339 00340 // if (position == std::string::npos) 00341 // position = d->name.find('.'); 00342 00343 std::string short_name(d->name.c_str(), position); 00344 std::cerr << "short_name: " << short_name << std::endl; 00345 if (short_name == "hmilch") 00346 00347 { 00348 //count_templates++; 00349 //documents_to_visualize[added] = documents_map[votes[0].first]; 00350 logger << short_name.c_str() << "\t" << count_templates++ 00351 << std::endl; 00352 } 00353 00354 /*if (unique_names.find(short_name) == unique_names.end()) 00355 { 00356 unique_names.insert(short_name); 00357 documents_to_visualize[added] = documents_map[votes[i].first]; 00358 logger << short_name.c_str() << "\t" << votes[i].second 00359 << std::endl; 00360 00361 //if (stat_summary_map.find(short_name) == stat_summary_map.end()) 00362 // stat_summary_map[short_name] = 0; 00363 //++stat_summary_map[short_name]; 00364 added++; 00365 }*/ 00366 // } 00367 // ROS_INFO("the name appears %d times" , count2++); 00368 00369 logger << std::endl; 00370 logger.flush(); 00371 00372 //visualize 00373 if (enable_visualization) { 00374 if (visualization_mode_ == FRAMES) 00375 visualize(camera_image_in, documents_to_visualize, &camera_keypoints); 00376 else 00377 { 00378 if (documents_to_visualize[0] != NULL) 00379 { 00380 save_result_for_sequence(documents_to_visualize[0]->name); 00381 } 00382 } 00383 00384 } 00385 delete[] documents_to_visualize; 00386 //also for logging 00387 size_t last_slash_id = name.find_last_of("/"); 00388 if (last_slash_id == std::string::npos) 00389 last_slash_id = 0; 00390 else 00391 ++last_slash_id; 00392 //return the name of the object, that is the correponding image name 00393 return name.substr(last_slash_id, name.find_last_of('.') 00394 - last_slash_id).c_str(); 00395 } 00396 FreeKeypoints(keypoints); 00397 return ""; 00398 } 00399 00401 int ODUFinder::start() { 00402 //if init build and save the database 00403 if (command.compare("/init") == 0) { 00404 build_database(images_directory); 00405 save_database(database_location); 00406 } 00407 //load previosly built database and perform recognition 00408 else if (command.compare("/load") == 0) 00409 load_database(database_location); 00410 //only extract sift features and save them in a specified images_directory 00411 else if (command.compare("/sift_only") == 0) 00412 process_images(images_directory); 00413 else 00414 return 1; 00415 00416 return 0; 00417 } 00418 00420 void ODUFinder::build_database(std::string directory) { 00421 std::vector<FeatureVector> images; 00422 trace_directory(directory.c_str(), "", images); 00423 ROS_INFO("Preparing features for the tree..."); 00424 FeatureVector all_features; 00425 for (unsigned int i = 0; i < images.size(); ++i) 00426 for (unsigned int j = 0; j < images[i].size(); ++j) 00427 all_features.push_back(images[i][j]); 00428 00429 ROS_INFO_STREAM("Building a tree with " << all_features.size() 00430 << " nodes..."); 00431 tree_builder.build(all_features, tree_k, tree_levels); 00432 tree = tree_builder.tree(); 00433 ROS_INFO("Creating the documents..."); 00434 docs.resize(images.size()); 00435 00436 for (unsigned int i = 0; i < images.size(); ++i) { 00437 //printf("\tImage %d\n", i); 00438 for (unsigned int j = 0; j < images[i].size(); ++j) { 00439 //printf("\t\tFeature %d\n", j); 00440 docs[i].push_back(tree.quantize(images[i][j])); 00441 } 00442 } 00443 00444 ROS_INFO("Creating database..."); 00445 db = new vt::Database(tree.words()); 00446 ROS_INFO("Populating the database with the documents..."); 00447 for (unsigned int i = 0; i < images.size(); ++i) { 00448 documents_map[db->insert(docs[i])] = new DocumentInfo(&(docs[i]), 00449 image_names[i]); 00450 } 00451 00452 ROS_INFO("Training database..."); 00453 db->computeTfIdfWeights(1); 00454 ROS_INFO("Database created!"); 00455 } 00456 00458 void ODUFinder::process_images(std::string directory) { 00459 std::vector<FeatureVector> images; 00460 trace_directory(directory.c_str(), "", images, true); 00461 } 00462 00464 void ODUFinder::save_database_without_tree(std::string& directory) { 00465 ROS_INFO("Saving documents..."); 00466 std::string documents_file(directory); 00467 documents_file.append("/images.documents"); 00468 std::ofstream out(documents_file.c_str(), std::ios::out | std::ios::binary); 00469 size_t map_size = documents_map.size(); 00470 out.write((char*) &map_size, sizeof(size_t)); 00471 std::map<int, DocumentInfo*>::iterator iter; 00472 for (iter = documents_map.begin(); iter != documents_map.end(); ++iter) { 00473 out.write((char*) &iter->first, sizeof(int)); 00474 iter->second->write(out); 00475 } 00476 00477 ROS_INFO("Saving weights..."); 00478 std::string weights_file(directory); 00479 weights_file.append("/images.weights"); 00480 db->saveWeights(weights_file.c_str()); 00481 out.close(); 00482 ROS_INFO("Done! Press Ctrl+C and roslaunch detect.launch"); 00483 } 00484 00486 void ODUFinder::save_database(std::string& directory) { 00487 ROS_INFO("Saving the tree..."); 00488 std::string tree_file(directory); 00489 tree_file.append("/images.tree"); 00490 tree.save(tree_file.c_str()); 00491 save_database_without_tree(directory); 00492 } 00493 00495 void ODUFinder::load_database(std::string& directory) { 00496 ROS_INFO("Loading the tree..."); 00497 std::string tree_file(directory); 00498 tree_file.append("/images.tree"); 00499 tree.load(tree_file.c_str()); 00500 ROS_INFO("Initializing the database..."); 00501 db = new vt::Database(tree.words());//, tree.splits()); 00502 std::string documents_file(directory); 00503 documents_file.append("/images.documents"); 00504 ROS_INFO("Loading the documents... (%s)", documents_file.c_str()); 00505 std::ifstream in(documents_file.c_str(), std::ios::in | std::ios::binary); 00506 size_t map_size; 00507 in.read((char*) &map_size, sizeof(size_t)); 00508 for (size_t i = 0; i < map_size; ++i) { 00509 int id; 00510 DocumentInfo* document_info = new DocumentInfo(); 00511 in.read((char*) &id, sizeof(int)); 00512 document_info->read(in); 00513 vt::Document* doc = document_info->document; 00514 int d = db->insert(*doc); 00515 documents_map[d] = document_info; 00516 } 00517 00518 ROS_INFO("Loading weights..."); 00519 std::string weights_file(directory); 00520 weights_file.append("/images.weights"); 00521 db->loadWeights(weights_file.c_str()); 00522 in.close(); 00523 ROS_INFO("READY!"); 00524 } 00525 00527 void ODUFinder::add_image_to_database(vt::Document& doc, std::string& name) { 00528 docs.push_back(doc); 00529 documents_map[db->insert(doc)] = new DocumentInfo(&doc, name); 00530 db->computeTfIdfWeights(1); 00531 //TODO: Why do we not update the images.tree??? 00532 save_database_without_tree(database_location); 00533 } 00534 00536 void ODUFinder::trace_directory(const char* dir, const char* prefix, 00537 std::vector<FeatureVector>& images, bool onlySaveImages) { 00538 ROS_INFO("Tracing directory: %s", dir); 00539 DIR *pdir = opendir(dir); 00540 struct dirent *pent = NULL; 00541 if (pdir == NULL) { 00542 ROS_ERROR("ERROR! Directory %s not found", dir); 00543 return; 00544 } 00545 00546 while ((pent = readdir(pdir))) { 00547 if (strcmp(pent->d_name, ".") != 0 && strcmp(pent->d_name, "..") != 0 00548 && strcmp(pent->d_name, "IGNORE") != 0) { 00549 std::string short_filename(prefix); 00550 short_filename.append(pent->d_name); 00551 std::string filename(dir); 00552 filename.append(pent->d_name); 00553 struct stat st_buf; 00554 if (lstat(filename.c_str(), &st_buf) == -1) { 00555 ROS_ERROR("ERROR: Invalid file name %s", filename.c_str()); 00556 ROS_ERROR("Exiting"); 00557 exit(2); 00558 } 00559 00560 if (S_ISDIR(st_buf.st_mode)) { 00561 filename.append("/"); 00562 short_filename.append("/"); 00563 trace_directory(filename.c_str(), short_filename.c_str(), 00564 images, onlySaveImages); 00565 } else { 00566 process_file(filename, images, onlySaveImages); 00567 image_names.push_back(short_filename); 00568 } 00569 } 00570 } 00571 closedir(pdir); 00572 } 00573 00575 void ODUFinder::visualize(IplImage *camera_image_in, 00576 DocumentInfo** template_document_info, 00577 std::vector<KeypointExt*> *camera_keypoints) { 00578 int templates_count = 0; 00579 00580 if (visualization_mode_ == FRAMES) 00581 templates_count = templates_to_show; 00582 else if (visualization_mode_ == SEQUENCES) 00583 { 00584 templates_count = sequence_buffer.size(); 00585 } 00586 00587 if (template_image != NULL) 00588 cvReleaseImage(&template_image); 00589 00590 if (image != NULL) 00591 cvReleaseImage(&image); 00592 00593 std::string image_file(images_for_visualization_directory); 00594 IplImage** template_images = new IplImage*[templates_count]; 00595 int total_height = 0; 00596 int max_width = 0; 00597 00598 00599 //calculate dimensions of the display image 00600 for (int i = 0; i < templates_count; ++i) { 00601 std::string template_image_file(image_file); 00602 00603 template_images[i] = NULL; 00604 00605 if (visualization_mode_ == FRAMES) { 00606 if (template_document_info[i] != NULL) { 00607 template_image_file.append( 00608 template_document_info[i]->name.c_str()); 00609 template_images[i] = cvLoadImage(template_image_file.c_str(), 00610 CV_LOAD_IMAGE_GRAYSCALE); 00611 } 00612 } else if (visualization_mode_ == SEQUENCES) { 00613 template_image_file.append(sequence_buffer[i]); 00614 template_images[i] = cvLoadImage(template_image_file.c_str(), 00615 CV_LOAD_IMAGE_GRAYSCALE); 00616 } 00617 00618 if (template_images[i] != NULL) { 00619 total_height += template_images[i]->height; 00620 max_width = MAX(max_width, template_images[i]->width); 00621 } 00622 } 00623 00624 int height = camera_image_in->height; 00625 00626 float scale_factor = ( total_height == 0 ? 0 : ((float) height) / ((float) total_height)); 00627 00628 if (scale_factor > 0.0001) 00629 max_width = (int) (max_width * scale_factor); 00630 else 00631 max_width = 0; 00632 00633 IplImage* tmp_image = cvCreateImage(cvSize(camera_image_in->width 00634 + max_width, height), camera_image_in->depth, 00635 camera_image_in->nChannels); 00636 00637 00638 cvFillImage(tmp_image, 0); 00639 cvSetImageROI(tmp_image, cvRect(0, 0, camera_image_in->width, 00640 camera_image_in->height)); 00641 cvCopy(camera_image_in, tmp_image); 00642 00643 //show template images 00644 int last_y = 0; 00645 for (int i = 0; i < templates_count; ++i) { 00646 if (template_images[i] == NULL) 00647 continue; 00648 00649 IplImage* tmp_template_image = cvCreateImage(cvSize( 00650 template_images[i]->width * scale_factor, 00651 template_images[i]->height * scale_factor), 00652 template_images[i]->depth, template_images[i]->nChannels); 00653 cvResize(template_images[i], tmp_template_image); 00654 cvSetImageROI(tmp_image, cvRect(camera_image_in->width, last_y, 00655 tmp_template_image->width, tmp_template_image->height)); 00656 last_y += tmp_template_image->height; 00657 00658 //free resources 00659 cvCopy(tmp_template_image, tmp_image); 00660 cvReleaseImage(&tmp_template_image); 00661 } 00662 00663 cvResetImageROI(tmp_image); 00664 image = cvCreateImage(cvSize(tmp_image->width, tmp_image->height), 00665 tmp_image->depth, 3); 00666 cvCvtColor(tmp_image, image, CV_GRAY2RGB); 00667 cvReleaseImage(&tmp_image); 00668 // display camera image keypoints 00669 if (camera_keypoints != NULL) 00670 { 00671 for (unsigned int i = 0; i < camera_keypoints->size(); ++i) { 00672 if (cluster_sizes[(*camera_keypoints)[i]->cluster] 00673 >= (size_t) min_cluster_size) 00674 cvCircle(image, cvPoint((int) ((*camera_keypoints)[i]->keypoint->col), 00675 (int) ((*camera_keypoints)[i]->keypoint->row)), 3, 00676 color_table[(*camera_keypoints)[i]->cluster % COLORS]); 00677 } 00678 } 00679 //display template keypoints 00680 for (int i = 0; i < templates_count; ++i) { 00681 if (template_images[i] == NULL) 00682 continue; 00683 // Keypoint template_keypoints = extract_keypoints(template_images[i], true); 00684 // for (int ii=0; template_keypoints != NULL; ++ii, template_keypoints = template_keypoints->next) 00685 // { 00686 // cvCircle(image, cvPoint((int)(camera_image_in->width + template_keypoints->col), 00687 // (int)(template_keypoints->row)), 3, 00688 // color_table[1 % COLORS]); //0, 255, 0 00689 // } 00690 //free remaining resources 00691 cvReleaseImage(&template_images[i]); 00692 } 00693 00694 delete[] template_images; 00695 00696 //if the region of interest around keypoints is needed 00697 //useful for e.g. in-hand object modeling 00698 if (extract_roi_) 00699 extract_roi(camera_image, (*camera_keypoints)); 00700 else 00701 image_roi = NULL; 00702 00703 00704 // // display template image keypoints 00705 // std::vector<KeypointExt*> template_keypoints; 00706 // if (template_document_info != NULL) 00707 // { 00708 // // template_keypoints.resize(template_document_info->document->size()); 00709 // Keypoint tmp_keypoints = extract_keypoints(template_image, true); 00710 // for (int i=0; tmp_keypoints != NULL; ++i, tmp_keypoints = tmp_keypoints->next) 00711 // { 00712 // cvCircle(image, cvPoint((int)(camera_image_in->width + tmp_keypoints->col), (int)(tmp_keypoints->row)), 3, cvScalar(0, 255, 255)); 00713 // // template_keypoints[i] = new KeypointExt(tmp_keypoints, template_document_info->document->at(i)); 00714 // } 00715 // } 00716 00717 cvShowImage("visualization", image); 00718 00719 // Free resources 00720 if (camera_keypoints != NULL) 00721 for (std::vector<KeypointExt*>::iterator iter = (*camera_keypoints).begin(); iter != (*camera_keypoints).end(); ++iter) 00722 delete *iter; 00723 } 00724 00726 void ODUFinder::update_matches_map(vt::Matches& matches, size_t size) { 00727 for (int i = 0; (i < votes_count && i < (int) matches.size()); ++i) { 00728 if (matches_map.count(matches[i].id) == 0) 00729 matches_map[matches[i].id] = 0; 00730 int next_i = i; 00731 float diff; 00732 00733 do { 00734 ++next_i; 00735 diff = matches[next_i].score - matches[i].score; 00736 } while (diff == 0 && next_i < votes_count); 00737 00738 float database_score = 2 - matches[i].score; 00739 float place_score = 1; 00740 float size_score = 1;//size/80.0; 00741 float score = database_score * place_score * size_score; 00742 matches_map[matches[i].id] += score; 00743 ROS_INFO("\t%f\t%f\t%f\t%s", matches[i].score, diff, score, 00744 documents_map[matches[i].id]->name.c_str()); 00745 } 00746 } 00747 00749 void ODUFinder::process_file(std::string& filename, 00750 std::vector<FeatureVector>& images, bool onlySaveImages) { 00751 ROS_INFO("Processing file %s...", filename.c_str()); 00752 IplImage *image = cvLoadImage((char*) filename.c_str(), 00753 CV_LOAD_IMAGE_GRAYSCALE); 00754 Keypoint keypoints = extract_keypoints(image); 00755 ROS_INFO("Keypoints extracted"); 00756 FeatureVector features; 00757 Keypoint p = keypoints; 00758 int count = 0; 00759 00760 while (p != NULL) { 00761 Feature f(p->descrip); 00762 features.push_back(f); 00763 p = p->next; 00764 ++count; 00765 } 00766 00767 if (!onlySaveImages) 00768 images.push_back(features); 00769 else { 00770 IplImage *colour_image = cvLoadImage((char*) filename.c_str()); 00771 p = keypoints; 00772 while (p != NULL) { 00773 cvCircle(colour_image, cvPoint((int) (p->col), (int) (p->row)), 3, 00774 cvScalar(255, 255, 0)); 00775 p = p->next; 00776 } 00777 cvSaveImage((char*) filename.c_str(), colour_image); 00778 cvReleaseImage(&colour_image); 00779 } 00780 cvReleaseImage(&image); 00781 FreeKeypoints(keypoints); 00782 ROS_INFO("Done! %d features found!", count); 00783 } 00784 00786 Keypoint ODUFinder::extract_keypoints(IplImage *image, bool frames_only) { 00787 Image sift_image = CreateImage(image->height, image->width); 00788 for (int i = 0; i < image->height; ++i) { 00789 uint8_t* pSrc = (uint8_t*) image->imageData + image->widthStep * i; 00790 float* pDst = sift_image->pixels + i * sift_image->stride; 00791 for (int j = 0; j < image->width; ++j) 00792 pDst[j] = (float) pSrc[j] * (1.0f / 255.0f); 00793 } 00794 00795 Keypoint keypoints; 00796 if (frames_only) 00797 keypoints = GetKeypointFrames(sift_image); 00798 else 00799 keypoints = GetKeypoints(sift_image); 00800 DestroyAllImages(); 00801 return keypoints; 00802 } 00803 00805 void ODUFinder::write_stat_summary() { 00806 std::vector<std::pair<std::string, int> > pairs(stat_summary_map.size()); 00807 std::map<std::string, int>::iterator iter = stat_summary_map.begin(); 00808 for (int i = 0; iter != stat_summary_map.end(); ++iter, ++i) { 00809 pairs[i].first = iter->first; 00810 pairs[i].second = iter->second; 00811 } 00812 00813 std::sort(pairs.begin(), pairs.end(), compare_pairs2); 00814 logger << "--- SUMMARY ---" << std::endl; 00815 for (unsigned int i = 0; i < pairs.size(); ++i) 00816 logger << pairs[i].first.c_str() << "\t" << pairs[i].second 00817 << std::endl; 00818 logger.close(); 00819 } 00820 00822 void ODUFinder::extract_roi(IplImage *image, 00823 std::vector<KeypointExt*> camera_keypoints) { 00824 //create a sequence storage for projected points 00825 CvMemStorage* stor = cvCreateMemStorage(0); 00826 CvSeq* seq = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), 00827 sizeof(CvPoint), stor); 00828 00829 for (unsigned long i = 0; i < camera_keypoints.size(); i++) { 00830 cv::Point2d uv; 00831 CvPoint pt; 00832 pt.x = camera_keypoints[i]->keypoint->col; 00833 pt.y = camera_keypoints[i]->keypoint->row; 00834 cvSeqPush(seq, &pt); 00835 } 00836 //draw rectangle around the points 00837 CvRect rect = cvBoundingRect(seq); 00838 ROS_DEBUG_STREAM("rect: " << rect.x << " " << rect.y << " " << rect.width 00839 << " " << rect.height); 00840 00841 //get subimage, aka region of interest 00842 cvSetImageROI(image, rect); 00843 //sub-image 00844 image_roi = cvCreateImage(cvSize(rect.width, rect.height), image->depth, 00845 image->nChannels); 00846 00847 cvCopy(image, image_roi); 00848 cvResetImageROI(image); // release image ROI 00849 return; 00850 } 00851 00852 void ODUFinder::save_result_for_sequence(std::string& best_template_filename) { 00853 sequence_buffer.push_back(best_template_filename); 00854 } 00855 00856 void ODUFinder::visualize_sequence() { 00857 00858 } 00859 00860 void ODUFinder::clear_sequence_buffer() { 00861 sequence_buffer.clear(); 00862 } 00863