17 #include "drwnNNGraph.h"
18 #include "drwnNNGraphMoves.h"
21 using namespace Eigen;
26 namespace drwnNNGraphThreadedMoves {
29 template<
class DistanceMetric>
30 void initialize(
drwnNNGraph& graph,
const DistanceMetric& M);
38 template<
class DistanceMetric>
39 double rescore(
drwnNNGraph& graph,
const DistanceMetric& M);
47 template<
class DistanceMetric>
48 void update(
drwnNNGraph& graph,
const DistanceMetric& M);
56 template<
class DistanceMetric>
57 void updateImage(
drwnNNGraph& graph,
unsigned imgIndx,
const DistanceMetric& M);
62 template<
class DistanceMetric>
63 bool randproj(
drwnNNGraph& graph,
const DistanceMetric& M);
67 template<
class DistanceMetric>
68 bool enrichment(
drwnNNGraph& graph,
const DistanceMetric& M);
71 template<
class DistanceMetric>
74 const DistanceMetric&
_M;
80 const DistanceMetric& M) : _M(M), _imgIndxes(imgIndxes), _graph(g) { }
84 for (set<unsigned>::const_iterator it = _imgIndxes.begin(); it != _imgIndxes.end(); ++it) {
91 template<
class DistanceMetric>
94 const DistanceMetric&
_M;
100 const DistanceMetric& M) : _M(M), _imgIndxes(imgIndxes), _graph(g) { }
104 for (set<unsigned>::const_iterator it = _imgIndxes.begin(); it != _imgIndxes.end(); ++it) {
111 template<
class DistanceMetric>
114 const DistanceMetric&
_M;
120 const DistanceMetric& M) : _M(M), _imgIndxes(imgIndxes), _graph(g) { }
124 for (set<unsigned>::const_iterator it = _imgIndxes.begin(); it != _imgIndxes.end(); ++it) {
131 template<
class DistanceMetric>
134 const DistanceMetric&
_M;
140 const DistanceMetric& M) : _M(M), _nodeIndxes(nodeIndxes), _graph(g) { }
144 for (set<drwnNNGraphNodeIndex>::const_iterator it = _nodeIndxes.begin(); it != _nodeIndxes.end(); ++it) {
153 template<
class DistanceMetric>
157 const unsigned nJobs = std::min((
unsigned)graph.
numImages(),
159 vector<set<unsigned> > imgIndxes(nJobs);
160 for (
unsigned imgIndx = 0; imgIndx < graph.
numImages(); imgIndx++) {
161 if (!graph[imgIndx].bSourceMatchable) {
162 DRWN_LOG_DEBUG(
"...skipping initialization of " << graph[imgIndx].name());
166 imgIndxes[imgIndx % nJobs].insert(imgIndx);
172 vector<drwnNNGraphThreadedInitializeJob<DistanceMetric> *> jobs(nJobs);
173 for (
unsigned i = 0; i < nJobs; i++) {
175 threadPool.
addJob(jobs[i]);
179 for (
unsigned i = 0; i < jobs.size(); i++) {
185 template<
class DistanceMetric>
191 const unsigned nJobs = std::min((
unsigned)graph.
numImages(),
193 vector<set<unsigned> > imgIndxes(nJobs);
194 for (
unsigned imgIndx = 0; imgIndx < graph.
numImages(); imgIndx++) {
195 imgIndxes[imgIndx % nJobs].insert(imgIndx);
201 vector<drwnNNGraphThreadedRescoreJob<DistanceMetric> *> jobs(nJobs);
202 for (
unsigned i = 0; i < nJobs; i++) {
204 threadPool.
addJob(jobs[i]);
208 for (
unsigned i = 0; i < jobs.size(); i++) {
214 return graph.
energy().first;
217 template<
class DistanceMetric>
225 double totalWeight = 0.0;
226 for (
unsigned imgIndx = 0; imgIndx < graph.
numImages(); imgIndx++) {
227 if (!graph[imgIndx].bSourceMatchable)
continue;
228 for (
unsigned segId = 0; segId < graph[imgIndx].
numNodes(); segId++) {
229 const drwnNNGraphEdgeList& e = graph[imgIndx][segId].edges;
230 if (e.empty())
continue;
232 totalWeight += (double)e.front().weight;
237 set<drwnNNGraphNodeIndex> sampledNodes;
241 double weight = totalWeight * drand48();
244 for (
unsigned imgIndx = 0; imgIndx < graph.
numImages(); imgIndx++) {
245 if (!graph[imgIndx].bSourceMatchable)
continue;
246 for (
unsigned segId = 0; segId < graph[imgIndx].
numNodes(); segId++) {
247 const drwnNNGraphEdgeList& e = graph[imgIndx][segId].edges;
248 if (e.empty())
continue;
254 weight -= (double)e.front().weight;
258 totalWeight -= (double)e.front().weight;
262 if (weight <= 0.0)
break;
267 if (sampledNodes.size() == 1) {
272 vector<drwnNNGraphThreadedExhaustiveJob<DistanceMetric> *> jobs;
273 for (set<drwnNNGraphNodeIndex>::const_iterator it = sampledNodes.begin(); it != sampledNodes.end(); ++it) {
274 set<drwnNNGraphNodeIndex> nodeIndexes;
275 nodeIndexes.insert(*it);
277 threadPool.
addJob(jobs.back());
281 for (
unsigned i = 0; i < jobs.size(); i++) {
296 const unsigned nJobs = std::min((
unsigned)graph.
numImages(),
298 vector<set<unsigned> > imgIndxes(nJobs);
299 for (
unsigned imgIndx = 0; imgIndx < graph.
numImages(); imgIndx++) {
300 if (!graph[imgIndx].bSourceMatchable) {
301 DRWN_LOG_DEBUG(
"...skipping update of " << graph[imgIndx].name());
305 imgIndxes[imgIndx % nJobs].insert(imgIndx);
311 vector<drwnNNGraphThreadedUpdateJob<DistanceMetric> *> jobs(nJobs);
312 for (
unsigned i = 0; i < nJobs; i++) {
314 threadPool.
addJob(jobs[i]);
318 for (
unsigned i = 0; i < jobs.size(); i++) {
326 enrichment(graph, M);
332 template<
class DistanceMetric>
350 template<
class DistanceMetric>
354 bool bChanged =
false;
357 VectorXf mu(graph[0][0].features.size());
358 for (
int i = 0; i < mu.rows(); i++) {
359 mu[i] = float(drand48() - 0.5);
364 vector<pair<float, drwnNNGraphNodeIndex> > projections;
365 projections.reserve(graph.
numNodes());
370 const float x = mu.dot(graph[u].features);
371 projections.push_back(make_pair(x, u));
376 sort(projections.begin(), projections.end());
379 unsigned dbCountChanged = 0;
381 for (
unsigned i = 0; i < projections.size() - 1; i++) {
385 if (!graph[u.
imgIndx].bSourceMatchable || graph[u].edges.empty()) {
386 if (inext <= i) inext += 1;
391 while (inext != projections.size()) {
392 if (graph[projections[inext].second.imgIndx].bTargetMatchable &&
398 if (inext == projections.size())
break;
400 float uworst = sqrt(graph[u].edges.back().weight);
403 if ((projections[j].first - projections[i].first) >= uworst) {
408 if (!graph[projections[j].second.imgIndx].bTargetMatchable)
continue;
415 if (M.isFinite(graph[u], graph[v])) {
416 const float w = M.score(graph[u], graph[v]);
418 uworst = sqrt(graph[u].edges.back().weight);
426 DRWN_LOG_DEBUG(
"randproj() improved " << dbCountChanged <<
" matches");
431 template<
class DistanceMetric>
435 bool bChanged =
false;
438 for (
unsigned imgIndx = 0; imgIndx < graph.
numImages(); imgIndx++) {
440 if (!graph[imgIndx].bTargetMatchable)
continue;
442 for (
unsigned segId = 0; segId < graph[imgIndx].
numNodes(); segId++) {
443 const drwnNNGraphEdgeList& el = graph[imgIndx][segId].edges;
444 for (drwnNNGraphEdgeList::const_iterator kt = el.begin(); kt != el.end(); ++kt) {
447 if (!graph[kt->targetNode.imgIndx].bSourceMatchable)
452 if (graph[kt->targetNode].insert(e)) {
460 for (
unsigned imgIndx = 0; imgIndx < graph.
numImages(); imgIndx++) {
462 if (!graph[imgIndx].bSourceMatchable)
continue;
464 for (
unsigned segId = 0; segId < graph[imgIndx].
numNodes(); segId++) {
466 const drwnNNGraphEdgeList el(graph[imgIndx][segId].edges);
469 for (drwnNNGraphEdgeList::const_iterator it = el.begin(); it != el.end(); ++it) {
470 const drwnNNGraphEdgeList& r = graph[it->targetNode].edges;
472 for (drwnNNGraphEdgeList::const_iterator kt = r.begin(); kt != r.end(); ++kt) {
475 if (!graph[kt->targetNode.imgIndx].bTargetMatchable)
continue;
476 if (graph.
inSameEqvClass(kt->targetNode.imgIndx, imgIndx))
continue;
479 if ((it->status == DRWN_NNG_PROCESSED_TWICE) &&
480 (kt->status == DRWN_NNG_PROCESSED_TWICE))
continue;
483 if (!M.isFinite(graph[imgIndx][segId], graph[kt->targetNode]))
486 const float w = M.score(graph[imgIndx][segId], graph[kt->targetNode]);
487 if (graph[imgIndx][segId].insert(
drwnNNGraphEdge(kt->targetNode, w))) {
492 if (nCompared < 0)
break;
495 if (nCompared < 0)
break;
static int DO_RANDPROJ
execute random projection move to given horizon
Definition: drwnNNGraph.h:315
bool local(drwnNNGraph &graph, const drwnNNGraphNodeIndex &u, const DistanceMetric &M)
local neighbourhood search around current match for superpixel u (returns true if a better match was ...
Definition: drwnNNGraphMoves.h:557
Implements a pool of threads for running concurrent jobs.
Definition: drwnThreadPool.h:76
uint16_t imgIndx
image index for this node
Definition: drwnNNGraph.h:47
Interface for a thread job functor.
Definition: drwnThreadPool.h:45
uint16_t segId
superpixel identifier this node
Definition: drwnNNGraph.h:48
void finish(bool bShowStatus=false)
finish the jobs in the queue and stop
Definition: drwnThreadPool.cpp:210
set< unsigned > _imgIndxes
indexes of images for this job
Definition: drwnNNGraphThreadedMoves.h:75
bool exhaustive(drwnNNGraph &graph, const drwnNNGraphNodeIndex &u, const DistanceMetric &M)
exhaustive search for best match across entire graph — use sparingly (returns true if a better match ...
Definition: drwnNNGraphMoves.h:745
void operator()()
thread functor called by drwnThreadPool with the appropriate threadId
Definition: drwnNNGraphThreadedMoves.h:83
Definition: drwnNNGraph.h:45
Implements the scoring functions needed by the search moves. Required member functions are isMatchabl...
Definition: drwnNNGraphMoves.h:24
static unsigned MAX_THREADS
maximum number of threads allowed
Definition: drwnThreadPool.h:80
bool enrichment(drwnNNGraph &graph, const DistanceMetric &M)
enrichment: inverse (from target to source) and forward (from source to target's target) (returns tru...
Definition: drwnNNGraphThreadedMoves.h:432
void operator()()
thread functor called by drwnThreadPool with the appropriate threadId
Definition: drwnNNGraphThreadedMoves.h:143
const DistanceMetric & _M
distance metric to use during moves
Definition: drwnNNGraphThreadedMoves.h:74
const DistanceMetric & _M
distance metric to use during moves
Definition: drwnNNGraphThreadedMoves.h:114
bool propagate(drwnNNGraph &graph, const drwnNNGraphNodeIndex &u, const DistanceMetric &M)
propagate good matches from supeprixel u to its neighbours (returns true if a better match was found)...
Definition: drwnNNGraphMoves.h:474
static bool DO_PROPAGATE
execute propagate move
Definition: drwnNNGraph.h:312
static bool DO_SEARCH
execute random search move
Definition: drwnNNGraph.h:314
void start()
prepare the thread pool to take jobs
Definition: drwnThreadPool.cpp:151
bool search(drwnNNGraph &graph, const drwnNNGraphNodeIndex &u, const DistanceMetric &M)
random search across all images for superpixel u (returns true if a better match was found) ...
Definition: drwnNNGraphMoves.h:521
void operator()()
thread functor called by drwnThreadPool with the appropriate threadId
Definition: drwnNNGraphThreadedMoves.h:123
set< drwnNNGraphNodeIndex > _nodeIndxes
indexes of nodes for this job
Definition: drwnNNGraphThreadedMoves.h:135
set< unsigned > _imgIndxes
indexes of images for this job
Definition: drwnNNGraphThreadedMoves.h:95
static unsigned int K
default number of matches per node
Definition: drwnNNGraph.h:311
void addJob(drwnThreadJob *job)
add a job to the queue
Definition: drwnThreadPool.cpp:179
double rescore(drwnNNGraph &graph, const DistanceMetric &M)
rescore all matches based on current features (which may have changed since graph was created) ...
Definition: drwnNNGraphThreadedMoves.h:186
void update(drwnNNGraph &graph, const DistanceMetric &M)
perform one update iteration (including enrichment and exhaustive) on all active images ...
Definition: drwnNNGraphThreadedMoves.h:218
size_t numNodes() const
number of nodes (superpixels) in the graph
Definition: drwnNNGraph.cpp:814
bool inSameEqvClass(unsigned imgIndxA, unsigned imgIndxB) const
return true if two images are in the same equivalence class
Definition: drwnNNGraph.h:367
drwnNNGraph & _graph
graph for updating (includes features)
Definition: drwnNNGraphThreadedMoves.h:96
const DistanceMetric & _M
distance metric to use during moves
Definition: drwnNNGraphThreadedMoves.h:94
threading rescore functor
Definition: drwnNNGraphThreadedMoves.h:92
threading exhaustive functor
Definition: drwnNNGraphThreadedMoves.h:132
pair< double, double > energy() const
sum of all edge weights (first) and best edge weights (second)
Definition: drwnNNGraph.cpp:882
size_t numImages() const
number of images in the graph
Definition: drwnNNGraph.h:343
Encapsulates an outgoing edge in a drwnNNGraph.
Definition: drwnNNGraph.h:82
drwnNNGraph & _graph
graph for updating (includes features)
Definition: drwnNNGraphThreadedMoves.h:76
void updateImage(drwnNNGraph &graph, unsigned imgIndx, const DistanceMetric &M)
perform single update iteration of propagate, local and search moves on a specific image ...
Definition: drwnNNGraphThreadedMoves.h:333
drwnNNGraph & _graph
graph for updating (includes features)
Definition: drwnNNGraphThreadedMoves.h:116
static int DO_EXHAUSTIVE
execute n exhaustive search moves per iteration
Definition: drwnNNGraph.h:317
const DistanceMetric & _M
distance metric to use during moves
Definition: drwnNNGraphThreadedMoves.h:134
static bool DO_LOCAL
execute local move
Definition: drwnNNGraph.h:313
void operator()()
thread functor called by drwnThreadPool with the appropriate threadId
Definition: drwnNNGraphThreadedMoves.h:103
double rescore(drwnNNGraph &graph, const DistanceMetric &M)
rescore all matches based on current features (which may have changed since graph was created) ...
Definition: drwnNNGraphMoves.h:283
set< unsigned > _imgIndxes
indexes of images for this job
Definition: drwnNNGraphThreadedMoves.h:115
threading initialize functor
Definition: drwnNNGraphThreadedMoves.h:72
static bool DO_ENRICHMENT
execute enrichment moves
Definition: drwnNNGraph.h:316
void initialize(drwnNNGraph &graph, const DistanceMetric &M)
randomly initialize edges (matched) for all active images (keeps existing matches unless an improveme...
Definition: drwnNNGraphThreadedMoves.h:154
Class for maintaining a nearest neighbour graph over superpixel images. Search moves are implemented ...
Definition: drwnNNGraph.h:309
drwnNNGraph & _graph
graph for updating (includes features)
Definition: drwnNNGraphThreadedMoves.h:136
void initialize(drwnNNGraph &graph, const DistanceMetric &M)
randomly initialize edges (matched) for all active images (keeps existing matches unless an improveme...
Definition: drwnNNGraphMoves.h:159
bool randproj(drwnNNGraph &graph, const DistanceMetric &M)
random projection moves that project all superpixels onto a random direction, sort and compare adjace...
Definition: drwnNNGraphThreadedMoves.h:351
threading update functor
Definition: drwnNNGraphThreadedMoves.h:112