From edfa53a4ff7fda5d1470be805d95f935a8496d39 Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Thu, 11 Oct 2018 17:05:41 +0200 Subject: [PATCH] WIP on new init Rework seems done, but man are there bugs --- DescriptorManager.cpp | 217 +++++++----------------------------------- DescriptorManager.h | 10 +- main.cpp | 10 +- 3 files changed, 48 insertions(+), 189 deletions(-) diff --git a/DescriptorManager.cpp b/DescriptorManager.cpp index 01824a4..d3da795 100644 --- a/DescriptorManager.cpp +++ b/DescriptorManager.cpp @@ -83,9 +83,15 @@ void DescriptorManager::Init() { if (!fs::is_directory(mutationBase)) fs::create_directory(mutationBase); fs::path mutPath(mutationBase / itr->path().filename().generic_string()); - - Image* mutated = mutators[i]->getMutated(image); - mutated->write(mutPath.generic_string()); + Image* mutated; + if (!fs::exists(mutPath)) { //only mutate if nothing on disk + mutated = mutators[i]->getMutated(image); + mutated->write(mutPath.generic_string()); + } + else { + mutated = new Image; + mutated->read(mutPath.generic_string()); + } //now calculate all the features for the mutated images as well //foreach descriptor @@ -103,7 +109,7 @@ void DescriptorManager::Init() { //descriptors[i][image_name] = b1; b1 = &descriptor_types[j]->feature(mutated); unsigned long long n = b1->to_ullong(); - cout << "Writing " << b1 << "(" << n << ")" << " to " << featurePath << endl; + cout << "Writing " << *b1 << "(" << n << ")" << " to " << featurePath << endl; ofs.open(featurePath, fs::fstream::binary); //in binary mode; only open file after calculations have been done ofs.write(reinterpret_cast(&n), sizeof(n)); ofs.close(); @@ -115,201 +121,52 @@ void DescriptorManager::Init() { ifs.close(); b1 = new bitset<64>(n); } - //Else...? - //Do we need to store mutated features in a cache? For large experiments it's probably faster. + mutatedFeatures[j][i][image_name] = *b1; } delete mutated; } delete image; } + initialized = true; } - - -//Loads all images and determines the feature vectors -bool DescriptorManager::loadDescriptors() { - if (!fs::exists(img_path)) return false; - fs::directory_iterator end_itr; //last file in dir - map images; //image cache - fs::ifstream ifs; - fs::ofstream ofs; - for (int i = 0; i < numDescriptors; i++) { - //cout << "waddup " << i << endl; - //folder to store descriptors; create if not exists - fs::path descriptorBase("meta" / descriptor_types[i]->ToPath()); - if (!fs::is_directory(descriptorBase)) - if (fs::create_directory(descriptorBase)) {} - //cout << descriptorBase << " created." << endl; - - //foreach image - for (fs::directory_iterator itr(img_path); itr != end_itr; ++itr) { - if (!itr->path().has_extension()) continue; - fs::path featurePath(descriptorBase / itr->path().stem()); - //string image_name = featurePath.filename().generic_string(); - string image_name = itr->path().filename().generic_string(); - if (fs::exists(featurePath)) { //feature already calculated - ifs.open(featurePath, fs::fstream::binary); //in binary mode - unsigned long long n; - ifs.read(reinterpret_cast(&n), sizeof(n)); - ifs.close(); - - bitset<64> b1(n); - features[i][image_name] = b1; - } - else { //feature not yet calculated - Image* image; //only load image from disk if not loaded before - if (images.count(image_name)) { //if image exists in map - image = images[image_name]; - } - else { - image = new Image; - image->read(itr->path().string()); - images[image_name] = image; - } - //cout << "Calculating " << image_name << endl; - bitset<64> b1 = descriptor_types[i]->feature(image); - //descriptor_types[i]->distance(b1, b1); - features[i][image_name] = b1; - - unsigned long long n = b1.to_ullong(); - ofs.open(featurePath, fs::fstream::binary); //in binary mode; only open file after calculations have been done - ofs.write(reinterpret_cast(&n), sizeof(n)); - ofs.close(); - } - } - } - - return true; -} - -//Loads all images and makes and stores the mutations -bool DescriptorManager::createMutations() { - if (!fs::exists(img_path)) return false; - fs::directory_iterator end_itr; //last file in dir - map images; //image cache - fs::ifstream ifs; - fs::ofstream ofs; - - //foreach mutation - for (int i = 0; i < numMutations; i++) { - fs::path mutationBase(img_path / mutators[i]->ToPath()); - if (!fs::is_directory(mutationBase)) - if (fs::create_directory(mutationBase)) {} - - //foreach image - int z = 0; - for (fs::directory_iterator itr(img_path); itr != end_itr; ++itr) { - fs::path mutPath(mutationBase / itr->path().filename().generic_string()); - //if (z++ > 50) break; //for quick execution - //if (fs::exists(mutPath)) continue; //already exists - if (!itr->path().has_extension()) continue; //skip directories - - Image* image = new Image(itr->path().string()); - Image* mutated = mutators[i]->getMutated(image); - mutated->write(mutPath.generic_string()); - - //now calculate all the features for the mutated images as well - //foreach descriptor - for (int j = 0; j < numDescriptors; j++) { - //folder to store descriptors; create if not exists - fs::path descriptorBase("meta" / descriptor_types[j]->ToPath() / mutators[i]->ToPath()); - //cout << "Doing mutated descriptors for " << descriptorBase << endl; - if (!fs::is_directory(descriptorBase)) - if (fs::create_directory(descriptorBase)) {} - fs::path featurePath(descriptorBase / itr->path().stem()); - //cout << featurePath << endl; - string image_name = itr->path().filename().generic_string(); - if (!fs::exists(featurePath)) { //feature not yet calculated - //cout << "Calculating " << image_name << endl; - //descriptor_types[i]->distance(b1, b1); - //descriptors[i][image_name] = b1; - bitset<64> b1 = descriptor_types[j]->feature(mutated); - unsigned long long n = b1.to_ullong(); - cout << "Writing " << b1 << "(" << n << ")" << " to " << featurePath << endl; - ofs.open(featurePath, fs::fstream::binary); //in binary mode; only open file after calculations have been done - ofs.write(reinterpret_cast(&n), sizeof(n)); - ofs.close(); - } - } - delete mutated; - delete image; - } - - } - return true; -} - -//essentially insertion sort into a map -void DescriptorManager::similarImages(string image_name, int method, int numImages) { +//Sorts all images we have on distance from the query image +void DescriptorManager::rankImages(string image_name, int method) { bitset<64> target; - if (features[method].count(image_name)) { //if image exists in map + if (features[method].count(image_name) && initialized) { //if we have image target = features[method][image_name]; } - else { - Image* image = new Image; - image->read(image_name); //assuming http url - target = descriptor_types[method]->feature(image); - } //TODO: Add support for uploaded images - //cout << "HEY?!" << endl; - //first we need all distances to this image.. and insert them in a sorted way - //multiset > distances; //multiset is probably not needed, but who knows.. - //distances.clear(); //start fresh + else { + return; + } + distances.clear(); //start fresh for (map>::iterator it = features[method].begin(); it != features[method].end(); ++it) { - //cout << "ho " << endl; unsigned long long d = descriptor_types[method]->distance(target, it->second); pair p(d, it->first); distances.insert(p); //pairs are compared by their first element.. } - - int i = 0; - for (std::multiset>::iterator it = distances.begin(); it != distances.end() && i < numImages; ++it) { - //cout << "hey " << endl; - if (true || it->second != image_name) { - //cout << "(" << it->first << ", " << it->second << ")" << endl; - i++; - } - } } //inserts the descriptors of the mutated versions of the image. //Assumes the distances array is filled with the normal distances -void DescriptorManager::insertMutations(string image_name, int method) { - multiset > local_distance; - fs::ifstream ifs; +void DescriptorManager::rankMutations(string image_name, int method) { bitset<64> target; - if (features[method].count(image_name)) { //if image exists in map + if (features[method].count(image_name) && initialized) { //if we have image target = features[method][image_name]; } - cout << "Finding hits for " << image_name << " which has feature-number " << target.to_ullong() << endl; - for (map>::iterator it = features[method].begin(); it != features[method].end(); ++it) { - //cout << "ho " << endl; - unsigned long long d = descriptor_types[method]->distance(target, it->second); - pair p(d, it->first); - local_distance.insert(p); //pairs are compared by their first element.. + else { + return; } + cout << "Finding hits for " << image_name << " which has feature-number " << target.to_ullong() << endl; + multiset > local_distance = distances; //get our local copy of the distances. for (int i = 0; i < numMutations; i++) { - fs::path descriptorBase("meta" / descriptor_types[method]->ToPath() / mutators[i]->ToPath()); - fs::path imagePath(image_name); - fs::path featurePath(descriptorBase / imagePath.stem()); - cout << "Finding mutation for this image at: " << featurePath << endl; - if (fs::exists(featurePath)) { //feature already calculated - ifs.open(featurePath, fs::fstream::binary); //in binary mode - unsigned long long n; - ifs.read(reinterpret_cast(&n), sizeof(n)); - ifs.close(); - cout << "Number: " << n << endl; - bitset<64> b1(n); - unsigned long long d = descriptor_types[method]->distance(target, b1); - pair p(d, mutators[i]->ToString()); - local_distance.insert(p); - } - else { - cout << "data not set properly" << endl; - } + bitset<64> b1 = mutatedFeatures[method][i][image_name]; + unsigned long long d = descriptor_types[method]->distance(target, b1); + pair p(d, mutators[i]->ToString()); + local_distance.insert(p); } - cout << "..." << endl; for (int i = 0; i < numMutations; i++) { int j = 0; @@ -324,19 +181,10 @@ void DescriptorManager::insertMutations(string image_name, int method) { } } -void DescriptorManager::checkImages(int method) { - fs::directory_iterator end_itr; - for (fs::directory_iterator itr(img_path); itr != end_itr; ++itr) { - if (!itr->path().has_extension()) continue; //skip directories - insertMutations(itr->path().string(), method); - } -} - //outputs the gathered data to iostream //can be called directly or is called by its overload //assumes a < numDescriptors void DescriptorManager::outputMap(int a) { - if (a != 2) return; cout << "Outputting map " << descriptor_types[a]->ToString() << endl; map> a_map = features[a]; if (a_map.begin() == a_map.end()) { @@ -353,4 +201,11 @@ void DescriptorManager::outputMap() { for (int i = 0; i < numDescriptors; i++) { outputMap(i); } +} + +//Outputs all generated features ordered on distance from the query image. +void DescriptorManager::outputRank(string imagename, int method) { + for (std::multiset>::iterator it = distances.begin(); it != distances.end(); ++it) { + cout << "(" << it->first << ", " << it->second << ")" << endl; + } } \ No newline at end of file diff --git a/DescriptorManager.h b/DescriptorManager.h index 6b2df39..a6093b2 100644 --- a/DescriptorManager.h +++ b/DescriptorManager.h @@ -27,18 +27,18 @@ public: DescriptorManager(const fs::path & image_path); ~DescriptorManager(); void Init(); - bool loadDescriptors(); - bool createMutations(); - void similarImages(string image_name, int method, int numImages); - void insertMutations(string image_name, int method); - void checkImages(int method); + void rankImages(string image_name, int method); + void rankMutations(string image_name, int method); void outputMap(int a); void outputMap(); + void DescriptorManager::outputRank(string imagename, int method); private: static const int numDescriptors = 8; static const int numMutations = 7; //TODO: automagically update this? + bool initialized = false; + map> features[numDescriptors]; //array of maps that will hold the descriptors map> mutatedFeatures[numDescriptors][numMutations]; multiset > distances; //multiset that stores the distances diff --git a/main.cpp b/main.cpp index 76a37d4..a2f89ff 100644 --- a/main.cpp +++ b/main.cpp @@ -23,7 +23,7 @@ using namespace Magick; int main(int argc, char **argv) { - string imagename = "im124.jpg"; + string imagename = "im80.jpg"; int method = 6; int count = 1000; if (argc > 2) { @@ -41,12 +41,16 @@ int main(int argc, char **argv) { InitializeMagick(*argv); DescriptorManager* manager = new DescriptorManager("data"); manager->Init(); + manager->rankImages(imagename, method); + manager->rankMutations(imagename, method); + //manager->outputMap(method); + manager->outputRank(imagename, method); //cout << "Loading descriptiors.."; //manager->loadDescriptors(); - manager->createMutations(); + //manager->createMutations(); //cout << "done?" << endl; //manager->similarImages(imagename, method, count); - manager->insertMutations(imagename, method); + //manager->insertMutations(imagename, method); //cout << "done!" << endl << "Calculating distances.." << endl; //cout << "done!" << endl << "Outputting map.." << endl; //manager->outputMap();