void add_grid_edges_direction(MRFEnergy<T>& mrfenergy, const PyArrayObject* nodeids, const typename T::EdgeData& ed, int direction) { typedef typename T::REAL REAL; typedef typename MRFEnergy<T>::NodeId NodeId; int ndim = PyArray_NDIM(nodeids); npy_intp* shape = PyArray_DIMS(nodeids); if(direction >= ndim || direction < 0) throw std::runtime_error("invalid direction"); for(pyarray_iterator it(nodeids); !it.atEnd(); ++it) { npy_intp* coord = it.getIndex(); if(coord[direction] - 1 < 0) continue; NodeId id1 = reinterpret_cast<NodeId>(PyArray_SafeGet<numeric_pointer>(nodeids, coord)); --coord[direction]; NodeId id2 = reinterpret_cast<NodeId>(PyArray_SafeGet<numeric_pointer>(nodeids, coord)); ++coord[direction]; mrfenergy.AddEdge(id2, id1, ed); } }
void add_grid_edges(MRFEnergy<T>& mrfenergy, const PyArrayObject* nodeids, const typename T::EdgeData& ed) { typedef typename T::REAL REAL; typedef typename MRFEnergy<T>::NodeId NodeId; int ndim = PyArray_NDIM(nodeids); npy_intp* shape = PyArray_DIMS(nodeids); for(pyarray_iterator it(nodeids); !it.atEnd(); ++it) { npy_intp* coord = it.getIndex(); NodeId id1 = reinterpret_cast<NodeId>(PyArray_SafeGet<numeric_pointer>(nodeids, coord)); for(int d=0; d < ndim; ++d) { if(coord[d] - 1 < 0) continue; --coord[d]; NodeId id2 = reinterpret_cast<NodeId>(PyArray_SafeGet<numeric_pointer>(nodeids, coord)); ++coord[d]; mrfenergy.AddEdge(id2, id1, ed); } } }
void testPotts() { MRFEnergy<TypePotts>* mrf; MRFEnergy<TypePotts>::NodeId* nodes; MRFEnergy<TypePotts>::Options options; TypePotts::REAL energy, lowerBound; const int nodeNum = 2; // number of nodes const int K = 3; // number of labels TypePotts::REAL D[K]; int x, y; mrf = new MRFEnergy<TypePotts>(TypePotts::GlobalSize(K)); nodes = new MRFEnergy<TypePotts>::NodeId[nodeNum]; // construct energy D[0] = 0; D[1] = 1; D[2] = 2; nodes[0] = mrf->AddNode(TypePotts::LocalSize(), TypePotts::NodeData(D)); D[0] = 3; D[1] = 4; D[2] = 5; nodes[1] = mrf->AddNode(TypePotts::LocalSize(), TypePotts::NodeData(D)); mrf->AddEdge(nodes[0], nodes[1], TypePotts::EdgeData(6)); // Function below is optional - it may help if, for example, nodes are added in a random order // mrf->SetAutomaticOrdering(); /////////////////////// TRW-S algorithm ////////////////////// options.m_iterMax = 30; // maximum number of iterations mrf->Minimize_TRW_S(options, lowerBound, energy); // read solution x = mrf->GetSolution(nodes[0]); y = mrf->GetSolution(nodes[1]); printf("Solution: %d %d\n", x, y); //////////////////////// BP algorithm //////////////////////// mrf->ZeroMessages(); // in general not necessary - it may be faster to start // with messages computed in previous iterations. // NOTE: in most cases, immediately after creating the energy // all messages are zero. EXCEPTION: typeBinary and typeBinaryFast. // So calling ZeroMessages for these types will NOT transform // the energy to the original state. options.m_iterMax = 30; // maximum number of iterations mrf->Minimize_BP(options, energy); // read solution x = mrf->GetSolution(nodes[0]); y = mrf->GetSolution(nodes[1]); printf("Solution: %d %d\n", x, y); // done delete nodes; delete mrf; }
void add_grid_edges_direction_local(MRFEnergy<T>& mrfenergy, const PyArrayObject* nodeids, const PyArrayObject* ed, int direction, int axis=0) { typedef typename T::REAL REAL; typedef typename MRFEnergy<T>::NodeId NodeId; typedef typename MRFEnergy<T>::EdgeData EdgeData; int ndim = PyArray_NDIM(nodeids); npy_intp* shape = PyArray_DIMS(nodeids); int ed_ndim = PyArray_NDIM(ed); npy_intp* ed_shape = PyArray_DIMS(ed); if(direction >= ndim || direction < 0) throw std::runtime_error("invalid direction"); if(ed_ndim != ndim+1) throw std::runtime_error("invalid number of dimensions for the edge data array"); // Check and fix the axis parameter. if(-axis > ed_ndim || axis >= ed_ndim) throw std::runtime_error("axis is out of bounds"); if(axis < 0) axis = ed_ndim + axis; // Check the shapes. // First, take the axis dimension out of the ed_shape. npy_intp* ed_shape_fix = new npy_intp[ndim]; std::copy(ed_shape, ed_shape+axis, ed_shape_fix); std::copy(ed_shape+axis+1, ed_shape+ed_ndim, ed_shape_fix+axis); if(std::mismatch(shape, shape+direction, ed_shape_fix, std::less_equal<int>()).first != shape+direction || std::mismatch(shape+direction+1, shape+ndim, ed_shape_fix+direction+1, std::less_equal<int>()).first != shape+ndim) throw std::runtime_error("invalid shape for the edge data array"); if(ed_shape_fix[direction] < shape[direction]-1) throw std::runtime_error("invalid shape for the edge data array"); delete [] ed_shape_fix; for(pyarray_iterator it(nodeids); !it.atEnd(); ++it) { npy_intp* coord = it.getIndex(); if(coord[direction] - 1 < 0) continue; NodeId id1 = reinterpret_cast<NodeId>(PyArray_SafeGet<numeric_pointer>(nodeids, coord)); --coord[direction]; // Create a list to access the EdgeData. py::list lcoord; int d; for(d=0; d<ndim; ++d) { if(d == axis) lcoord.append(py::slice()); lcoord.append(coord[d]); } if(d == axis) lcoord.append(py::slice()); PyArrayObject* localed = reinterpret_cast<PyArrayObject*>( PyObject_GetItem((PyObject*)ed, py::tuple(lcoord).ptr())); NodeId id2 = reinterpret_cast<NodeId>(PyArray_SafeGet<numeric_pointer>(nodeids, coord)); ++coord[direction]; mrfenergy.AddEdge(id2, id1, EdgeData(py::object(localed))); } }
///----------------------------------------------------------------------------- //extern __declspec(dllexport) double trw_potts( int nnodes, // number of nodes int nlabels, // number of labels double const* unary, // unary potentials int npairs, // number of pairs int const *pairs, // pairs (ith pair = pairs[2*i], pairs[2*i+1]) double const *wpairs, // binary potentials int* solution, // return array int max_iter, // max number of iterations bool randomize_order, // bool use_bp, // belief propagation bool verbose // print debug info ) { MRFEnergy<TypePotts>* mrf; MRFEnergy<TypePotts>::NodeId* nodes; MRFEnergy<TypePotts>::Options options; TypePotts::REAL energy, lowerBound; mrf = new MRFEnergy<TypePotts>(TypePotts::GlobalSize(nlabels)); nodes = new MRFEnergy<TypePotts>::NodeId[nnodes]; // construct energy TypePotts::REAL * U = new TypePotts::REAL[nlabels]; for (int i=0; i < nnodes; i++) { for (int l=0; l < nlabels; l++) { U[l] = unary[i*nlabels + l]; } nodes[i] = mrf->AddNode( TypePotts::LocalSize(), TypePotts::NodeData(U) ); } delete[] U; /// pairs for (int i = 0; i < npairs; ++i) { mrf->AddEdge( nodes[pairs[i*2]], nodes[pairs[i*2+1]], TypePotts::EdgeData(wpairs[i]) ); } // TypeGeneral::REAL * E = new TypeGeneral::REAL[nlabels*nlabels]; // for (int i=0; i < npairs; i++) // { // for (int l1 = 0; l1 < nlabels; l1++) // for (int l2 = 0; l2 < nlabels; l2++) // {{ // E[l1 + l2*nlabels] = wpairs[i*nlabels*nlabels + l1 + l2*nlabels]; // }} // mrf->AddEdge( // nodes[pairs[i*2]], // nodes[pairs[i*2+1]], // TypeGeneral::EdgeData(TypeGeneral::GENERAL, E) // ); // } // Function below is optional - it may help if, for example, nodes are added in a random order if (randomize_order) mrf->SetAutomaticOrdering(); /////////////////////// TRW-S algorithm ////////////////////// if (verbose) options.m_printMinIter = 0; else options.m_printMinIter = max_iter+1; options.m_iterMax = max_iter; // maximum number of iterations if (use_bp) mrf->Minimize_BP(options, energy); else mrf->Minimize_TRW_S(options, lowerBound, energy); // read solution for (int i = 0; i<nnodes; i++) { solution[i] = mrf->GetSolution(nodes[i]); } delete mrf; delete[] nodes; return energy; }