interpixel_boundary_segmentation.cxx
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <opengm/opengm.hxx>
#include <opengm/datastructures/marray/marray.hxx>
#include <opengm/graphicalmodel/space/simplediscretespace.hxx>
#include <opengm/graphicalmodel/graphicalmodel.hxx>
#include <opengm/operations/adder.hxx>
#include <opengm/inference/lazyflipper.hxx>
using namespace std;
class TopologicalCoordinateToIndex {
public:
TopologicalCoordinateToIndex(
const size_t geometricGridSizeX,
const size_t geometricGridSizeY
)
: gridSizeX_(geometricGridSizeX),
gridSizeY_(geometricGridSizeY)
{}
const size_t operator()(
const size_t tx,
const size_t ty
) const {
return tx / 2 + (ty / 2)*(gridSizeX_) + ((ty + ty % 2) / 2)*(gridSizeX_ - 1);
}
size_t gridSizeX_;
size_t gridSizeY_;
};
template<class T>
void randomData(
const size_t gridSizeX,
const size_t gridSizeY,
marray::Marray<T>& data
) {
srand(gridSizeX * gridSizeY);
const size_t shape[] = {gridSizeX, gridSizeY};
data.assign();
data.resize(shape, shape + 2);
for (size_t y = 0; y < gridSizeY; ++y) {
for (size_t x = 0; x < gridSizeX; ++x) {
data(x, y) = static_cast<float> (rand() % 10) *0.1;
}
}
}
template<class T>
void printData(
const marray::Marray<T> & data
) {
cout << "energy for boundary to be active:" << endl;
for (size_t y = 0; y < data.shape(1)*2 - 1; ++y) {
for (size_t x = 0; x < data.shape(0)*2 - 1; ++x) {
if (x % 2 == 0 && y % 2 == 0) {
cout << left << setw(3) << setprecision(1) << data(x / 2, y / 2);
} else if (x % 2 == 0 && y % 2 == 1) {
cout << left << setw(3) << setprecision(1) << "___";
} else if (x % 2 == 1 && y % 2 == 0) {
cout << left << setw(3) << setprecision(1) << " | ";
} else if (x % 2 == 1 && y % 2 == 1) {
cout << left << setw(3) << setprecision(1) << " * ";
}
}
cout << "\n";
}
}
template<class T>
void printSolution(
const marray::Marray<T>& data,
const vector<size_t>& solution
)
{
TopologicalCoordinateToIndex cTHelper(data.shape(0), data.shape(1));
cout << endl << "solution states:" << endl;
cout << "solution:" << endl;
for (size_t x = 0; x < data.shape(0)*2 - 1; ++x) {
cout << left << setw(3) << setprecision(1) << "___";
}
cout << endl;
for (size_t y = 0; y < data.shape(1)*2 - 1; ++y) {
cout << "|";
for (size_t x = 0; x < data.shape(0)*2 - 1; ++x) {
if (x % 2 == 0 && y % 2 == 0) {
data(x / 2, y / 2) = static_cast<float> (rand() % 10) *0.1;
cout << left << setw(3) << setprecision(1) << " ";
} else if (x % 2 == 0 && y % 2 == 1) {
if (solution[cTHelper(x, y)]) {
cout << left << setw(3) << setprecision(1) << "___";
}
else {
cout << left << setw(3) << setprecision(1) << " ";
}
} else if (x % 2 == 1 && y % 2 == 0) {
if (solution[cTHelper(x, y)])
cout << left << setw(3) << setprecision(1) << " | ";
else
cout << left << setw(3) << setprecision(1) << " ";
} else if (x % 2 == 1 && y % 2 == 1) {
cout << left << setw(3) << setprecision(1) << " * ";
}
}
cout << "|" << endl;
}
for (size_t x = 0; x < data.shape(0)*2 - 1; ++x) {
cout << left << setw(3) << setprecision(1) << "___";
}
cout << endl;
}
template<class T>
struct ClosednessFunctor {
public:
typedef T value_type;
template<class Iterator>
inline const T operator()(Iterator begin)const {
size_t sum = begin[0];
sum += begin[1];
sum += begin[2];
sum += begin[3];
if (sum != 2 && sum != 0) {
return high;
}
return 0;
}
size_t dimension()const {
return 4;
}
size_t shape(const size_t i)const {
return 2;
}
size_t size()const {
return 16;
}
T high;
};
int main(int argc, char** argv) {
const size_t gridSizeX = 5, gridSizeY = 5;
const float beta = 0.9;
const float high = 10;
const size_t tGridSizeX = 2 * gridSizeX - 1, tGridSizeY = 2 * gridSizeY - 1;
const size_t nrOfVariables = gridSizeY * (gridSizeX - 1) + gridSizeX * (gridSizeY - 1);
const size_t dimT[] = {tGridSizeX, tGridSizeY};
TopologicalCoordinateToIndex cTHelper(gridSizeX, gridSizeY);
marray::Marray<float> data;
randomData(gridSizeX, gridSizeY, data);
cout << "interpixel boundary segmentation with closedness:" << endl;
printData(data);
typedef opengm::meta::TypeListGenerator<
opengm::ExplicitFunction<float>,
ClosednessFunctor<float>
>::type FunctionTypeList;
typedef opengm::GraphicalModel<float, opengm::Adder, FunctionTypeList,
opengm::SimpleDiscreteSpace<> > Model;
typedef Model::FunctionIdentifier FunctionIdentifier;
Model gm(opengm::SimpleDiscreteSpace<>(nrOfVariables, 2));
{
const size_t shape[] = {2};
opengm::ExplicitFunction<float> f(shape, shape + 1);
for (size_t yT = 0; yT < dimT[1]; ++yT) {
for (size_t xT = 0; xT < dimT[0]; ++xT) {
if ((xT % 2 + yT % 2) == 1) {
float gradient = fabs(data(xT / 2, yT / 2) - data(xT / 2 + xT % 2, yT / 2 + yT % 2));
f(0) = beta * gradient;
f(1) = (1.0 - beta) * (1.0 - gradient);
FunctionIdentifier id = gm.addFunction(f);
size_t vi[] = {cTHelper(xT, yT)};
gm.addFactor(id, vi, vi + 1);
}
}
}
}
{
ClosednessFunctor<float> f;
f.high = high;
FunctionIdentifier id = gm.addFunction(f);
for (size_t y = 0; y < dimT[1]; ++y) {
for (size_t x = 0; x < dimT[0]; ++x) {
if (x % 2 + y % 2 == 2) {
size_t vi[] = {
cTHelper(x + 1, y),
cTHelper(x - 1, y),
cTHelper(x, y + 1),
cTHelper(x, y - 1)
};
sort(vi, vi + 4);
gm.addFactor(id, vi, vi + 4);
}
}
}
}
typedef opengm::LazyFlipper<Model, opengm::Minimizer> LazyFlipperType;
LazyFlipperType::VerboseVisitorType verboseVisitor;
size_t maxSubgraphSize = 5;
LazyFlipperType lazyflipper(gm, maxSubgraphSize);
cout << "start inference:" << endl;
lazyflipper.infer(verboseVisitor);
vector<size_t> solution;
lazyflipper.arg(solution);
printSolution(data, solution);
}