sustaining_gazes/lib/3rdParty/dlib/include/dlib/test/graph_cuts.cpp

1218 lines
37 KiB
C++

// Copyright (C) 2012 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#include <sstream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <dlib/graph_cuts.h>
#include <dlib/graph_utils.h>
#include <dlib/directed_graph.h>
#include <dlib/graph.h>
#include <dlib/rand.h>
#include <dlib/hash.h>
#include <dlib/image_transforms.h>
#include "tester.h"
namespace
{
using namespace test;
using namespace dlib;
using namespace std;
logger dlog("test.graph_cuts");
// ----------------------------------------------------------------------------------------
class dense_potts_problem
{
public:
typedef double value_type;
private:
matrix<value_type,0,1> factors1;
matrix<value_type> factors2;
matrix<node_label,0,1> labels;
public:
dense_potts_problem (
unsigned long num_nodes,
dlib::rand& rnd
)
{
factors1 = -7*(randm(num_nodes, 1, rnd)-0.5);
factors2 = make_symmetric(randm(num_nodes, num_nodes, rnd) > 0.5);
labels.set_size(num_nodes);
labels = FREE_NODE;
}
unsigned long number_of_nodes (
) const { return factors1.nr(); }
unsigned long number_of_neighbors (
unsigned long // idx
) const { return number_of_nodes()-1; }
unsigned long get_neighbor_idx (
unsigned long node_id1,
unsigned long node_id2
) const
{
if (node_id2 < node_id1)
return node_id2;
else
return node_id2-1;
}
unsigned long get_neighbor (
unsigned long node_id,
unsigned long idx
) const
{
DLIB_TEST(node_id < number_of_nodes());
DLIB_TEST(idx < number_of_neighbors(node_id));
if (idx < node_id)
return idx;
else
return idx+1;
}
void set_label (
const unsigned long& idx,
node_label value
)
{
labels(idx) = value;
}
node_label get_label (
const unsigned long& idx
) const
{
return labels(idx);
}
value_type factor_value (unsigned long idx) const
{
DLIB_TEST(idx < number_of_nodes());
return factors1(idx);
}
value_type factor_value_disagreement (unsigned long idx1, unsigned long idx2) const
{
DLIB_TEST(idx1 != idx2);
DLIB_TEST(idx1 < number_of_nodes());
DLIB_TEST(idx2 < number_of_nodes());
DLIB_TEST(get_neighbor_idx(idx1,idx2) < number_of_neighbors(idx1));
DLIB_TEST(get_neighbor_idx(idx2,idx1) < number_of_neighbors(idx2));
return factors2(idx1, idx2);
}
};
// ----------------------------------------------------------------------------------------
class image_potts_problem
{
public:
typedef double value_type;
const static unsigned long max_number_of_neighbors = 4;
private:
matrix<value_type,0,1> factors1;
matrix<value_type> factors2;
matrix<node_label,0,1> labels;
long nr;
long nc;
rectangle rect, inner_rect;
mutable long count;
public:
image_potts_problem (
long nr_,
long nc_,
dlib::rand& rnd
) : nr(nr_), nc(nc_)
{
rect = rectangle(0,0,nc-1,nr-1);
inner_rect = shrink_rect(rect,1);
const unsigned long num_nodes = nr*nc;
factors1 = -7*(randm(num_nodes, 1, rnd));
factors2 = randm(num_nodes, 4, rnd) > 0.5;
//factors1 = 0;
//set_rowm(factors1, range(0, factors1.nr()/2)) = -1;
labels.set_size(num_nodes);
labels = FREE_NODE;
count = 0;
}
~image_potts_problem()
{
dlog << LTRACE << "interface calls: " << count;
dlog << LTRACE << "labels hash: "<< murmur_hash3_128bit(&labels(0), labels.size()*sizeof(labels(0)), 0).first;
}
unsigned long number_of_nodes (
) const { return factors1.nr(); }
unsigned long number_of_neighbors (
unsigned long idx
) const
{
++count;
const point& p = get_loc(idx);
if (inner_rect.contains(p))
return 4;
else if (p == rect.tl_corner() ||
p == rect.bl_corner() ||
p == rect.tr_corner() ||
p == rect.br_corner() )
return 2;
else
return 3;
}
unsigned long get_neighbor_idx (
long node_id1,
long node_id2
) const
{
++count;
const point& p = get_loc(node_id1);
long ret = 0;
if (rect.contains(p + point(1,0)))
{
if (node_id2-node_id1 == 1)
return ret;
++ret;
}
if (rect.contains(p - point(1,0)))
{
if (node_id2-node_id1 == -1)
return ret;
++ret;
}
if (rect.contains(p + point(0,1)))
{
if (node_id2-node_id1 == nc)
return ret;
++ret;
}
return ret;
}
unsigned long get_neighbor (
long node_id,
long idx
) const
{
++count;
const point& p = get_loc(node_id);
if (rect.contains(p + point(1,0)))
{
if (idx == 0)
return node_id+1;
--idx;
}
if (rect.contains(p - point(1,0)))
{
if (idx == 0)
return node_id-1;
--idx;
}
if (rect.contains(p + point(0,1)))
{
if (idx == 0)
return node_id+nc;
--idx;
}
return node_id-nc;
}
void set_label (
const unsigned long& idx,
node_label value
)
{
++count;
labels(idx) = value;
}
node_label get_label (
const unsigned long& idx
) const
{
++count;
return labels(idx);
}
value_type factor_value (unsigned long idx) const
{
++count;
DLIB_TEST(idx < (unsigned long)number_of_nodes());
return factors1(idx);
}
value_type factor_value_disagreement (unsigned long idx1, unsigned long idx2) const
{
++count;
DLIB_TEST(idx1 != idx2);
DLIB_TEST(idx1 < (unsigned long)number_of_nodes());
DLIB_TEST(idx2 < (unsigned long)number_of_nodes());
// make this function symmetric
if (idx1 > idx2)
swap(idx1,idx2);
DLIB_TEST(get_neighbor(idx1, get_neighbor_idx(idx1, idx2)) == idx2);
DLIB_TEST(get_neighbor(idx2, get_neighbor_idx(idx2, idx1)) == idx1);
// the neighbor relationship better be symmetric
DLIB_TEST(get_neighbor_idx(idx1,idx2) < number_of_neighbors(idx1));
DLIB_TEST_MSG(get_neighbor_idx(idx2,idx1) < number_of_neighbors(idx2),
"\n idx1: "<< idx1 <<
"\n idx2: "<< idx2 <<
"\n get_neighbor_idx(idx2,idx1): "<< get_neighbor_idx(idx2,idx1) <<
"\n number_of_neighbors(idx2): " << number_of_neighbors(idx2) <<
"\n nr: "<< nr <<
"\n nc: "<< nc
);
return factors2(idx1, get_neighbor_idx(idx1,idx2));
}
private:
point get_loc (
const unsigned long& idx
) const
{
return point(idx%nc, idx/nc);
}
};
// ----------------------------------------------------------------------------------------
template <typename potts_model>
void brute_force_potts_model (
potts_model& g
)
{
potts_model m(g);
const unsigned long num = (unsigned long)std::pow(2.0, (double)m.number_of_nodes());
double best_score = -std::numeric_limits<double>::infinity();
for (unsigned long i = 0; i < num; ++i)
{
for (unsigned long j = 0; j < m.number_of_nodes(); ++j)
{
unsigned long T = (1)<<j;
T = (T&i);
if (T != 0)
m.set_label(j,SINK_CUT);
else
m.set_label(j,SOURCE_CUT);
}
double score = potts_model_score(m);
if (score > best_score)
{
best_score = score;
g = m;
}
}
}
// ----------------------------------------------------------------------------------------
template <typename graph_type>
void brute_force_potts_model_on_graph (
const graph_type& g,
std::vector<node_label>& labels_
)
{
std::vector<node_label> labels;
labels.resize(g.number_of_nodes());
const unsigned long num = (unsigned long)std::pow(2.0, (double)g.number_of_nodes());
double best_score = -std::numeric_limits<double>::infinity();
for (unsigned long i = 0; i < num; ++i)
{
for (unsigned long j = 0; j < g.number_of_nodes(); ++j)
{
unsigned long T = (1)<<j;
T = (T&i);
if (T != 0)
labels[j] = SINK_CUT;
else
labels[j] = SOURCE_CUT;
}
double score = potts_model_score(g,labels);
if (score > best_score)
{
best_score = score;
labels_ = labels;
}
}
}
// ----------------------------------------------------------------------------------------
template <typename graph_type>
void make_random_undirected_graph(
dlib::rand& rnd,
graph_type& g
)
{
typedef typename graph_type::edge_type edge_weight_type;
g.clear();
const unsigned int num_nodes = rnd.get_random_32bit_number()%8;
g.set_number_of_nodes(num_nodes);
const unsigned int num_edges = static_cast<unsigned int>(num_nodes*(num_nodes-1)/2*rnd.get_random_double() + 0.5);
// add the right number of randomly selected edges
unsigned int count = 0;
while (count < num_edges)
{
unsigned long i = rnd.get_random_32bit_number()%g.number_of_nodes();
unsigned long j = rnd.get_random_32bit_number()%g.number_of_nodes();
if (i != j && g.has_edge(i, j) == false)
{
++count;
g.add_edge(i, j);
edge(g, i, j) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
}
}
for (unsigned long i = 0; i < g.number_of_nodes(); ++i)
{
g.node(i).data = static_cast<edge_weight_type>(rnd.get_random_gaussian()*200);
}
}
// ----------------------------------------------------------------------------------------
void test_graph_potts_model(
dlib::rand& rnd
)
{
using namespace std;
double brute_force_score;
double graph_cut_score;
graph<double,double>::kernel_1a_c temp;
make_random_undirected_graph(rnd,temp);
{
std::vector<node_label> labels;
brute_force_potts_model_on_graph(temp, labels);
for (unsigned long i = 0; i < temp.number_of_nodes(); ++i)
{
dlog << LTRACE << "node " << i << ": "<< (int)labels[i];
}
brute_force_score = potts_model_score(temp, labels);
dlog << LTRACE << "brute force score: "<< brute_force_score;
}
dlog << LTRACE << "******************";
{
std::vector<node_label> labels;
find_max_factor_graph_potts(temp, labels);
DLIB_TEST(temp.number_of_nodes() == labels.size());
for (unsigned long i = 0; i < temp.number_of_nodes(); ++i)
{
dlog << LTRACE << "node " << i << ": "<< (int)labels[i];
}
graph_cut_score = potts_model_score(temp, labels);
dlog << LTRACE << "graph cut score: "<< graph_cut_score;
}
DLIB_TEST_MSG(graph_cut_score == brute_force_score, std::abs(graph_cut_score - brute_force_score));
dlog << LTRACE << "##################";
dlog << LTRACE << "##################";
dlog << LTRACE << "##################";
}
// ----------------------------------------------------------------------------------------
template <typename potts_prob>
void impl_test_potts_model (
potts_prob& p
)
{
using namespace std;
double brute_force_score;
double graph_cut_score;
{
potts_prob temp(p);
brute_force_potts_model(temp);
for (unsigned long i = 0; i < temp.number_of_nodes(); ++i)
{
dlog << LTRACE << "node " << i << ": "<< (int)temp.get_label(i);
}
brute_force_score = potts_model_score(temp);
dlog << LTRACE << "brute force score: "<< brute_force_score;
}
dlog << LTRACE << "******************";
{
potts_prob temp(p);
find_max_factor_graph_potts(temp);
for (unsigned long i = 0; i < temp.number_of_nodes(); ++i)
{
dlog << LTRACE << "node " << i << ": "<< (int)temp.get_label(i);
}
graph_cut_score = potts_model_score(temp);
dlog << LTRACE << "graph cut score: "<< graph_cut_score;
}
DLIB_TEST_MSG(graph_cut_score == brute_force_score, std::abs(graph_cut_score - brute_force_score));
dlog << LTRACE << "##################";
dlog << LTRACE << "##################";
dlog << LTRACE << "##################";
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// BASIC MIN CUT STUFF
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename directed_graph>
void brute_force_min_cut (
directed_graph& g,
unsigned long source,
unsigned long sink
)
{
typedef typename directed_graph::edge_type edge_weight_type;
const unsigned long num = (unsigned long)std::pow(2.0, (double)g.number_of_nodes());
std::vector<node_label> best_cut(g.number_of_nodes(),FREE_NODE);
edge_weight_type best_score = std::numeric_limits<edge_weight_type>::max();
for (unsigned long i = 0; i < num; ++i)
{
for (unsigned long j = 0; j < g.number_of_nodes(); ++j)
{
unsigned long T = (1)<<j;
T = (T&i);
if (T != 0)
g.node(j).data = SINK_CUT;
else
g.node(j).data = SOURCE_CUT;
}
// ignore cuts that don't label the source or sink node the way we want.
if (g.node(source).data != SOURCE_CUT ||
g.node(sink).data != SINK_CUT)
continue;
edge_weight_type score = graph_cut_score(g);
if (score < best_score)
{
best_score = score;
for (unsigned long j = 0; j < g.number_of_nodes(); ++j)
best_cut[j] = g.node(j).data;
}
}
for (unsigned long j = 0; j < g.number_of_nodes(); ++j)
g.node(j).data = best_cut[j];
}
// ----------------------------------------------------------------------------------------
template <typename directed_graph>
void print_graph(
const directed_graph& g
)
{
using namespace std;
dlog << LTRACE << "number of nodes: "<< g.number_of_nodes();
for (unsigned long i = 0; i < g.number_of_nodes(); ++i)
{
for (unsigned long n = 0; n < g.node(i).number_of_children(); ++n)
dlog << LTRACE << i << " -(" << g.node(i).child_edge(n) << ")-> " << g.node(i).child(n).index();
}
}
template <typename directed_graph>
void copy_edge_weights (
directed_graph& dest,
const directed_graph& src
)
{
for (unsigned long i = 0; i < src.number_of_nodes(); ++i)
{
for (unsigned long n = 0; n < src.node(i).number_of_children(); ++n)
{
dest.node(i).child_edge(n) = src.node(i).child_edge(n);
}
}
}
// ----------------------------------------------------------------------------------------
template <typename graph_type>
void pick_random_source_and_sink (
dlib::rand& rnd,
const graph_type& g,
unsigned long& source,
unsigned long& sink
)
{
source = rnd.get_random_32bit_number()%g.number_of_nodes();
sink = rnd.get_random_32bit_number()%g.number_of_nodes();
while (sink == source)
sink = rnd.get_random_32bit_number()%g.number_of_nodes();
}
// ----------------------------------------------------------------------------------------
template <typename dgraph_type>
void make_random_graph(
dlib::rand& rnd,
dgraph_type& g,
unsigned long& source,
unsigned long& sink
)
{
typedef typename dgraph_type::edge_type edge_weight_type;
g.clear();
const unsigned int num_nodes = rnd.get_random_32bit_number()%7 + 2;
g.set_number_of_nodes(num_nodes);
const unsigned int num_edges = static_cast<unsigned int>(num_nodes*(num_nodes-1)/2*rnd.get_random_double() + 0.5);
// add the right number of randomly selected edges
unsigned int count = 0;
while (count < num_edges)
{
unsigned long parent = rnd.get_random_32bit_number()%g.number_of_nodes();
unsigned long child = rnd.get_random_32bit_number()%g.number_of_nodes();
if (parent != child && g.has_edge(parent, child) == false)
{
++count;
g.add_edge(parent, child);
edge(g, parent, child) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
// have to have edges both ways
swap(parent, child);
g.add_edge(parent, child);
edge(g, parent, child) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
}
}
pick_random_source_and_sink(rnd, g, source, sink);
}
// ----------------------------------------------------------------------------------------
template <typename dgraph_type>
void make_random_chain_graph(
dlib::rand& rnd,
dgraph_type& g,
unsigned long& source,
unsigned long& sink
)
{
typedef typename dgraph_type::edge_type edge_weight_type;
g.clear();
const unsigned int num_nodes = rnd.get_random_32bit_number()%7 + 2;
g.set_number_of_nodes(num_nodes);
for (unsigned long i = 1; i < g.number_of_nodes(); ++i)
{
g.add_edge(i,i-1);
g.add_edge(i-1,i);
edge(g, i, i-1) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
edge(g, i-1, i) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
}
pick_random_source_and_sink(rnd, g, source, sink);
}
// ----------------------------------------------------------------------------------------
template <typename dgraph_type>
void make_random_grid_graph(
dlib::rand& rnd,
dgraph_type& g,
unsigned long& source,
unsigned long& sink
)
/*!
ensures
- makes a grid graph like the kind used for potts models.
!*/
{
typedef typename dgraph_type::edge_type edge_weight_type;
g.clear();
const long nr = rnd.get_random_32bit_number()%2 + 2;
const long nc = rnd.get_random_32bit_number()%2 + 2;
g.set_number_of_nodes(nr*nc+2);
const rectangle rect(0,0,nc-1,nr-1);
for (long r = 0; r < nr; ++r)
{
for (long c = 0; c < nc; ++c)
{
const point p(c,r);
const unsigned long i = p.y()*nc + p.x();
const point n2(c-1,r);
if (rect.contains(n2))
{
const unsigned long j = n2.y()*nc + n2.x();
g.add_edge(i,j);
g.add_edge(j,i);
edge(g,i,j) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
edge(g,j,i) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
}
const point n4(c,r-1);
if (rect.contains(n4))
{
const unsigned long j = n4.y()*nc + n4.x();
g.add_edge(i,j);
g.add_edge(j,i);
edge(g,i,j) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
edge(g,j,i) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
}
}
}
// use the last two nodes as source and sink. Also connect them to all the other nodes.
source = g.number_of_nodes()-1;
sink = g.number_of_nodes()-2;
for (unsigned long i = 0; i < g.number_of_nodes()-2; ++i)
{
g.add_edge(i,source);
g.add_edge(source,i);
g.add_edge(i,sink);
g.add_edge(sink,i);
edge(g,i,source) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
edge(g,source,i) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
edge(g,i,sink) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
edge(g,sink,i) = static_cast<edge_weight_type>(rnd.get_random_double()*50);
}
}
// ----------------------------------------------------------------------------------------
template <typename min_cut, typename dgraph_type>
void run_test_on_graphs (
const min_cut& mc,
dgraph_type& g1,
dgraph_type& g2,
unsigned long source,
unsigned long sink
)
{
typedef typename dgraph_type::edge_type edge_weight_type;
using namespace std;
dlog << LTRACE << "number of nodes: "<< g1.number_of_nodes();
dlog << LTRACE << "is graph connected: "<< graph_is_connected(g1);
dlog << LTRACE << "has self loops: "<< graph_contains_length_one_cycle(g1);
dlog << LTRACE << "SOURCE_CUT: " << source;
dlog << LTRACE << "SINK_CUT: " << sink;
mc(g1, source, sink);
brute_force_min_cut(g2, source, sink);
print_graph(g1);
// make sure the flow residuals are 0 at the cut locations
for (unsigned long i = 0; i < g1.number_of_nodes(); ++i)
{
for (unsigned long j = 0; j < g1.node(i).number_of_children(); ++j)
{
if ((g1.node(i).data == SOURCE_CUT && g1.node(i).child(j).data != SOURCE_CUT) ||
(g1.node(i).data != SINK_CUT && g1.node(i).child(j).data == SINK_CUT)
)
{
DLIB_TEST_MSG(g1.node(i).child_edge(j) == 0, g1.node(i).child_edge(j));
}
}
}
// copy the edge weights from g2 back to g1 so we can compute cut scores
copy_edge_weights(g1, g2);
DLIB_TEST(g1.number_of_nodes() == g2.number_of_nodes());
for (unsigned long i = 0; i < g1.number_of_nodes(); ++i)
{
dlog << LTRACE << "node " << i << ": " << (int)g1.node(i).data << ", " << (int)g2.node(i).data;
if (g1.node(i).data != g2.node(i).data)
{
edge_weight_type cut_score = graph_cut_score(g1);
edge_weight_type brute_force_score = graph_cut_score(g2);
dlog << LTRACE << "graph cut score: "<< cut_score;
dlog << LTRACE << "brute force score: "<< brute_force_score;
if (brute_force_score != cut_score)
print_graph(g1);
DLIB_TEST_MSG(brute_force_score == cut_score,std::abs(brute_force_score-cut_score));
}
}
}
// ----------------------------------------------------------------------------------------
template <typename min_cut, typename edge_weight_type>
void test_graph_cuts(dlib::rand& rnd)
{
typedef typename dlib::directed_graph<node_label, edge_weight_type>::kernel_1a_c dgraph_type;
// we will create two identical graphs.
dgraph_type g1, g2;
min_cut mc;
unsigned long source, sink;
dlib::rand rnd_copy(rnd);
make_random_graph(rnd,g1, source, sink);
make_random_graph(rnd_copy,g2, source, sink);
run_test_on_graphs(mc, g1, g2, source, sink);
rnd_copy = rnd;
make_random_grid_graph(rnd,g1, source, sink);
make_random_grid_graph(rnd_copy,g2, source, sink);
run_test_on_graphs(mc, g1, g2, source, sink);
rnd_copy = rnd;
make_random_chain_graph(rnd,g1, source, sink);
make_random_chain_graph(rnd_copy,g2, source, sink);
run_test_on_graphs(mc, g1, g2, source, sink);
}
// ----------------------------------------------------------------------------------------
class test_potts_grid_problem
{
public:
test_potts_grid_problem(int seed_) :seed(seed_){}
int seed;
long nr() const { return 3;}
long nc() const { return 3;}
typedef double value_type;
value_type factor_value(unsigned long idx) const
{
// Copy idx into a char buffer to avoid warnings about violation of strict aliasing
// rules when murmur_hash3() gets inlined into this function.
char buf[sizeof(idx)];
memcpy(buf,&idx,sizeof(idx));
// now hash the buffer rather than idx.
return ((double)murmur_hash3(buf, sizeof(buf), seed) - std::numeric_limits<uint32>::max()/2.0)/1000.0;
}
value_type factor_value_disagreement(unsigned long idx1, unsigned long idx2) const
{
return std::abs(factor_value(idx1+idx2)/10.0);
}
};
// ----------------------------------------------------------------------------------------
template <typename prob_type>
void brute_force_potts_grid_problem(
const prob_type& prob,
array2d<unsigned char>& labels
)
{
const unsigned long num = (unsigned long)std::pow(2.0, (double)prob.nr()*prob.nc());
array2d<unsigned char> temp(prob.nr(), prob.nc());
unsigned char* data = &temp[0][0];
double best_score = -std::numeric_limits<double>::infinity();
for (unsigned long i = 0; i < num; ++i)
{
for (unsigned long j = 0; j < temp.size(); ++j)
{
unsigned long T = (1)<<j;
T = (T&i);
if (T != 0)
*(data + j) = SINK_CUT;
else
*(data + j) = SOURCE_CUT;
}
double score = potts_model_score(prob, temp);
if (score > best_score)
{
best_score = score;
assign_image(labels, temp);
}
}
}
void test_inf()
{
graph<double,double>::kernel_1a_c g;
g.set_number_of_nodes(4);
g.add_edge(0,1);
g.add_edge(1,2);
g.add_edge(2,3);
g.add_edge(3,0);
g.node(0).data = std::numeric_limits<double>::infinity();
g.node(1).data = -std::numeric_limits<double>::infinity();
g.node(2).data = std::numeric_limits<double>::infinity();
g.node(3).data = -std::numeric_limits<double>::infinity();
edge(g,0,1) = 1;
edge(g,1,2) = 1;
edge(g,2,3) = 1;
edge(g,3,0) = 1;
std::vector<node_label> labels;
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] != 0);
DLIB_TEST(labels[1] == 0);
DLIB_TEST(labels[2] != 0);
DLIB_TEST(labels[3] == 0);
// --------------------------
g.node(0).data = std::numeric_limits<double>::infinity();
g.node(1).data = 0;
g.node(2).data = 0;
g.node(3).data = -3;
edge(g,0,1) = 1;
edge(g,1,2) = 1;
edge(g,2,3) = 1;
edge(g,3,0) = 1;
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] != 0);
DLIB_TEST(labels[1] != 0);
DLIB_TEST(labels[2] != 0);
DLIB_TEST(labels[3] == 0);
// --------------------------
g.node(0).data = std::numeric_limits<double>::infinity();
g.node(1).data = 0;
g.node(2).data = 0;
g.node(3).data = -0.1;
edge(g,0,1) = 1;
edge(g,1,2) = 1;
edge(g,2,3) = 1;
edge(g,3,0) = 1;
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] != 0);
DLIB_TEST(labels[1] != 0);
DLIB_TEST(labels[2] != 0);
DLIB_TEST(labels[3] != 0);
// --------------------------
g.node(0).data = std::numeric_limits<double>::infinity();
g.node(1).data = 0;
g.node(2).data = 0;
g.node(3).data = -0.1;
edge(g,0,1) = 1;
edge(g,1,2) = 1;
edge(g,2,3) = 0;
edge(g,3,0) = 0;
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] != 0);
DLIB_TEST(labels[1] != 0);
DLIB_TEST(labels[2] != 0);
DLIB_TEST(labels[3] == 0);
// --------------------------
g.node(0).data = -std::numeric_limits<double>::infinity();
g.node(1).data = 0;
g.node(2).data = 0;
g.node(3).data = 0.1;
edge(g,0,1) = 1;
edge(g,1,2) = 1;
edge(g,2,3) = 0;
edge(g,3,0) = 0;
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] == 0);
DLIB_TEST(labels[1] == 0);
DLIB_TEST(labels[2] == 0);
DLIB_TEST(labels[3] != 0);
// --------------------------
g.node(0).data = -std::numeric_limits<double>::infinity();
g.node(1).data = std::numeric_limits<double>::infinity();
g.node(2).data = 0;
g.node(3).data = 0.1;
edge(g,0,1) = 1;
edge(g,1,2) = 1;
edge(g,2,3) = 0;
edge(g,3,0) = 0;
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] == 0);
DLIB_TEST(labels[1] != 0);
DLIB_TEST(labels[2] != 0);
DLIB_TEST(labels[3] != 0);
// --------------------------
g.node(0).data = -10;
g.node(1).data = std::numeric_limits<double>::infinity();
g.node(2).data = 0;
g.node(3).data = 0.1;
edge(g,0,1) = std::numeric_limits<double>::infinity();
edge(g,1,2) = std::numeric_limits<double>::infinity();
edge(g,2,3) = std::numeric_limits<double>::infinity();
edge(g,3,0) = std::numeric_limits<double>::infinity();
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] != 0);
DLIB_TEST(labels[1] != 0);
DLIB_TEST(labels[2] != 0);
DLIB_TEST(labels[3] != 0);
// --------------------------
g.node(0).data = 10;
g.node(1).data = -std::numeric_limits<double>::infinity();
g.node(2).data = 20.05;
g.node(3).data = -0.1;
edge(g,0,1) = std::numeric_limits<double>::infinity();
edge(g,1,2) = 10;
edge(g,2,3) = std::numeric_limits<double>::infinity();
edge(g,3,0) = 10;
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] == 0);
DLIB_TEST(labels[1] == 0);
DLIB_TEST(labels[2] == 0);
DLIB_TEST(labels[3] == 0);
// --------------------------
g.node(0).data = 10;
g.node(1).data = -std::numeric_limits<double>::infinity();
g.node(2).data = 20.2;
g.node(3).data = -0.1;
edge(g,0,1) = std::numeric_limits<double>::infinity();
edge(g,1,2) = 10;
edge(g,2,3) = std::numeric_limits<double>::infinity();
edge(g,3,0) = 10;
find_max_factor_graph_potts(g, labels);
DLIB_TEST(labels[0] == 0);
DLIB_TEST(labels[1] == 0);
DLIB_TEST(labels[2] != 0);
DLIB_TEST(labels[3] != 0);
}
struct potts_pair_image_model
{
typedef double value_type;
template <typename pixel_type1, typename pixel_type2>
value_type factor_value (
const pixel_type1& ,
const pixel_type2& v2
) const
{
return v2;
}
template <typename pixel_type>
value_type factor_value_disagreement (
const pixel_type& v1,
const pixel_type& v2
) const
{
if (v1 == v2)
return 10;
else
return 0;
}
};
void test_potts_pair_grid()
{
array2d<int> img1(40,40);
array2d<double> img2(40,40);
assign_all_pixels(img1, -1);
assign_all_pixels(img2, -1);
img1[4][4] = 1000;
img2[4][3] = 1;
img2[4][4] = 1;
img2[4][5] = 1;
img2[3][3] = 1;
img2[3][4] = 1;
img2[3][5] = 1;
img2[5][3] = 1;
img2[5][4] = 1;
img2[5][5] = 1;
array2d<unsigned char> labels;
find_max_factor_graph_potts(make_potts_grid_problem(potts_pair_image_model(),img2,img1), labels);
dlog << LINFO << "num true labels: " << sum(matrix_cast<int>(mat(labels)!=0));
DLIB_TEST(sum(matrix_cast<int>(mat(labels)!=0)) == 9);
DLIB_TEST(sum(matrix_cast<int>(mat(labels)==0)) == (int)img1.size()-9);
DLIB_TEST(labels[4][3] != 0);
DLIB_TEST(labels[4][4] != 0);
DLIB_TEST(labels[4][5] != 0);
DLIB_TEST(labels[3][3] != 0);
DLIB_TEST(labels[3][4] != 0);
DLIB_TEST(labels[3][5] != 0);
DLIB_TEST(labels[5][3] != 0);
DLIB_TEST(labels[5][4] != 0);
DLIB_TEST(labels[5][5] != 0);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class graph_cuts_tester : public tester
{
public:
graph_cuts_tester (
) :
tester ("test_graph_cuts",
"Runs tests on the graph cuts tools.")
{}
dlib::rand rnd;
void perform_test (
)
{
test_potts_pair_grid();
test_inf();
for (int i = 0; i < 500; ++i)
{
array2d<unsigned char> labels, brute_labels;
test_potts_grid_problem prob(i);
find_max_factor_graph_potts(prob, labels);
brute_force_potts_grid_problem(prob, brute_labels);
DLIB_TEST(labels.nr() == brute_labels.nr());
DLIB_TEST(labels.nc() == brute_labels.nc());
for (long r = 0; r < labels.nr(); ++r)
{
for (long c = 0; c < labels.nc(); ++c)
{
bool normal = (labels[r][c] != 0);
bool brute = (brute_labels[r][c] != 0);
DLIB_TEST(normal == brute);
}
}
}
for (int i = 0; i < 1000; ++i)
{
print_spinner();
dlog << LTRACE << "test_grpah_cuts<short> iter: " << i;
test_graph_cuts<min_cut,short>(rnd);
print_spinner();
dlog << LTRACE << "test_grpah_cuts<double> iter: " << i;
test_graph_cuts<min_cut,double>(rnd);
}
for (int k = 0; k < 300; ++k)
{
dlog << LTRACE << "image_potts_problem iter " << k;
print_spinner();
image_potts_problem p(3,3, rnd);
impl_test_potts_model(p);
}
for (int k = 0; k < 300; ++k)
{
dlog << LTRACE << "dense_potts_problem iter " << k;
print_spinner();
dense_potts_problem p(6, rnd);
impl_test_potts_model(p);
}
for (int k = 0; k < 300; ++k)
{
dlog << LTRACE << "dense_potts_problem iter " << k;
print_spinner();
test_graph_potts_model(rnd);
}
}
} a;
}