#include "DescriptorManager.h" //Default constructor, don't use this DescriptorManager::DescriptorManager() { img_path = "data"; //default value } //Sets image path and defines the image descriptors. DescriptorManager::DescriptorManager(const fs::path & image_path) { img_path = image_path; //Manual definitions.. SAD! descriptor_types[6] = new DCTPearson(); descriptor_types[5] = new threshold(); descriptor_types[4] = new pearson(); descriptor_types[3] = new sobel(); descriptor_types[2] = new median(); descriptor_types[1] = new numColors(); descriptor_types[0] = new averageColor(); } //No need to call destructor.. yet? DescriptorManager::~DescriptorManager() { //Do some clean-up? //Realistically, when this gets destroyed the application is done anyway. } //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) { 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); descriptors[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); descriptors[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(); } } } //cout << "ma qualle ide!" << endl; /*for (map::iterator it = images.begin(); it != images.end(); ++it) { cout << "sup?" << endl; delete it->second; //free willy }*/ return true; } //essentially insertion sort into a map void DescriptorManager::similarImages(string image_name, int method, int numImages) { bitset<64> target; if (descriptors[method].count(image_name)) { //if image exists in map target = descriptors[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 //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.. for (map>::iterator it = descriptors[method].begin(); it != descriptors[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->second << endl; i++; } } } //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 != 6) return; cout << "Outputting map " << descriptor_types[a]->ToString() << endl; map> a_map = descriptors[a]; if (a_map.begin() == a_map.end()) { cout << "------------------------" << endl << "No data found" << endl << endl; } for (map>::iterator it = a_map.begin(); it != a_map.end(); ++it) { cout << it->first << " => " << it->second << " (" << it->second.to_ullong() << ")" << endl; } } //calls its buddy function to output all data to iostream void DescriptorManager::outputMap() { for (int i = 0; i < numDescriptors; i++) { outputMap(i); } }