Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Filter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

#include "Filter.h"
#include "MatchKD.h"
#include <set>

/*
* Filters the matches by the distances (->Ratio-test), and by using the A->B algorithm.
*
* @param pairMatches1 - The vector which presents pair of matches between image A to image B.
* @param pairMatches2 - The vector which presents pair of matches between image B to image A.
*
* return the vector of filtered matches according to the ratio-test,
* or empty; if pairMatches was empty or if filtered-matches were not found.
*/

vector<MatchKD, allocator<MatchKD>> filterMatches(vector<vector<MatchKD>> pairMatches1, vector<vector<MatchKD>> pairMatches2) {

float matchConf = 0.3f;
vector<MatchKD, allocator<MatchKD>> matches;
set<pair<int, int>> tempmatch;

// Finding filtered matches from A to B
for (size_t i = 0; i < pairMatches1.size(); ++i)
{
// Checking if there are less than 2 matches
if (pairMatches1[i].size() < 2)
continue;
const MatchKD& m0 = pairMatches1[i][0];
const MatchKD& m1 = pairMatches1[i][1];
// Ratio-test
if (m0.distance < (1.f - matchConf) * m1.distance)
{
matches.push_back(m0);
tempmatch.insert(std::make_pair(m0.queryIdx, m0.trainIdx));
}
}

// Finding filtered matches B to A
for (size_t i = 0; i < pairMatches2.size(); ++i)
{
// Checking if there are less than 2 matches
if (pairMatches2[i].size() < 2)
continue;
const MatchKD& m0 = pairMatches2[i][0];
const MatchKD& m1 = pairMatches2[i][1];
// Ratio-test
if (m0.distance < (1.f - matchConf) * m1.distance)
if (tempmatch.find(std::make_pair(m0.trainIdx, m0.queryIdx)) == tempmatch.end())
matches.push_back(MatchKD(m0.trainIdx, m0.queryIdx, m0.distance));
}
return matches;
}
7 changes: 7 additions & 0 deletions Filter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once
#include <vector>
#include "MatchKD.h"

using namespace std;

vector<MatchKD, allocator<MatchKD>> filterMatches(vector<vector<MatchKD>> pairMatches1, vector<vector<MatchKD>> pairMatches2);
82 changes: 82 additions & 0 deletions FilterTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "Filter.h"
#include <iostream>
#include <vector>

bool areVectorsEqual(const std::vector<MatchKD>& vec1, const std::vector<MatchKD>& vec2) {
if (vec1.size() != vec2.size()) {
return false;
}
for (size_t i = 0; i < vec1.size(); ++i) {
if (!(vec1[i] == vec2[i])) {
return false;
}
}
return true;
}

void printMatches(const std::vector<MatchKD>& matches) {
for (const auto& match : matches) {
std::cout << "QueryIdx: " << match.queryIdx << ", TrainIdx: " << match.trainIdx << ", Distance: " << match.distance << std::endl;
}
}

TEST_CASE("testing the filterMatches function when there is a match") {

vector<vector<MatchKD>> pairMatches1 = {
{MatchKD(0, 191, 77.0f), MatchKD(0, 27, 82.0f)},
{MatchKD(1, 18, 46.0f), MatchKD(1, 46, 69.0f)},
{MatchKD(2, 163, 98.0f), MatchKD(2, 139, 102.0f)},
{MatchKD(3, 89, 64.0f), MatchKD(3, 220, 73.0f)},
};

vector<vector<MatchKD>> pairMatches2 = {
{MatchKD(0, 321, 70.0f), MatchKD(0, 164, 78.0f)},
{MatchKD(1, 50, 65.0f), MatchKD(1, 166, 76.0f)},
{MatchKD(2, 360, 86.0f), MatchKD(2, 48, 88.0f)},
{MatchKD(3, 107, 79.0f), MatchKD(3, 196, 85.0f)},
};

vector<MatchKD> expectedMatches = {
MatchKD(1, 18, 46.0f)
};

vector<MatchKD> actualMatches = filterMatches(pairMatches1, pairMatches2);

std::cout << "Tesing filterMatches when matches found: " << actualMatches.size() << " matches" << std::endl;
printMatches(actualMatches);
CHECK(areVectorsEqual(actualMatches, expectedMatches));

}

TEST_CASE("Testing empty inputs") {
vector<vector<MatchKD>> empty1, empty2;
vector<MatchKD> expectedMatches;
vector<MatchKD> actualMatches = filterMatches(empty1, empty2);

std::cout << "Testing empty inputs - Expected: 0 matches, Actual: " << actualMatches.size() << " matches" << std::endl;
CHECK(areVectorsEqual(actualMatches, expectedMatches));
}

TEST_CASE("Tesing filterMatches when filtered not found")
{
std::vector<std::vector<MatchKD>> pairMatches1 = {
{MatchKD(0, 191, 77.0f), MatchKD(0, 27, 82.0f)},
{MatchKD(2, 163, 98.0f), MatchKD(2, 139, 102.0f)},
{MatchKD(3, 89, 64.0f), MatchKD(3, 220, 73.0f)},
};

std::vector<std::vector<MatchKD>> pairMatches2 = {
{MatchKD(0, 191, 77.0f), MatchKD(0, 27, 82.0f)},
{MatchKD(2, 163, 98.0f), MatchKD(2, 139, 102.0f)},
{MatchKD(3, 89, 64.0f), MatchKD(3, 220, 73.0f)},
};

vector<MatchKD> actualMatches = filterMatches(pairMatches1, pairMatches2);
vector<MatchKD> expectedMatches;

std::cout << "Tesing filterMatches when filtered not found: " << actualMatches.size() << " matches" << std::endl;
CHECK(areVectorsEqual(actualMatches, expectedMatches));
}

1 change: 1 addition & 0 deletions MatchKD.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "MatchKD.h"
22 changes: 22 additions & 0 deletions MatchKD.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include <vector>

using namespace std;

//Class MatchKD to create an object that represents a match between 2 features of 2 images
class MatchKD {
public:
int queryIdx;
int trainIdx;
float distance;

MatchKD() : queryIdx(-1), trainIdx(-1), distance(FLT_MAX) {}

MatchKD(int qIdx, int tIdx, float dist) : queryIdx(qIdx), trainIdx(tIdx), distance(dist) {}

bool operator==(const MatchKD& other) const {
return queryIdx == other.queryIdx && trainIdx == other.trainIdx && distance == other.distance;
}

};