-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
226a1d5
commit c248dd9
Showing
3 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
from .eigen cimport * | ||
|
||
|
||
cdef extern from "densecrf/include/labelcompatibility.h": | ||
cdef cppclass LabelCompatibility: | ||
pass | ||
|
||
cdef cppclass PottsCompatibility(LabelCompatibility): | ||
PottsCompatibility(float) except + | ||
|
||
cdef cppclass DiagonalCompatibility(LabelCompatibility): | ||
DiagonalCompatibility(const c_VectorXf&) except + | ||
|
||
cdef cppclass MatrixCompatibility(LabelCompatibility): | ||
MatrixCompatibility(const c_MatrixXf&) except + | ||
|
||
|
||
cdef extern from "densecrf/include/unary.h": | ||
cdef cppclass UnaryEnergy: | ||
pass | ||
|
||
cdef cppclass ConstUnaryEnergy(UnaryEnergy): | ||
ConstUnaryEnergy(const c_MatrixXf& unary) except + | ||
|
||
cdef cppclass LogisticUnaryEnergy(UnaryEnergy): | ||
LogisticUnaryEnergy(const c_MatrixXf& L, const c_MatrixXf& feature) except + | ||
|
||
|
||
cdef class Unary: | ||
cdef UnaryEnergy *thisptr | ||
cdef UnaryEnergy* move(self) | ||
|
||
|
||
cdef class ConstUnary(Unary): | ||
pass | ||
|
||
|
||
cdef class LogisticUnary(Unary): | ||
pass | ||
|
||
|
||
cdef extern from "densecrf/include/pairwise.h": | ||
cpdef enum NormalizationType: NO_NORMALIZATION, NORMALIZE_BEFORE, NORMALIZE_AFTER, NORMALIZE_SYMMETRIC | ||
cpdef enum KernelType: CONST_KERNEL, DIAG_KERNEL, FULL_KERNEL | ||
|
||
|
||
cdef extern from "densecrf/include/densecrf.h": | ||
cdef cppclass c_DenseCRF "DenseCRF": | ||
c_DenseCRF(int N, int M) except + | ||
|
||
# Setup methods. | ||
# TODO | ||
#void addPairwiseEnergy(PairwisePotential *potential) | ||
void addPairwiseEnergy(const c_MatrixXf &features, LabelCompatibility*, KernelType, NormalizationType) | ||
void setUnaryEnergy(UnaryEnergy *unary) | ||
void setUnaryEnergy(const c_MatrixXf &unary) | ||
void setUnaryEnergy(const c_MatrixXf &L, const c_MatrixXf &feature) | ||
|
||
# Inference methods. | ||
c_MatrixXf inference(int n_iterations) | ||
# TODO: Not enabled because it would require wrapping VectorXs (note the `s`) | ||
#c_VectorXs map(int n_iterations) | ||
|
||
# Step-by-step inference methods. | ||
c_MatrixXf startInference() const | ||
void stepInference(c_MatrixXf &Q, c_MatrixXf &tmp1, c_MatrixXf &tmp2) const | ||
#double gradient( int n_iterations, const ObjectiveFunction & objective, c_VectorXf * unary_grad, c_VectorXf * lbl_cmp_grad, c_VectorXf * kernel_grad=NULL ) const; | ||
|
||
double klDivergence(const c_MatrixXf &Q) const | ||
|
||
#c_VectorXf unaryParameters() const; | ||
#void setUnaryParameters( const c_VectorXf & v ); | ||
#c_VectorXf labelCompatibilityParameters() const; | ||
#void setLabelCompatibilityParameters( const c_VectorXf & v ); | ||
#c_VectorXf kernelParameters() const; | ||
#void setKernelParameters( const c_VectorXf & v ); | ||
|
||
|
||
cdef extern from "densecrf/include/densecrf.h": | ||
cdef cppclass c_DenseCRF2D "DenseCRF2D" (c_DenseCRF): | ||
c_DenseCRF2D(int W, int H, int M) except + | ||
|
||
void addPairwiseGaussian(float sx, float sy, LabelCompatibility*, KernelType, NormalizationType) | ||
void addPairwiseBilateral(float sx, float sy, float sr, float sg, float sb, const unsigned char *rgbim, LabelCompatibility*, KernelType, NormalizationType) | ||
|
||
|
||
cdef class DenseCRF: | ||
cdef c_DenseCRF *_this | ||
cdef int _nlabel | ||
cdef int _nvar | ||
|
||
|
||
cdef class DenseCRF2D(DenseCRF): | ||
cdef c_DenseCRF2D *_this2d | ||
cdef int _w | ||
cdef int _h |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# distutils: language = c++ | ||
# distutils: sources = pydensecrf/densecrf/src/densecrf.cpp pydensecrf/densecrf/src/unary.cpp pydensecrf/densecrf/src/pairwise.cpp pydensecrf/densecrf/src/permutohedral.cpp pydensecrf/densecrf/src/optimization.cpp pydensecrf/densecrf/src/objective.cpp pydensecrf/densecrf/src/labelcompatibility.cpp pydensecrf/densecrf/src/util.cpp pydensecrf/densecrf/external/liblbfgs/lib/lbfgs.c | ||
# distutils: include_dirs = pydensecrf/densecrf/include pydensecrf/densecrf/external/liblbfgs/include | ||
|
||
from numbers import Number | ||
|
||
import eigen | ||
from .eigen cimport * | ||
|
||
|
||
cdef LabelCompatibility* _labelcomp(compat) except NULL: | ||
if isinstance(compat, Number): | ||
return new PottsCompatibility(compat) | ||
elif memoryview(compat).ndim == 1: | ||
return new DiagonalCompatibility(c_vectorXf(compat)) | ||
elif memoryview(compat).ndim == 2: | ||
return new MatrixCompatibility(c_matrixXf(compat)) | ||
else: | ||
raise ValueError("LabelCompatibility of dimension >2 not meaningful.") | ||
return NULL # Important for the exception(s) to propagate! | ||
|
||
|
||
cdef class Unary: | ||
|
||
# Because all of the APIs that take an object of this type will | ||
# take ownership. Thus, we need to make sure not to delete this | ||
# upon destruction. | ||
cdef UnaryEnergy* move(self): | ||
ptr = self.thisptr | ||
self.thisptr = NULL | ||
return ptr | ||
|
||
# It might already be deleted by the library, actually. | ||
# Yeah, pretty sure it is. | ||
def __dealloc__(self): | ||
del self.thisptr | ||
|
||
|
||
cdef class ConstUnary(Unary): | ||
def __cinit__(self, float[:,::1] u not None): | ||
self.thisptr = new ConstUnaryEnergy(c_matrixXf(u)) | ||
|
||
|
||
cdef class LogisticUnary(Unary): | ||
def __cinit__(self, float[:,::1] L not None, float[:,::1] f not None): | ||
self.thisptr = new LogisticUnaryEnergy(c_matrixXf(L), c_matrixXf(f)) | ||
|
||
|
||
cdef class DenseCRF: | ||
|
||
def __cinit__(self, int nvar, int nlabels, *_, **__): | ||
# We need to swallow extra-arguments because superclass cinit function | ||
# will always be called with the same params as the subclass, automatically. | ||
|
||
# We also only want to avoid creating an object if we're just being called | ||
# from a subclass as part of the hierarchy. | ||
if type(self) is DenseCRF: | ||
self._this = new c_DenseCRF(nvar, nlabels) | ||
else: | ||
self._this = NULL | ||
|
||
self._nvar = nvar | ||
self._nlabel = nlabels | ||
|
||
def __dealloc__(self): | ||
# Because destructors are virtual, this is enough to delete any object | ||
# of child classes too. | ||
if self._this: | ||
del self._this | ||
|
||
def addPairwiseEnergy(self, float[:,::1] features not None, compat, KernelType kernel=DIAG_KERNEL, NormalizationType normalization=NORMALIZE_SYMMETRIC): | ||
if features.shape[1] != self._nvar: | ||
raise ValueError("Bad shape for pairwise energy (Need (?, {}), got {})".format(self._nvar, (features.shape[0], features.shape[1]))) | ||
|
||
self._this.addPairwiseEnergy(c_matrixXf(features), _labelcomp(compat), kernel, normalization) | ||
|
||
def setUnary(self, Unary u): | ||
self._this.setUnaryEnergy(u.move()) | ||
|
||
def setUnaryEnergy(self, float[:,::1] u not None, float[:,::1] f = None): | ||
if u.shape[0] != self._nlabel or u.shape[1] != self._nvar: | ||
raise ValueError("Bad shape for unary energy (Need {}, got {})".format((self._nlabel, self._nvar), (u.shape[0], u.shape[1]))) | ||
# TODO: I don't remember the exact shape `f` should have, so I'm not putting an assertion here. | ||
# If you get hit by a wrong shape of `f`, please open an issue with the necessary info! | ||
|
||
if f is None: | ||
self._this.setUnaryEnergy(c_matrixXf(u)) | ||
else: | ||
self._this.setUnaryEnergy(c_matrixXf(u), c_matrixXf(f)) | ||
|
||
def inference(self, int niter): | ||
return MatrixXf().wrap(self._this.inference(niter)) | ||
|
||
def startInference(self): | ||
return MatrixXf().wrap(self._this.startInference()), MatrixXf(), MatrixXf() | ||
|
||
def stepInference(self, MatrixXf Q, MatrixXf tmp1, MatrixXf tmp2): | ||
self._this.stepInference(Q.m, tmp1.m, tmp2.m) | ||
|
||
def klDivergence(self, MatrixXf Q): | ||
return self._this.klDivergence(Q.m) | ||
|
||
|
||
cdef class DenseCRF2D(DenseCRF): | ||
|
||
# The same comments as in the superclass' `__cinit__` apply here. | ||
def __cinit__(self, int w, int h, int nlabels, *_, **__): | ||
if type(self) is DenseCRF2D: | ||
self._this = self._this2d = new c_DenseCRF2D(w, h, nlabels) | ||
|
||
# Unfortunately, self._this2d.W_ and .H_ are protected in C++ and thus | ||
# we cannot access them from here for sanity-checks, so keep our own... | ||
self._w = w | ||
self._h = h | ||
|
||
# Also set these for the superclass | ||
self._nvar = w*h | ||
self._nlabel = nlabels | ||
|
||
def addPairwiseGaussian(self, sxy, compat, KernelType kernel=DIAG_KERNEL, NormalizationType normalization=NORMALIZE_SYMMETRIC): | ||
if isinstance(sxy, Number): | ||
sxy = (sxy, sxy) | ||
|
||
self._this2d.addPairwiseGaussian(sxy[0], sxy[1], _labelcomp(compat), kernel, normalization) | ||
|
||
def addPairwiseBilateral(self, sxy, srgb, unsigned char[:,:,::1] rgbim not None, compat, KernelType kernel=DIAG_KERNEL, NormalizationType normalization=NORMALIZE_SYMMETRIC): | ||
if isinstance(sxy, Number): | ||
sxy = (sxy, sxy) | ||
|
||
if isinstance(srgb, Number): | ||
srgb = (srgb, srgb, srgb) | ||
|
||
if rgbim.shape[0] != self._h or rgbim.shape[1] != self._w: | ||
raise ValueError("Bad shape for pairwise bilateral (Need {}, got {})".format((self._h, self._w, 3), rgbim.shape)) | ||
if rgbim.shape[2] != 3: | ||
raise ValueError("addPairwiseBilateral only works for RGB images. For other types, use `utils.create_pairwise_bilateral` to construct your own pairwise energy and add it through `addPairwiseEnergy`.") | ||
|
||
self._this2d.addPairwiseBilateral( | ||
sxy[0], sxy[1], srgb[0], srgb[1], srgb[2], &rgbim[0,0,0], _labelcomp(compat), kernel, normalization | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# coding: UTF-8 | ||
from setuptools import setup | ||
|
||
# TODO: | ||
# - Wrap learning. | ||
# - Make LabelCompatibility, UnaryEnergy, PairwisePotential extensible? (Maybe overkill?) | ||
|
||
|
||
# If Cython is available, build using Cython. | ||
# Otherwise, use the pre-built (by someone who has Cython, i.e. me) wrapper `.cpp` files. | ||
try: | ||
from Cython.Build import cythonize | ||
ext_modules = cythonize(['pydensecrf/eigen.pyx']) | ||
ext_modules = cythonize(['pydensecrf/densecrf.pyx']) | ||
except ImportError: | ||
from setuptools.extension import Extension | ||
ext_modules = [ | ||
Extension("pydensecrf/eigen", ["pydensecrf/eigen.cpp", "pydensecrf/eigen_impl.cpp"], language="c++", include_dirs=["pydensecrf/densecrf/include"]), | ||
Extension("pydensecrf/densecrf", ["pydensecrf/densecrf.cpp", "pydensecrf/densecrf/src/densecrf.cpp", "pydensecrf/densecrf/src/unary.cpp", "pydensecrf/densecrf/src/pairwise.cpp", "pydensecrf/densecrf/src/permutohedral.cpp", "pydensecrf/densecrf/src/optimization.cpp", "pydensecrf/densecrf/src/objective.cpp", "pydensecrf/densecrf/src/labelcompatibility.cpp", "pydensecrf/densecrf/src/util.cpp", "pydensecrf/densecrf/external/liblbfgs/lib/lbfgs.c"], language="c++", include_dirs=["pydensecrf/densecrf/include", "pydensecrf/densecrf/external/liblbfgs/include"]), | ||
] | ||
|
||
setup( | ||
name="pydensecrf", | ||
version="1.0rc2", | ||
description="A python interface to Philipp Krähenbühl's fully-connected (dense) CRF code.", | ||
long_description="See the README.md at http://github.com/lucasb-eyer/pydensecrf", | ||
author="Lucas Beyer", | ||
author_email="lucasb.eyer.be@gmail.com", | ||
url="http://github.com/lucasb-eyer/pydensecrf", | ||
ext_modules=ext_modules, | ||
packages=["pydensecrf"], | ||
setup_requires=['cython>=0.22'], | ||
classifiers=[ | ||
"Intended Audience :: Developers", | ||
"License :: OSI Approved :: MIT License", | ||
"Development Status :: 5 - Production/Stable", | ||
"Programming Language :: C++", | ||
"Programming Language :: Python", | ||
"Operating System :: POSIX :: Linux", | ||
"Topic :: Software Development :: Libraries", | ||
"Topic :: Scientific/Engineering :: Image Recognition", | ||
"Topic :: Scientific/Engineering :: Artificial Intelligence", | ||
], | ||
) |