提交scripts
This commit is contained in:
1 parent
82caf72036
commit
07dabbd186
224 files changed
+130146
No files matched your search
+241
@@ -0,0 +1,241 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// LBA.h
|
||||
//
|
||||
// Copyright 2007 cDc@seacave
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// (See http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef __SEACAVE_LBA_H__
|
||||
#define __SEACAVE_LBA_H__
|
||||
|
||||
|
||||
// I N C L U D E S /////////////////////////////////////////////////
|
||||
|
||||
|
||||
// D E F I N E S ///////////////////////////////////////////////////
|
||||
|
||||
// uncomment to enable multi-threading based on OpenMP
|
||||
#ifdef _USE_OPENMP
|
||||
#define LBP_USE_OPENMP
|
||||
#endif
|
||||
|
||||
|
||||
namespace SEACAVE {
|
||||
|
||||
// S T R U C T S ///////////////////////////////////////////////////
|
||||
|
||||
// basic implementation of the loopy belief propagation algorithm
|
||||
// based on a code originally written by Michael Waechter:
|
||||
// https://github.com/nmoehrle/mvs-texturing
|
||||
// Copyright(c) Michael Waechter
|
||||
// Licensed under the BSD 3-Clause license
|
||||
class MATH_API LBPInference
|
||||
{
|
||||
public:
|
||||
typedef unsigned NodeID;
|
||||
typedef unsigned LabelID;
|
||||
typedef unsigned EdgeID;
|
||||
typedef float EnergyType;
|
||||
|
||||
struct DataCost {
|
||||
NodeID nodeID;
|
||||
EnergyType cost;
|
||||
};
|
||||
|
||||
typedef EnergyType (STCALL *FncSmoothCost)(NodeID, NodeID, LabelID, LabelID);
|
||||
|
||||
enum { MaxEnergy = 1000 };
|
||||
|
||||
protected:
|
||||
struct DirectedEdge {
|
||||
NodeID nodeID1;
|
||||
NodeID nodeID2;
|
||||
std::vector<EnergyType> newMsgs;
|
||||
std::vector<EnergyType> oldMsgs;
|
||||
inline DirectedEdge(NodeID _nodeID1, NodeID _nodeID2) : nodeID1(_nodeID1), nodeID2(_nodeID2) {}
|
||||
};
|
||||
|
||||
struct Node {
|
||||
LabelID label;
|
||||
EnergyType dataCost;
|
||||
std::vector<LabelID> labels;
|
||||
std::vector<EnergyType> dataCosts;
|
||||
std::vector<EdgeID> incomingEdges;
|
||||
inline Node() : label(0), dataCost(MaxEnergy) {}
|
||||
};
|
||||
|
||||
std::vector<DirectedEdge> edges;
|
||||
std::vector<Node> nodes;
|
||||
FncSmoothCost fncSmoothCost;
|
||||
|
||||
public:
|
||||
LBPInference() {}
|
||||
LBPInference(NodeID nNodes) : nodes(nNodes) {}
|
||||
|
||||
inline void SetNumNodes(NodeID nNodes) {
|
||||
nodes.resize(nNodes);
|
||||
}
|
||||
inline NodeID GetNumNodes() const {
|
||||
return (NodeID)nodes.size();
|
||||
}
|
||||
|
||||
inline void SetNeighbors(NodeID nodeID1, NodeID nodeID2) {
|
||||
nodes[nodeID2].incomingEdges.push_back((EdgeID)edges.size());
|
||||
edges.push_back(DirectedEdge(nodeID1, nodeID2));
|
||||
nodes[nodeID1].incomingEdges.push_back((EdgeID)edges.size());
|
||||
edges.push_back(DirectedEdge(nodeID2, nodeID1));
|
||||
}
|
||||
|
||||
inline void SetDataCost(LabelID label, NodeID nodeID, EnergyType cost) {
|
||||
Node& node = nodes[nodeID];
|
||||
node.labels.push_back(label);
|
||||
const EnergyType dataCost(cost);
|
||||
node.dataCosts.push_back(dataCost);
|
||||
if (dataCost < node.dataCost) {
|
||||
node.label = label;
|
||||
node.dataCost = dataCost;
|
||||
}
|
||||
for (EdgeID edgeID: node.incomingEdges) {
|
||||
DirectedEdge& incomingEdge = edges[edgeID];
|
||||
incomingEdge.oldMsgs.push_back(0);
|
||||
incomingEdge.newMsgs.push_back(0);
|
||||
}
|
||||
}
|
||||
inline void SetDataCost(LabelID label, const DataCost& cost) {
|
||||
SetDataCost(label, cost.nodeID, cost.cost);
|
||||
}
|
||||
inline void SetDataCosts(LabelID label, const std::vector<DataCost>& costs) {
|
||||
for (const DataCost& cost: costs)
|
||||
SetDataCost(label, cost);
|
||||
}
|
||||
|
||||
inline void SetSmoothCost(FncSmoothCost func) {
|
||||
fncSmoothCost = func;
|
||||
}
|
||||
|
||||
EnergyType ComputeEnergy() const {
|
||||
EnergyType energy(0);
|
||||
#ifdef LBP_USE_OPENMP
|
||||
#pragma omp parallel for reduction(+:energy)
|
||||
#endif
|
||||
for (int_t nodeID = 0; nodeID < (int_t)nodes.size(); ++nodeID)
|
||||
energy += nodes[nodeID].dataCost;
|
||||
#ifdef LBP_USE_OPENMP
|
||||
#pragma omp parallel for reduction(+:energy)
|
||||
#endif
|
||||
for (int_t edgeID = 0; edgeID < (int_t)edges.size(); ++edgeID) {
|
||||
const DirectedEdge& edge = edges[edgeID];
|
||||
energy += fncSmoothCost(edge.nodeID1, edge.nodeID2, nodes[edge.nodeID1].label, nodes[edge.nodeID2].label);
|
||||
}
|
||||
return energy;
|
||||
}
|
||||
|
||||
void Optimize(unsigned num_iterations) {
|
||||
for (unsigned i = 0; i < num_iterations; ++i) {
|
||||
#ifdef LBP_USE_OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int_t edgeID = 0; edgeID < (int_t)edges.size(); ++edgeID) {
|
||||
DirectedEdge& edge = edges[edgeID];
|
||||
const std::vector<LabelID>& labels1 = nodes[edge.nodeID1].labels;
|
||||
const std::vector<LabelID>& labels2 = nodes[edge.nodeID2].labels;
|
||||
for (size_t j = 0; j < labels2.size(); ++j) {
|
||||
const LabelID label2(labels2[j]);
|
||||
EnergyType minEnergy(std::numeric_limits<EnergyType>::max());
|
||||
for (size_t k = 0; k < labels1.size(); ++k) {
|
||||
const LabelID label1(labels1[k]);
|
||||
EnergyType energy(nodes[edge.nodeID1].dataCosts[k] + fncSmoothCost(edge.nodeID1, edge.nodeID2, label1, label2));
|
||||
const std::vector<EdgeID>& incoming_edges1 = nodes[edge.nodeID1].incomingEdges;
|
||||
for (size_t n = 0; n < incoming_edges1.size(); ++n) {
|
||||
const DirectedEdge& pre_edge = edges[incoming_edges1[n]];
|
||||
if (pre_edge.nodeID1 == edge.nodeID2) continue;
|
||||
energy += pre_edge.oldMsgs[k];
|
||||
}
|
||||
if (minEnergy > energy)
|
||||
minEnergy = energy;
|
||||
}
|
||||
edge.newMsgs[j] = minEnergy;
|
||||
}
|
||||
}
|
||||
#ifdef LBP_USE_OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int_t edgeID = 0; edgeID < (int_t)edges.size(); ++edgeID) {
|
||||
DirectedEdge& edge = edges[edgeID];
|
||||
edge.newMsgs.swap(edge.oldMsgs);
|
||||
EnergyType minMsg(std::numeric_limits<EnergyType>::max());
|
||||
for (EnergyType msg: edge.oldMsgs)
|
||||
if (minMsg > msg)
|
||||
minMsg = msg;
|
||||
for (EnergyType& msg: edge.oldMsgs)
|
||||
msg -= minMsg;
|
||||
}
|
||||
}
|
||||
#ifdef LBP_USE_OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int_t nodeID = 0; nodeID < (int_t)nodes.size(); ++nodeID) {
|
||||
Node& node = nodes[nodeID];
|
||||
EnergyType minEnergy(std::numeric_limits<EnergyType>::max());
|
||||
for (size_t j = 0; j < node.labels.size(); ++j) {
|
||||
EnergyType energy(node.dataCosts[j]);
|
||||
for (EdgeID incoming_edge_idx : node.incomingEdges)
|
||||
energy += edges[incoming_edge_idx].oldMsgs[j];
|
||||
if (energy < minEnergy) {
|
||||
minEnergy = energy;
|
||||
node.label = node.labels[j];
|
||||
node.dataCost = node.dataCosts[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EnergyType Optimize() {
|
||||
TD_TIMER_STARTD();
|
||||
EnergyType energy(ComputeEnergy());
|
||||
EnergyType diff(energy);
|
||||
unsigned i(0);
|
||||
#if 1
|
||||
unsigned nIncreases(0), nTotalIncreases(0);
|
||||
#endif
|
||||
while (true) {
|
||||
TD_TIMER_STARTD();
|
||||
const EnergyType last_energy(energy);
|
||||
Optimize(1);
|
||||
energy = ComputeEnergy();
|
||||
diff = last_energy - energy;
|
||||
DEBUG_ULTIMATE("\t%2u. e: %g\td: %g\tt: %s", i, last_energy, diff, TD_TIMER_GET_FMT().c_str());
|
||||
if (++i > 100 || diff == EnergyType(0))
|
||||
break;
|
||||
#if 1
|
||||
if (diff < EnergyType(0)) {
|
||||
++nTotalIncreases;
|
||||
if (++nIncreases > 3)
|
||||
break;
|
||||
} else {
|
||||
if (nTotalIncreases > 5)
|
||||
break;
|
||||
nIncreases = 0;
|
||||
}
|
||||
#else
|
||||
if (diff < EnergyType(0))
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (diff == EnergyType(0)) {
|
||||
DEBUG_ULTIMATE("Inference converged in %u iterations: %g energy (%s)", i, energy, TD_TIMER_GET_FMT().c_str());
|
||||
} else {
|
||||
DEBUG_ULTIMATE("Inference aborted (energy increased): %u iterations, %g energy (%s)", i, energy, TD_TIMER_GET_FMT().c_str());
|
||||
}
|
||||
return energy;
|
||||
}
|
||||
|
||||
inline LabelID GetLabel(NodeID nodeID) const {
|
||||
return nodes[nodeID].label;
|
||||
}
|
||||
};
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
} // namespace SEACAVE
|
||||
|
||||
#endif // __SEACAVE_LBP_H__
|
||||
Reference in new issue
Block a user