test_pie/external/MRF/mrf.h

273 lines
12 KiB
C
Raw Permalink Normal View History

2023-09-14 11:12:02 +02:00
/* Copyright Olga Veksler, Ramin Zabih, Vladimir Kolmogorov, and Daniel Scharstein
* Send any questions to schar@middlebury.edu
*/
#ifndef __MRF_H__
#define __MRF_H__
#include <stdio.h>
class EnergyFunction;
class MRF
{
public:
// *********** CONSTRUCTORS/DESTRUCTOR
// Constructor. After you call this, you must call setData and setSmoothness
// Use this constructor for 2D grid graphs of size width by height Standard 4-connected
// neighborhood system is assumed. Labels are in the range 0,1,...nLabels - 1
// Width is in the range 0,1,...width-1 and height is in the range 0,1,...height-1
// Input parameter eng specifies the data and smoothness parts of the energy
// For 2D grids, since 4 connected neighborhood structure is assumed, this
// fully specifies the energy
MRF(int width, int height, int nLabels, EnergyFunction *eng);
// Use this constructor for a general neighborhood system. Pixels are in the range
// 0,1,..nPixels-1, and labels are in the range 0,1,...,nLabels-1
// Input parameter eng specifies the data and smoothness parts of the energy
// after this constructor you need to call setNeighbors() to specify the neighborhood system
MRF(int nPixels, int nLabels, EnergyFunction *eng);
virtual ~MRF() { }
// Returns true if energy function has been specified, returns false otherwise
// By default, it always returns true. Can be modified by the supplier of
// optimization algorithm
virtual int isValid(){return true;};
// *********** EVALUATING THE ENERGY
typedef int Label;
typedef float EnergyVal; /* The total energy of a labeling */
typedef float CostVal; /* costs of individual terms of the energy */
EnergyVal totalEnergy(); /* returns energy of current labeling */
virtual EnergyVal dataEnergy() = 0; /* returns the data part of the energy */
virtual EnergyVal smoothnessEnergy() = 0; /* returns the smoothness part of the energy */
//Functional representation for data costs
typedef CostVal (*DataCostFn)(int pix, Label l);
// Functional representation for the general cost function type
typedef CostVal (*SmoothCostGeneralFn)(int pix1, int pix2, Label l1, Label l2);
// For general smoothness functions, some implementations try to cache all function values in an array
// for efficiency. To prevent this, call the following function before calling initialize():
void dontCacheSmoothnessCosts() {m_allocateArrayForSmoothnessCostFn = false;}
// Use this function only for non-grid graphs. Sets pix1 and pix2 to be neighbors
// with the specified weight. Can be called ONLY once for each pair of pixels
// That is if pixel1 and pixel2 are neihbors, call either setNeighbors(pixel1,pixel2,weight)
// or setNeighbors(pixel2,pixel1,weight), but NOT BOTH
virtual void setNeighbors(int pix1, int pix2, CostVal weight)= 0;
void initialize();
// Runs optimization for nIterations. Input parameter time returns the time it took to
// perform nIterations of optimization
void optimize(int nIterations, float& time);
virtual void optimizeAlg(int nIterations)=0;
// *********** ACCESS TO SOLUTION
// Returns pointer to array of size nPixels. Client may then read/write solution (but not deallocate array).
virtual Label* getAnswerPtr()= 0;
// returns the label of the input pixel
virtual Label getLabel(int pixel)= 0;
// sets label of a pixel
virtual void setLabel(int pixel,Label label)= 0;
// sets all the labels to zero
virtual void clearAnswer() = 0;
// use this function to pass any parameters to optimization algorithm.
// The first argument is the number of passed, parameters and
// the second argument is the pointer to the array of parameters
virtual void setParameters(int numParam, void *param) = 0;
// This function returns lower bound computed by the algorithm (if any)
// By default, it returns 0.
virtual double lowerBound(){return((double) 0);};
// Returns 0 if the energy is not suitable for current optimization algorithm
// Returns 1 if the energy is suitable for current optimization algorithm
// Returns 2 if current optimizaiton algorithm does not check the energy
virtual char checkEnergy();
typedef enum
{
FUNCTION,
ARRAY,
THREE_PARAM,
NONE
} InputType;
protected:
int m_width, m_height; // width and height of a grid,if graph is a grid
int m_nPixels; // number of pixels, for both grid and non-grid graphs
int m_nLabels; // number of labels, for both grid and non-grid graphs
bool m_grid_graph; // true if the graph is a 2D grid
bool m_varWeights; // true if weights are spatially varying. To be used only with 2D grids
bool m_initialized; // true if array m_V is allocated memory.
EnergyFunction *m_e;
InputType m_dataType;
InputType m_smoothType;
// *********** SET THE DATA COSTS
// Following 2 functions set the data costs
virtual void setData(DataCostFn dcost)=0;
virtual void setData(CostVal* data)=0;
// *********** SET THE SMOOTHNESS COSTS
// following 3 functions set the smoothness costs
// there are 2 ways to represent the smoothness costs, one with array, one with function
// In addition, for 2D grid graphs spacially varying weights can be specified by 2 arrays
// Smoothness cost depends on labels V(l1,l2) for all edges (except for a multiplier - see setCues() ).
// V must be symmetric: V(l1,l2) = V(l2,l1)
// V must be an array of size nLabels*nLabels. It is NOT copied into internal memory
virtual void setSmoothness(CostVal* V)=0;
// General smoothness cost can be specified by passing pointer to a function
virtual void setSmoothness(SmoothCostGeneralFn cost)=0;
// To prevent implementations from caching all general smoothness costs values, the flag below
// can be set to false by calling dontCacheSmoothnessCosts() before calling initialize():
bool m_allocateArrayForSmoothnessCostFn;
// Use if the smoothness is V(l1,l2) = lambda * min ( |l1-l2|^m_smoothExp, m_smoothMax )
// Can also add optional spatially varying weights for 2D grid graphs using setCues()
virtual void setSmoothness(int smoothExp,CostVal smoothMax, CostVal lambda)=0;
// You are not required to call setCues, in which case there is no multiplier.
// Function below cannot be called for general cost function.
// This function can be only used for a 2D grid graph
// hCue and vCue must be arrays of size width*height in row major order.
// They are NOT copied into internal memory.
// hCue(x,y) holds the variable weight for edge between pixels (x+1,y) and (x,y)
// vCue(x,y) holds the variable weight for edge between pixels (x,y+1) and (x,y)
virtual void setCues(CostVal* hCue, CostVal* vCue)=0;
virtual void initializeAlg()=0; // called by initialize()
void commonInitialization(EnergyFunction *e);
void checkArray(CostVal *V);
};
// *********** This class is for data costs
// Data costs can be specified eithe by an array or by a pointer to a function
// If specified by an array, use constructor DataCost(cost) where
// cost is the array of type CostVal. The cost of pixel p and label l is
// stored at cost[p*nLabels+l] where nLabels is the number of labels
// If data costs are to be specified by a function, pass
// a pointer to a function
// CostVal costFn(int pix, Label lab)
// which returns the
// data cost of pixel pix to be assigned label lab
class DataCost
{
friend class MRF;
public:
typedef MRF::CostVal CostVal;
typedef MRF::DataCostFn DataCostFn;
DataCost(CostVal *cost){m_costArray = cost;m_type = MRF::ARRAY; };
DataCost(DataCostFn costFn){m_costFn = costFn;m_type = MRF::FUNCTION;};
private:
MRF::CostVal *m_costArray;
MRF::DataCostFn m_costFn;
MRF::InputType m_type;
};
// ***************** This class represents smoothness costs
// If the smoothness is V(l1,l2) = lambda * min ( |l1-l2|^m_smoothExp, m_smoothMax )
// use constructor SmoothnessCost(smoothExp,smoothMax,lambda)
// If, in addition, there are spacially varying weights use constructor
// SmoothnessCost(smoothExp,smoothMax,lambda,hWeights,vWeights)
// hWeights and vWeights can be only used for a 2D grid graph
// hWeights and vWeights must be arrays of size width*height in row major order.
// They are NOT copied into internal memory.
// hWeights(x,y) holds the variable weight for edge between pixels (x+1,y) and (x,y)
// vWeights(x,y) holds the variable weight for edge between pixels (x,y+1) and (x,y)
// If the smoothness costs are specified by input array V of type CostVal and
// size nLabels*nLabels, use consructor SmoothnessCost(V).
// If in addition, there are
// are spacially varying weights use constructor SmoothnessCost(V,hWeights,vWeights)
// Note that array V must be of size nLabels*nLabels, and be symmetric.
// That is V[i*nLabels+j] = V[j*nLabels+i]
// Finally, if the smoothness term is specified by a general function, use
// constructor SmoothnessCost(costFn)
class SmoothnessCost
{
friend class MRF;
public:
typedef MRF::CostVal CostVal;
// Can be used for 2D grids and for general graphs
// In case if used for 2D grids, the smoothness term WILL NOT be spacially varying
SmoothnessCost(int smoothExp,CostVal smoothMax,CostVal lambda)
{m_type=MRF::THREE_PARAM;m_smoothMax = smoothMax;m_smoothExp = smoothExp;m_lambda=lambda;m_varWeights=false;};
// Can be used only for 2D grids
// the smoothness term WILL BE be spacially varying
SmoothnessCost(int smoothExp,CostVal smoothMax,CostVal lambda,CostVal *hWeights, CostVal *vWeights)
{m_type=MRF::THREE_PARAM;m_smoothMax = smoothMax;m_smoothExp = smoothExp;m_lambda=lambda;
m_varWeights = true;m_hWeights = hWeights; m_vWeights = vWeights;};
// Can be used 2D grids and for general graphs
// In case if used for 2D grids, the smoothness term WILL NOT be spacially varying
SmoothnessCost(CostVal *V){m_V = V;m_type = MRF::ARRAY;m_varWeights=false;};
// Can be used only for 2D grids
// the smoothness term WILL BE be spacially varying
SmoothnessCost(CostVal *V,CostVal *hWeights, CostVal *vWeights )
{m_V = V;m_hWeights = hWeights; m_vWeights = vWeights; m_varWeights = true; m_type=MRF::ARRAY;};
// Can be used 2D grids and for general graphs
SmoothnessCost(MRF::SmoothCostGeneralFn costFn){m_costFn = costFn;m_type = MRF::FUNCTION;m_varWeights=false;};
private:
CostVal *m_V,*m_hWeights, *m_vWeights;
MRF::SmoothCostGeneralFn m_costFn;
MRF::InputType m_type;
int m_smoothExp;
CostVal m_smoothMax,m_lambda;
bool m_varWeights;
EnergyFunction *m_eng;
};
class EnergyFunction
{
public:
EnergyFunction(DataCost *dataCost,SmoothnessCost *smoothCost)
{m_dataCost = dataCost;m_smoothCost = smoothCost;};
DataCost *m_dataCost;
SmoothnessCost *m_smoothCost;
};
#endif /* __MRF_H__ */
/*
virtual EnergyVal dataEnergy() = 0;
virtual EnergyVal smoothnessEnergy() = 0;
virtual void setNeighbors(int pix1, int pix2, CostVal weight)= 0;
virtual void optimizeAlg(int nIterations)=0;
virtual Label* getAnswerPtr()= 0;
virtual Label getLabel(int pixel)= 0;
virtual void setLabel(int pixel,Label label)= 0;
virtual void clearAnswer() = 0;
virtual void setParameters(int numParam, void *param) = 0;
virtual void setData(DataCostFn dcost)=0;
virtual void setData(CostVal* data)=0;
virtual void setSmoothness(CostVal* V)=0;
virtual void setSmoothness(SmoothCostGeneralFn cost)=0;
virtual void setCues(CostVal* hCue, CostVal* vCue)=0;
virtual void setSmoothness(int smoothExp,CostVal smoothMax, CostVal lambda);
virtual EnergyVal lowerBound(){return((EnergyVal) 0);};
*/