summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/graph_cuts/find_max_factor_graph_potts_abstract.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/graph_cuts/find_max_factor_graph_potts_abstract.h')
-rw-r--r--ml/dlib/dlib/graph_cuts/find_max_factor_graph_potts_abstract.h636
1 files changed, 636 insertions, 0 deletions
diff --git a/ml/dlib/dlib/graph_cuts/find_max_factor_graph_potts_abstract.h b/ml/dlib/dlib/graph_cuts/find_max_factor_graph_potts_abstract.h
new file mode 100644
index 000000000..69aa59256
--- /dev/null
+++ b/ml/dlib/dlib/graph_cuts/find_max_factor_graph_potts_abstract.h
@@ -0,0 +1,636 @@
+// Copyright (C) 2012 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#undef DLIB_FIND_MAX_FACTOR_GRAPH_PoTTS_ABSTRACT_Hh_
+#ifdef DLIB_FIND_MAX_FACTOR_GRAPH_PoTTS_ABSTRACT_Hh_
+
+#include "../matrix.h"
+#include "min_cut_abstract.h"
+#include "../graph_utils.h"
+#include "../array2d/array2d_kernel_abstract.h"
+
+namespace dlib
+{
+
+// ----------------------------------------------------------------------------------------
+
+ class potts_problem
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This object represents a boolean valued factor graph or graphical model
+ that can be efficiently operated on using graph cuts. In particular, this
+ object defines the interface a MAP problem on a factor graph must
+ implement if it is to be solved using the find_max_factor_graph_potts()
+ routine defined at the bottom of this file.
+
+ Note that there is no dlib::potts_problem object. What you are looking
+ at here is simply the interface definition for a Potts problem. You must
+ implement your own version of this object for the problem you wish to
+ solve and then pass it to the find_max_factor_graph_potts() routine.
+
+ Note also that a factor graph should not have any nodes which are
+ neighbors with themselves. Additionally, the graph is undirected. This
+ mean that if A is a neighbor of B then B must be a neighbor of A for
+ the MAP problem to be valid.
+ !*/
+
+ public:
+
+ unsigned long number_of_nodes (
+ ) const;
+ /*!
+ ensures
+ - returns the number of nodes in the factor graph. Or in other words,
+ returns the number of variables in the MAP problem/Potts model.
+ !*/
+
+ unsigned long number_of_neighbors (
+ unsigned long idx
+ ) const;
+ /*!
+ requires
+ - idx < number_of_nodes()
+ ensures
+ - returns the number of neighbors of node idx.
+ !*/
+
+ // This is an optional variable which specifies a number that is always
+ // greater than or equal to number_of_neighbors(idx). If you don't know
+ // the value at compile time then either don't include max_number_of_neighbors
+ // in your potts_problem object or set it to 0.
+ const static unsigned long max_number_of_neighbors = 0;
+
+ unsigned long get_neighbor (
+ unsigned long idx,
+ unsigned long n
+ ) const;
+ /*!
+ requires
+ - idx < number_of_nodes()
+ - n < number_of_neighbors(idx)
+ ensures
+ - returns the node index value of the n-th neighbor of
+ the node with index value idx.
+ - The neighbor relationship is reciprocal. That is, if
+ get_neighbor(A,i)==B then there is a value of j such
+ that get_neighbor(B,j)==A.
+ - A node is never its own neighbor. That is, there is
+ no i such that get_neighbor(idx,i)==idx.
+ !*/
+
+ unsigned long get_neighbor_idx (
+ unsigned long idx1,
+ unsigned long idx2
+ ) const;
+ /*!
+ requires
+ - idx1 < number_of_nodes()
+ - idx2 < number_of_nodes()
+ ensures
+ - This function is basically the inverse of get_neighbor().
+ - returns a number IDX such that:
+ - get_neighbor(idx1,IDX) == idx2
+ - IDX < number_of_neighbors(idx1)
+ !*/
+
+ void set_label (
+ const unsigned long& idx,
+ node_label value
+ );
+ /*!
+ requires
+ - idx < number_of_nodes()
+ ensures
+ - #get_label(idx) == value
+ !*/
+
+ node_label get_label (
+ const unsigned long& idx
+ ) const;
+ /*!
+ requires
+ - idx < number_of_nodes()
+ ensures
+ - returns the current label for the idx-th node. This is a value which is
+ 0 if the node's label is false and is any other value if it is true.
+
+ Note that this value is not used by factor_value() or factor_value_disagreement().
+ It is simply here to provide a mechanism for find_max_factor_graph_potts()
+ to return its labeled result. Additionally, the reason it returns a
+ node_label rather than a bool is because doing it this way facilitates
+ use of a graph cut algorithm for the solution of the MAP problem. For
+ more of an explanation you should read the paper referenced by the min_cut
+ object.
+ !*/
+
+ // This typedef should be for a type like int or double. It
+ // must also be capable of representing signed values.
+ typedef an_integer_or_real_type value_type;
+
+ value_type factor_value (
+ unsigned long idx
+ ) const;
+ /*!
+ requires
+ - idx < number_of_nodes()
+ ensures
+ - returns a value which indicates how "good" it is to assign the idx-th
+ node the label of true. The larger the value, the more desirable it is
+ to give it this label. Similarly, a negative value indicates that it is
+ better to give the node a label of false.
+ - It is valid for the returned value to be positive or negative infinity.
+ A value of positive infinity indicates that the idx-th node must be labeled
+ true while negative infinity means it must be labeled false.
+ !*/
+
+ value_type factor_value_disagreement (
+ unsigned long idx1,
+ unsigned long idx2
+ ) const;
+ /*!
+ requires
+ - idx1 < number_of_nodes()
+ - idx2 < number_of_nodes()
+ - idx1 != idx2
+ - the idx1-th node and idx2-th node are neighbors in the graph. That is,
+ get_neighbor(idx1,i)==idx2 for some value of i.
+ ensures
+ - returns a number >= 0. This is the penalty for giving node idx1 and idx2
+ different labels. Larger values indicate a larger penalty.
+ - this function is symmetric. That is, it is true that:
+ factor_value_disagreement(i,j) == factor_value_disagreement(j,i)
+ - It is valid for the returned value to be positive infinity. Returning
+ infinity indicates that the idx1-th and idx2-th nodes must share the same
+ label.
+ !*/
+
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ class potts_grid_problem
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This object is a specialization of a potts_problem to the case where
+ the graph is a regular grid where each node is connected to its four
+ neighbors. An example of this is an image where each pixel is a node
+ and is connected to its four immediate neighboring pixels. Therefore,
+ this object defines the interface this special kind of MAP problem
+ must implement if it is to be solved by the find_max_factor_graph_potts(potts_grid_problem,array2d)
+ routine defined at the end of this file.
+
+
+ Note that all nodes always have four neighbors, even nodes on the edge
+ of the graph. This is because these border nodes are connected to
+ the border nodes on the other side of the graph. That is, the graph
+ "wraps" around at the borders.
+ !*/
+
+ public:
+
+ // This typedef should be for a type like int or double. It
+ // must also be capable of representing signed values.
+ typedef an_integer_or_real_type value_type;
+
+ long nr(
+ ) const;
+ /*!
+ ensures
+ - returns the number of rows in the grid
+ !*/
+
+ long nc(
+ ) const;
+ /*!
+ ensures
+ - returns the number of columns in the grid
+ !*/
+
+ value_type factor_value (
+ unsigned long idx
+ ) const;
+ /*!
+ requires
+ - idx < nr()*nc()
+ ensures
+ - The grid is represented in row-major-order format. Therefore, idx
+ identifies a node according to its position in the row-major-order
+ representation of the grid graph. Or in other words, idx corresponds
+ to the following row and column location in the graph:
+ - row == idx/nc()
+ - col == idx%nc()
+ - returns a value which indicates how "good" it is to assign the idx-th
+ node the label of true. The larger the value, the more desirable it is
+ to give it this label. Similarly, a negative value indicates that it is
+ better to give the node a label of false.
+ - It is valid for the returned value to be positive or negative infinity.
+ A value of positive infinity indicates that the idx-th node must be labeled
+ true while negative infinity means it must be labeled false.
+ !*/
+
+ value_type factor_value_disagreement (
+ unsigned long idx1,
+ unsigned long idx2
+ ) const;
+ /*!
+ requires
+ - idx1 < nr()*nc()
+ - idx2 < nr()*nc()
+ - idx1 != idx2
+ - the idx1-th node and idx2-th node are neighbors in the grid graph.
+ ensures
+ - The grid is represented in row-major-order format. Therefore, idx1 and
+ idx2 identify nodes according to their positions in the row-major-order
+ representation of the grid graph. For example, idx1 corresponds
+ to the following row and column location in the graph:
+ - row == idx1/nc()
+ - col == idx1%nc()
+ - returns a number >= 0. This is the penalty for giving node idx1 and idx2
+ different labels. Larger values indicate a larger penalty.
+ - this function is symmetric. That is, it is true that:
+ factor_value_disagreement(i,j) == factor_value_disagreement(j,i)
+ - It is valid for the returned value to be positive infinity. Returning
+ infinity indicates that the idx1-th and idx2-th nodes must share the same
+ label.
+ !*/
+ };
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename potts_problem
+ >
+ typename potts_problem::value_type potts_model_score (
+ const potts_problem& prob
+ );
+ /*!
+ requires
+ - potts_problem == an object with an interface compatible with the potts_problem
+ object defined at the top of this file.
+ - for all valid i and j:
+ - prob.factor_value_disagreement(i,j) >= 0
+ - prob.factor_value_disagreement(i,j) == prob.factor_value_disagreement(j,i)
+ ensures
+ - computes the model score for the given potts_problem. We define this
+ precisely below:
+ - let L(i) == the boolean label of the i-th variable in prob. Or in other
+ words, L(i) == (prob.get_label(i) != 0).
+ - let F == the sum of values of prob.factor_value(i) for only i values
+ where L(i) == true.
+ - Let D == the sum of values of prob.factor_value_disagreement(i,j)
+ for only i and j values which meet the following conditions:
+ - i and j are neighbors in the graph defined by prob, that is,
+ it is valid to call prob.factor_value_disagreement(i,j).
+ - L(i) != L(j)
+ - i < j
+ (i.e. We want to make sure to only count the edge between i and j once)
+
+ - Then this function returns F - D
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename graph_type
+ >
+ typename graph_type::edge_type potts_model_score (
+ const graph_type& g,
+ const std::vector<node_label>& labels
+ );
+ /*!
+ requires
+ - graph_type is an implementation of dlib/graph/graph_kernel_abstract.h
+ - graph_type::edge_type is some signed type such as int or double
+ - graph_type::type must be the same type as graph_type::edge_type
+ - graph_contains_length_one_cycle(g) == false
+ - for all valid i and j:
+ - edge(g,i,j) >= 0
+ ensures
+ - This function does the same thing as the version of potts_model_score()
+ defined above, except that this version operates on a dlib::graph
+ instead of a potts_problem object.
+ - computes the model score for the given graph and labeling. We define this
+ precisely below:
+ - let L(i) == the boolean label of the i-th variable in g. Or in other
+ words, L(i) == (labels[i] != 0).
+ - let F == the sum of values of g.node(i).data for only i values
+ where L(i) == true.
+ - Let D == the sum of values of edge(g,i,j) for only i and j
+ values which meet the following conditions:
+ - i and j are neighbors in the graph defined by g, that is,
+ it is valid to call edge(g,i,j).
+ - L(i) != L(j)
+ - i < j
+ (i.e. We want to make sure to only count the edge between i and j once)
+
+ - Then this function returns F - D
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename potts_grid_problem,
+ typename mem_manager
+ >
+ typename potts_grid_problem::value_type potts_model_score (
+ const potts_grid_problem& prob,
+ const array2d<node_label,mem_manager>& labels
+ );
+ /*!
+ requires
+ - prob.nr() == labels.nr()
+ - prob.nc() == labels.nc()
+ - potts_grid_problem == an object with an interface compatible with the
+ potts_grid_problem object defined above.
+ - for all valid i and j:
+ - prob.factor_value_disagreement(i,j) >= 0
+ - prob.factor_value_disagreement(i,j) == prob.factor_value_disagreement(j,i)
+ ensures
+ - computes the model score for the given potts_grid_problem. We define this
+ precisely below:
+ - let L(i) == the boolean label of the i-th variable in prob. Or in other
+ words, L(i) == (labels[i/labels.nc()][i%labels.nc()] != 0).
+ - let F == the sum of values of prob.factor_value(i) for only i values
+ where L(i) == true.
+ - Let D == the sum of values of prob.factor_value_disagreement(i,j)
+ for only i and j values which meet the following conditions:
+ - i and j are neighbors in the graph defined by prob, that is,
+ it is valid to call prob.factor_value_disagreement(i,j).
+ - L(i) != L(j)
+ - i < j
+ (i.e. We want to make sure to only count the edge between i and j once)
+
+ - Then this function returns F - D
+ !*/
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename potts_problem
+ >
+ void find_max_factor_graph_potts (
+ potts_problem& prob
+ );
+ /*!
+ requires
+ - potts_problem == an object with an interface compatible with the potts_problem
+ object defined at the top of this file.
+ - for all valid i and j:
+ - prob.factor_value_disagreement(i,j) >= 0
+ - prob.factor_value_disagreement(i,j) == prob.factor_value_disagreement(j,i)
+ ensures
+ - This function is a tool for exactly solving the MAP problem in a Potts
+ model. In particular, this means that this function finds the assignments
+ to all the labels in prob which maximizes potts_model_score(#prob).
+ - The optimal labels are stored in #prob.
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename graph_type
+ >
+ void find_max_factor_graph_potts (
+ const graph_type& g,
+ std::vector<node_label>& labels
+ );
+ /*!
+ requires
+ - graph_type is an implementation of dlib/graph/graph_kernel_abstract.h
+ - graph_type::edge_type is some signed type such as int or double
+ - graph_type::type must be the same type as graph_type::edge_type
+ - graph_contains_length_one_cycle(g) == false
+ - for all valid i and j:
+ - edge(g,i,j) >= 0
+ ensures
+ - This routine simply converts g into a potts_problem and calls the
+ version of find_max_factor_graph_potts() defined above on it. Therefore,
+ this routine is just a convenience wrapper that lets you use a dlib::graph
+ to represent a potts problem. This means that this function maximizes
+ the value of potts_model_score(g, #labels).
+ - #labels.size() == g.number_of_nodes()
+ - for all valid i:
+ - #labels[i] == the optimal label for g.node(i)
+ - The correspondence between g and a potts_problem is the following:
+ - the factor_value() for a node is stored in g.node(i).data.
+ - the factor_value_disagreement(i,j) is stored in edge(g,i,j).
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename potts_grid_problem,
+ typename mem_manager
+ >
+ void find_max_factor_graph_potts (
+ const potts_grid_problem& prob,
+ array2d<node_label,mem_manager>& labels
+ );
+ /*!
+ requires
+ - potts_grid_problem == an object with an interface compatible with the
+ potts_grid_problem object defined above.
+ - for all valid i and j:
+ - prob.factor_value_disagreement(i,j) >= 0
+ - prob.factor_value_disagreement(i,j) == prob.factor_value_disagreement(j,i)
+ ensures
+ - This routine solves a version of a potts problem where the graph is a
+ regular grid where each node is connected to its four immediate neighbors.
+ In particular, this means that this function finds the assignments
+ to all the labels in prob which maximizes potts_model_score(prob,#labels).
+ - The optimal labels are stored in #labels.
+ - #labels.nr() == prob.nr()
+ - #labels.nc() == prob.nc()
+ !*/
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// The following functions and interface definitions are convenience routines for use
+// with the potts grid problem version of find_max_factor_graph_potts() defined above.
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ struct single_image_model
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This object defines a slightly more convenient interface for creating
+ potts_grid_problems which operate on an image. In this case, the goal
+ is to assign a binary label to each pixel in an image. In particular,
+ this object defines the interface used by the make_potts_grid_problem()
+ routine defined below.
+
+ In the following comments, we will refer to the image supplied to
+ make_potts_grid_problem() as IMG.
+ !*/
+
+ // This typedef should be for a type like int or double. It
+ // must also be capable of representing signed values.
+ typedef an_integer_or_real_type value_type;
+
+ template <typename pixel_type>
+ value_type factor_value (
+ const pixel_type& v
+ ) const;
+ /*!
+ requires
+ - v is a pixel value from IMG.
+ ensures
+ - returns a value which indicates how "good" it is to assign the location
+ in IMG corresponding to v with the label of true. The larger the value,
+ the more desirable it is to give it this label. Similarly, a negative
+ value indicates that it is better to give the node a label of false.
+ - It is valid for the returned value to be positive or negative infinity.
+ A value of positive infinity indicates that the pixel must be labeled
+ true while negative infinity means it must be labeled false.
+ !*/
+
+ template <typename pixel_type>
+ value_type factor_value_disagreement (
+ const pixel_type& v1,
+ const pixel_type& v2
+ ) const;
+ /*!
+ requires
+ - v1 and v2 are pixel values from neighboring pixels in the IMG image.
+ ensures
+ - returns a number >= 0. This is the penalty for giving neighboring pixels
+ with values v1 and v2 different labels. Larger values indicate a larger
+ penalty.
+ - this function is symmetric. That is, it is true that:
+ factor_value_disagreement(i,j) == factor_value_disagreement(j,i)
+ - It is valid for the returned value to be positive infinity. Returning
+ infinity indicates that the idx1-th and idx2-th nodes must share the same
+ label.
+ !*/
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ struct pair_image_model
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This object defines a slightly more convenient interface for creating
+ potts_grid_problems which operate on a pair of identically sized images.
+ In this case, the goal is to assign a label to each pixel in the first
+ image of the pair. In particular, this object defines the interface
+ used by the make_potts_grid_problem() routine defined below.
+
+ In the following comments, we will refer to the two images supplied to
+ make_potts_grid_problem() as IMG1 and IMG2. The goal of the potts
+ problem will be to assign labels to each pixel in IMG1 (IMG2 is
+ not labeled, it is simply used as a place to keep auxiliary data).
+ !*/
+
+ // This typedef should be for a type like int or double. It
+ // must also be capable of representing signed values.
+ typedef an_integer_or_real_type value_type;
+
+ template <typename pixel_type1, typename pixel_type2>
+ value_type factor_value (
+ const pixel_type1& v1,
+ const pixel_type2& v2
+ ) const;
+ /*!
+ requires
+ - v1 and v2 are corresponding pixels from IMG1 and IMG2 respectively.
+ That is, both pixel values have the same coordinates in the images.
+ So for example, if v1 is the value of IMG1[4][5] then v2 is the value
+ of IMG2[4][5].
+ ensures
+ - returns a value which indicates how "good" it is to assign the location
+ in IMG1 corresponding to v1 with the label of true. The larger the value,
+ the more desirable it is to give it this label. Similarly, a negative
+ value indicates that it is better to give the node a label of false.
+ - It is valid for the returned value to be positive or negative infinity.
+ A value of positive infinity indicates that the pixel must be labeled
+ true while negative infinity means it must be labeled false.
+ !*/
+
+ template <typename pixel_type>
+ value_type factor_value_disagreement (
+ const pixel_type& v1,
+ const pixel_type& v2
+ ) const;
+ /*!
+ requires
+ - v1 and v2 are pixel values from neighboring pixels in the IMG1 image.
+ ensures
+ - returns a number >= 0. This is the penalty for giving neighboring pixels
+ with values v1 and v2 different labels. Larger values indicate a larger
+ penalty.
+ - this function is symmetric. That is, it is true that:
+ factor_value_disagreement(i,j) == factor_value_disagreement(j,i)
+ - It is valid for the returned value to be positive infinity. Returning
+ infinity indicates that the idx1-th and idx2-th nodes must share the same
+ label.
+ !*/
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename single_image_model,
+ typename pixel_type,
+ typename mem_manager
+ >
+ potts_grid_problem make_potts_grid_problem (
+ const single_image_model& model,
+ const array2d<pixel_type,mem_manager>& img
+ );
+ /*!
+ requires
+ - single_image_model == an object with an interface compatible with the
+ single_image_model object defined above.
+ - for all valid i and j:
+ - model.factor_value_disagreement(i,j) >= 0
+ - model.factor_value_disagreement(i,j) == model.factor_value_disagreement(j,i)
+ ensures
+ - returns a potts_grid_problem which can be solved using the
+ find_max_factor_graph_potts(prob,array2d) routine defined above. That is,
+ given an image to store the labels, the following statement would solve the
+ potts problem defined by the given model and image:
+ find_max_factor_graph_potts(make_potts_grid_problem(model,img),labels);
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename pair_image_model,
+ typename pixel_type1,
+ typename pixel_type2,
+ typename mem_manager
+ >
+ potts_grid_problem make_potts_grid_problem (
+ const pair_image_model& model,
+ const array2d<pixel_type1,mem_manager>& img1,
+ const array2d<pixel_type2,mem_manager>& img2
+ );
+ /*!
+ requires
+ - get_rect(img1) == get_rect(img2)
+ (i.e. img1 and img2 have the same dimensions)
+ - pair_image_model == an object with an interface compatible with the
+ pair_image_model object defined above.
+ - for all valid i and j:
+ - model.factor_value_disagreement(i,j) >= 0
+ - model.factor_value_disagreement(i,j) == model.factor_value_disagreement(j,i)
+ ensures
+ - returns a potts_grid_problem which can be solved using the
+ find_max_factor_graph_potts(prob,array2d) routine defined above. That is,
+ given an image to store the labels, the following statement would solve the
+ potts problem defined by the given model and pair of images:
+ find_max_factor_graph_potts(make_potts_grid_problem(model,img1,img2),labels);
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+}
+
+#endif // DLIB_FIND_MAX_FACTOR_GRAPH_PoTTS_ABSTRACT_Hh_
+
+