Пример #1
0
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;
}
Пример #2
0
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);
    }
}
Пример #3
0
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);
        }
    }
}
Пример #4
0
py::object add_grid_nodes(MRFEnergy<T>& mrfenergy, const PyArrayObject* unaryterms,
                            int axis=0)
{
    typedef typename T::REAL REAL;
    typedef typename T::LocalSize LocalSize;
    typedef typename T::NodeData NodeData;
    
    int ndim = PyArray_NDIM(unaryterms);
    npy_intp* shape = PyArray_DIMS(unaryterms);
    if(-axis > ndim || axis >= ndim)
        throw std::runtime_error("axis is out of bounds");
    if(axis < 0)
        axis = ndim + axis;
    int num_labels = shape[axis];
    
    npy_intp* nodeids_shape = new npy_intp[ndim-1];
    // Copy the shape except for the axis given.
    std::copy(shape, shape+axis, nodeids_shape);
    std::copy(shape+axis+1, shape+ndim, nodeids_shape+axis);
    PyArrayObject* nodeids = reinterpret_cast<PyArrayObject*>(
                                PyArray_SimpleNew(ndim-1, nodeids_shape, NPY_ULONG));
    
    std::vector<REAL> d(num_labels);
    pyarray_index unaryterms_idx(ndim);
    for(pyarray_iterator it(nodeids); !it.atEnd(); ++it)
    {
        const pyarray_index& nodeids_idx = it.getIndex();
        // Extract unary terms for this node.
        std::copy(nodeids_idx.idx, nodeids_idx.idx+axis, &unaryterms_idx[0]);
        std::copy(nodeids_idx.idx+axis, nodeids_idx.idx+nodeids_idx.ndim, &unaryterms_idx[axis+1]);
        // std::copy(nodeids_idx.idx, nodeids_idx.idx+nodeids_idx.ndim, &unaryterms_idx[1]);
        for(int j=0; j<num_labels; ++j)
        {
            unaryterms_idx[axis] = j;
            d[j] = PyArray_SafeGet<REAL>(unaryterms, unaryterms_idx);
        }
        
        // Create the node.
        typename MRFEnergy<T>::NodeId id = mrfenergy.AddNode(LocalSize(num_labels), NodeData(d));
        
        // Store the node.
        PyArray_SafeSet<numeric_pointer>(nodeids, nodeids_idx, reinterpret_cast<numeric_pointer>(id));
    }
    
    delete [] nodeids_shape;
    
    return py::object(nodeids);
}
Пример #5
0
py::object get_solution(MRFEnergy<T>& mrfenergy, const PyArrayObject* nodeids)
{
    typedef typename MRFEnergy<T>::NodeId NodeId;
    typedef typename T::Label Label;
    
    int ndim = PyArray_NDIM(nodeids);
    npy_intp* shape = PyArray_DIMS(nodeids);
    PyArrayObject* solution = reinterpret_cast<PyArrayObject*>(
                                PyArray_SimpleNew(ndim, shape, (mpl::at<numpy_typemap,Label>::type::value)));
    
    for(pyarray_iterator it(nodeids); !it.atEnd(); ++it)
    {
        NodeId id = reinterpret_cast<NodeId>(PyArray_SafeGet<numeric_pointer>(nodeids, it.getIndex()));
        Label label = mrfenergy.GetSolution(id);
        PyArray_SafeSet(solution, it.getIndex(), label);
    }
    
    return py::object(solution);
}
Пример #6
0
py::object minimize_bp(MRFEnergy<T>& mrfenergy,
    typename T::REAL eps=-1, int itermax=50,
    int printiter=5, int printminiter=0, bool details=false)
{
    typename MRFEnergy<T>::Options opt;
    opt.m_eps = eps;
    opt.m_iterMax = itermax;
    opt.m_printIter = printiter;
    opt.m_printMinIter = printminiter;
    
    std::vector<int> iterVector;
    std::vector<typename T::REAL> energyVector;
    int num_iters = mrfenergy.Minimize_BP(opt, iterVector, energyVector);
    
    if(details)
        return py::make_tuple(vector2pylist(iterVector), vector2pylist(energyVector));
    else
        return py::make_tuple(num_iters, energyVector.back());
}
Пример #7
0
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)));
    }
}
Пример #8
0
///-----------------------------------------------------------------------------
//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;
}