140 lines
3.4 KiB
C++
140 lines
3.4 KiB
C++
|
#include <map>
|
||
|
#include "math.hpp"
|
||
|
#include <stdexcept>
|
||
|
#include <queue>
|
||
|
#include <opencv2/opencv.hpp>
|
||
|
#include <boost/filesystem.hpp>
|
||
|
#include <iterator>
|
||
|
#include <iostream>
|
||
|
#include <algorithm>
|
||
|
|
||
|
using dataset = std::vector<std::pair<math::csignal, std::string>>;
|
||
|
|
||
|
struct path_leaf_string {
|
||
|
std::string operator()(const boost::filesystem::directory_entry& entry) const
|
||
|
{
|
||
|
return entry.path().leaf().string();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
void read_directory(const std::string& name, std::vector<std::string>& v) {
|
||
|
boost::filesystem::path p(name);
|
||
|
boost::filesystem::directory_iterator start(p);
|
||
|
boost::filesystem::directory_iterator end;
|
||
|
std::transform(start, end, std::back_inserter(v), path_leaf_string());
|
||
|
}
|
||
|
|
||
|
double distance(math::csignal& v1, math::csignal& v2, int n){
|
||
|
if (v1.size() != v2.size()) {
|
||
|
throw std::runtime_error("les deux vecteurs doivent être de même longueur");
|
||
|
}
|
||
|
double d = 0;
|
||
|
|
||
|
auto v1_it = v1.begin();
|
||
|
auto v2_it = v2.begin();
|
||
|
|
||
|
while (v1_it != v1.end()) {
|
||
|
double dist = std::abs(*(v1_it++) - *(v2_it++));
|
||
|
d += std::pow(dist, n);
|
||
|
}
|
||
|
return std::pow(d, 1/n);
|
||
|
};
|
||
|
|
||
|
int argmax(std::vector<int>& v){
|
||
|
int arg = 0;
|
||
|
int max = v[0];
|
||
|
for(int i = 1; i < v.size() ; ++i){
|
||
|
if (v[i]>max){
|
||
|
arg = i;
|
||
|
max = v[i];
|
||
|
};
|
||
|
};
|
||
|
return arg;
|
||
|
};
|
||
|
|
||
|
struct pair_comp {
|
||
|
bool operator()(std::pair<double, std::string> a, std::pair<double, std::string> b) {
|
||
|
if (a.first == b.first) {
|
||
|
return false;
|
||
|
}
|
||
|
if (a.first > b.first) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
math::csignal img2desc(std::string filename, int cmax, int threshold) {
|
||
|
cv::Mat img = cv::imread(filename, CV_LOAD_IMAGE_COLOR);
|
||
|
return math::descriptors(img, cmax, threshold);
|
||
|
}
|
||
|
|
||
|
dataset get_data(std::string path, int size, int cmax, int threshold) {
|
||
|
dataset res;
|
||
|
std::vector<std::string> dirs;
|
||
|
read_directory(path, dirs);
|
||
|
for (auto dir: dirs) {
|
||
|
std::vector<std::string> files;
|
||
|
read_directory(path+"/"+dir, files);
|
||
|
|
||
|
std::string label = dir;
|
||
|
int count = 0;
|
||
|
for (int i=0; count<size/4 && i<files.size(); ++i) {
|
||
|
try {
|
||
|
math::csignal d = img2desc(path+"/"+dir+"/"+files[i], cmax, threshold);
|
||
|
res.push_back({d, label});
|
||
|
count++;
|
||
|
} catch (std::length_error& e) {
|
||
|
std::cout << "No contour: image skiped." << std::endl;
|
||
|
}
|
||
|
}
|
||
|
std::cout << res.size() << std::endl;
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char** argv) {
|
||
|
|
||
|
int k = 20;
|
||
|
int size = 100;
|
||
|
std::string path;
|
||
|
int cmax = 10;
|
||
|
int threshold = 20;
|
||
|
|
||
|
if (argc > 2) {
|
||
|
path = argv[1];
|
||
|
threshold = atoi(argv[2]);
|
||
|
} else {
|
||
|
std::cout << "Invalid number of arguments" << std::endl;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
dataset references = get_data(path, size, cmax, threshold);
|
||
|
math::csignal sample = img2desc(path+"/arret/arret0199.jpg", cmax, threshold);
|
||
|
std::priority_queue<std::pair<double, std::string>, std::vector<std::pair<double, std::string>>, pair_comp> neighbors;
|
||
|
std::map<std::string, int> labels;
|
||
|
|
||
|
for (auto desc: references) {
|
||
|
double d = distance(desc.first, sample, 1);
|
||
|
neighbors.push({d, desc.second});
|
||
|
}
|
||
|
|
||
|
for (int i=0; i<k; ++i) {
|
||
|
std::pair<double, std::string> nearest = neighbors.top();
|
||
|
neighbors.pop();
|
||
|
labels[nearest.second] += 1;
|
||
|
}
|
||
|
|
||
|
int max = 0;
|
||
|
std::string label;
|
||
|
|
||
|
for (auto val: labels) {
|
||
|
if (val.second > max) {
|
||
|
max = val.second;
|
||
|
label = val.first;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::cout << label << std::endl;
|
||
|
};
|