Code Monkey home page Code Monkey logo

pydensecrf's Introduction

PyDenseCRF

This is a (Cython-based) Python wrapper for Philipp Krähenbühl's Fully-Connected CRFs (version 2, new, incomplete page).

If you use this code for your reasearch, please cite:

Efficient Inference in Fully Connected CRFs with Gaussian Edge Potentials
Philipp Krähenbühl and Vladlen Koltun
NIPS 2011

and provide a link to this repository as a footnote or a citation.

Installation

The package is on PyPI, so simply run pip install pydensecrf to install it.

If you want the newest and freshest version, you can install it by executing:

pip install git+https://github.com/lucasb-eyer/pydensecrf.git

and ignoring all the warnings coming from Eigen.

Note that you need a relatively recent version of Cython (at least version 0.22) for this wrapper, the one shipped with Ubuntu 14.04 is too old. (Thanks to Scott Wehrwein for pointing this out.) I suggest you use a virtual environment and install the newest version of Cython there (pip install cython), but you may update the system version by

sudo apt-get remove cython
sudo pip install -U cython

Problems on Windows/VS

Since this library needs to compile C++ code, installation can be a little more problematic than pure Python packages. Make sure to have Cython installed or try installing via conda instead if you are getting problems. PRs that improve Windows support are welcome.

Problems on Colab/Kaggle Kernel

pydensecrf does not come pre-installed in Colab or Kaggle Kernel. Running pip install pydensecrf will result into build failures. Follow these steps instead for Colab/Kaggle Kernel:

pip install -U cython
pip install git+https://github.com/lucasb-eyer/pydensecrf.git

Usage

For images, the easiest way to use this library is using the DenseCRF2D class:

import numpy as np
import pydensecrf.densecrf as dcrf

d = dcrf.DenseCRF2D(640, 480, 5)  # width, height, nlabels

Unary potential

You can then set a fixed unary potential in the following way:

U = np.array(...)     # Get the unary in some way.
print(U.shape)        # -> (5, 480, 640)
print(U.dtype)        # -> dtype('float32')
U = U.reshape((5,-1)) # Needs to be flat.
d.setUnaryEnergy(U)

# Or alternatively: d.setUnary(ConstUnary(U))

Remember that U should be negative log-probabilities, so if you're using probabilities py, don't forget to U = -np.log(py) them.

Requiring the reshape on the unary is an API wart that I'd like to fix, but don't know how to without introducing an explicit dependency on numpy.

Note that the nlabels dimension is the first here before the reshape; you may need to move it there before reshaping if that's not already the case, like so:

print(U.shape)  # -> (480, 640, 5)
U = U.transpose(2, 0, 1).reshape((5,-1))

Getting a Unary

There's two common ways of getting unary potentials:

  1. From a hard labeling generated by a human or some other processing. This case is covered by from pydensecrf.utils import unary_from_labels.

  2. From a probability distribution computed by, e.g. the softmax output of a deep network. For this, see from pydensecrf.utils import unary_from_softmax.

For usage of both of these, please refer to their docstrings or have a look at the example.

Pairwise potentials

The two-dimensional case has two utility methods for adding the most-common pairwise potentials:

# This adds the color-independent term, features are the locations only.
d.addPairwiseGaussian(sxy=(3,3), compat=3, kernel=dcrf.DIAG_KERNEL, normalization=dcrf.NORMALIZE_SYMMETRIC)

# This adds the color-dependent term, i.e. features are (x,y,r,g,b).
# im is an image-array, e.g. im.dtype == np.uint8 and im.shape == (640,480,3)
d.addPairwiseBilateral(sxy=(80,80), srgb=(13,13,13), rgbim=im, compat=10, kernel=dcrf.DIAG_KERNEL, normalization=dcrf.NORMALIZE_SYMMETRIC)

Both of these methods have shortcuts and default-arguments such that the most common use-case can be simplified to:

d.addPairwiseGaussian(sxy=3, compat=3)
d.addPairwiseBilateral(sxy=80, srgb=13, rgbim=im, compat=10)

The parameters map to those in the paper as follows: sxy in the Gaussian case is $\theta_{\gamma}$, and in the Bilateral case, sxy and srgb map to $\theta_{\alpha}$ and $\theta_{\beta}$, respectively. The names are shorthand for "x/y standard-deviation" and "rgb standard-deviation" and for reference, the formula is:

Equation 3 in the original paper

Non-RGB bilateral

An important caveat is that addPairwiseBilateral only works for RGB images, i.e. three channels. If your data is of different type than this simple but common case, you'll need to compute your own pairwise energy using utils.create_pairwise_bilateral; see the generic non-2D case for details.

A good example of working with Non-RGB data is provided as a notebook in the examples folder.

Compatibilities

The compat argument can be any of the following:

  • A number, then a PottsCompatibility is being used.
  • A 1D array, then a DiagonalCompatibility is being used.
  • A 2D array, then a MatrixCompatibility is being used.

These are label-compatibilites µ(xi, xj) whose parameters could possibly be learned. For example, they could indicate that mistaking bird pixels for sky is not as bad as mistaking cat for sky. The arrays should have nlabels or (nlabels,nlabels) as shape and a float32 datatype.

Kernels

Possible values for the kernel argument are:

  • CONST_KERNEL
  • DIAG_KERNEL (the default)
  • FULL_KERNEL

This specifies the kernel's precision-matrix Λ(m), which could possibly be learned. These indicate correlations between feature types, the default implying no correlation. Again, this could possiblty be learned.

Normalizations

Possible values for the normalization argument are:

  • NO_NORMALIZATION
  • NORMALIZE_BEFORE
  • NORMALIZE_AFTER
  • NORMALIZE_SYMMETRIC (the default)

Kernel weight

I have so far not found a way to set the kernel weights w(m). According to the paper, w(2) was set to 1 and w(1) was cross-validated, but never specified. Looking through Philip's code (included in pydensecrf/densecrf), I couldn't find such explicit weights, and my guess is they are thus hard-coded to 1. If anyone knows otherwise, please open an issue or, better yet, a pull-request. Update: user @waldol1 has an idea in this issue. Feel free to try it out!

Inference

The easiest way to do inference with 5 iterations is to simply call:

Q = d.inference(5)

And the MAP prediction is then:

map = np.argmax(Q, axis=0).reshape((640,480))

If you're interested in the class-probabilities Q, you'll notice Q is a wrapped Eigen matrix. The Eigen wrappers of this project implement the buffer interface and can be simply cast to numpy arrays like so:

proba = np.array(Q)

Step-by-step inference

If for some reason you want to run the inference loop manually, you can do so:

Q, tmp1, tmp2 = d.startInference()
for i in range(5):
    print("KL-divergence at {}: {}".format(i, d.klDivergence(Q)))
    d.stepInference(Q, tmp1, tmp2)

Generic non-2D

The DenseCRF class can be used for generic (non-2D) dense CRFs. Its usage is exactly the same as above, except that the 2D-specific pairwise potentials addPairwiseGaussian and addPairwiseBilateral are missing.

Instead, you need to use the generic addPairwiseEnergy method like this:

d = dcrf.DenseCRF(100, 5)  # npoints, nlabels

feats = np.array(...)  # Get the pairwise features from somewhere.
print(feats.shape)     # -> (7, 100) = (feature dimensionality, npoints)
print(feats.dtype)     # -> dtype('float32')

dcrf.addPairwiseEnergy(feats)

In addition, you can pass compatibility, kernel and normalization arguments just like in the 2D gaussian and bilateral cases.

The potential will be computed as w*exp(-0.5 * |f_i - f_j|^2).

Pairwise potentials for N-D

User @markusnagel has written a couple numpy-functions generalizing the two classic 2-D image pairwise potentials (gaussian and bilateral) to an arbitrary number of dimensions: create_pairwise_gaussian and create_pairwise_bilateral. You can access them as from pydensecrf.utils import create_pairwise_gaussian and then have a look at their docstring to see how to use them.

Learning

The learning has not been fully wrapped. If you need it, get in touch or better yet, wrap it and submit a pull-request!

Here's a pointer for starters: issue#24. We need to wrap the gradients and getting/setting parameters. But then, we also need to do something with these, most likely call minimizeLBFGS from optimization.cpp. It should be relatively straightforward to just follow the learning examples included in the original code.

Common Problems

undefined symbol when importing

If while importing pydensecrf you get an error about some undefined symbols (for example .../pydensecrf/densecrf.so: undefined symbol: _ZTINSt8ios_base7failureB5cxx11E), you most likely are inadvertently mixing different compilers or toolchains. Try to see what's going on using tools like ldd. If you're using Anaconda, running conda install libgcc might be a solution.

ValueError: Buffer dtype mismatch, expected 'float' but got 'double'

This is a pretty common user error. It means exactly what it says: you are passing a double but it wants a float. Solve it by, for example, calling d.setUnaryEnergy(U.astype(np.float32)) instead of just d.setUnaryEnergy(U), or using float32 in your code in the first place.

My results are all pixelated like MS Paint's airbrush tool!

You screwed up reshaping somewhere and treated the class/label dimension as spatial dimension. This is you misunderstanding NumPy's memory layout and nothing that PyDenseCRF can detect or help with.

This mistake often happens for the Unary, see the Note in that section of the README.

Maintaining

These are instructions for maintainers about how to release new versions. (Mainly instructions for myself.)

# Go increment the version in setup.py
> python setup.py build_ext
> python setup.py sdist
> twine upload dist/pydensecrf-VERSION_NUM.tar.gz

And that's it. At some point, it would be cool to automate this on TravisCI, but not worth it yet. At that point, looking into creating "manylinux" wheels might be nice, too.

Testing

Thanks to @MarvinTeichmann we now have proper tests, install the package and run py.test. Maybe there's a better way to run them, but both of us don't know 😄

pydensecrf's People

Contributors

alexlyzhov avatar li-plus avatar lucasb-eyer avatar markusnagel avatar marvinteichmann avatar maximlt avatar reynoldscem avatar rodrigob avatar rogerqi avatar sayakpaul avatar soravux avatar stulling avatar swehrwein avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pydensecrf's Issues

Problem installation windows

Hi, recently i tried to reinstall the librairy on a Windows computer and got the following error:

" LINK : error LNK2001: unresolved external symbol PyInit_pydensecrf/eigen
build\temp.win-amd64-3.6\Release\pydensecrf\eigen.cp36-win_amd64.lib : fatal error LNK1120: 1 unresolved externals
error: command 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe' failed with exit status 1120"

But the installation works well on a linux computer with the same version of pip and python:
pip version = 9.0.1
python version = 3.6.3

Do you have any idea on where the problem could be?

Segmentation Fault at Permutohedral.cpp

First of all, thank you for the wrapper :)

I'm getting a segmentation fault error when I call the inference method.

I did a traceback with gdb; It is the Permutohedral's code causing the error.

Program received signal SIGSEGV, Segmentation fault.
Permutohedral::sseCompute (this=, out=0x76e5750, in=0x76e5750, value_size=263169, reverse=false) at densecrf/src/permutohedral.cpp:551
551 values[ o*sse_value_size+k ] += w * sse_val[k];

Do you have any guess about the reason?

Thank you in advance.

Soner

Problem with non-RGB input image

Hi Lucas,

I recently started using your wrapper for Phillip Krahenbuhl's fully connected CRFs. Very useful -- thanks for making this available!

I'm working through a simple example, to make sure that I understand the usage, and I came across something a bit strange. If I input an image that doesn't have 3 channels (eg, it could be grayscale, or a feature map with more than 3 channels), I get a nonsense output. I understand that typical usage would be for RGB images, but is there a way to use images without exactly 3 channels?

Here is a gist with an example: https://gist.github.com/DaveRichmond-/3d4b45f06a1fedb2527dae3a0856b213

Thanks for your help.

Best,
Dave

Training

If I were to introduce a pure pythonic way of training with some kind of grid-search, instead of interfacing with the C code, do you think it would make sense?

To get : sx, sy, sr, sg, sb for the gaussian and bilateral functions

I'd put in a bunch of parameters, and see for which the error over my dataset is the least, and use those at test time. Does it make sense, or do I have to do more?

ValueError: Buffer dtype mismatch, expected 'unsigned char' but got 'double'

Hello, when I execute this sentence will be incorrect, please help me to solve it, thank you very much:

d.addPairwiseBilateral(sxy=sxy_bilateral, compat=compat_bilateral,
kernel=kernel_bilateral, normalization=normalisation_bilateral,
srgb=srgb_bilateral, rgbim=img[0])

ValueError: Buffer dtype mismatch, expected 'unsigned char' but got 'double'

Can't import the library

Hi,

I am trying to install this library with pip install. The library seemed to be successfully installed. My cython is v 0.24.1. But when I tried to import pydensecrf.densecrf, I got .../pydensecrf/densecrf.so: undefined symbol: _ZTINSt8ios_base7failureB5cxx11E error.

I would really appreciate if anyone could help me with this?

Kernel Weights

I have an idea on how kernel weights might be set in the code. You have a note on the README asking for explanations.

In the 2011 paper (Eq. 2), the label compatibility matrix appears outside the sum over kernel responses. However, both the addPairwiseGaussian() and addPairwiseBilateral() functions in the code accept an arbitrary label compatibility matrix. By controlling the relative magnitude of the matrices, you can effectively set the kernel weights.

Based on your understanding of Philipp's code, is this correct?

Turn into "proper" package for utils.

See comments in #6, we'd like to make them easily available.

This issue serves as a reminder to myself, and as an indicator to others that this is indeed intended to happen.

issue with installing.

Hey, I tried to install the package. It installed properly. But when I tried to actually use it in python, this is what I am getting. Any idea why? I am using python 2.7. Also, I ran the setup.py file manually : python setup.py build_ext --inplace and I am using windows if that matters.

warning: pydensecrf\densecrf.pyx:20:4: Unreachable code

Error compiling Cython file:
------------------------------------------------------------
...
cimport eigen


cdef LabelCompatibility* _labelcomp(compat) except NULL:
    if isinstance(compat, Number):
        return new PottsCompatibility(compat)
                  ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:13:19: Operation only allowed in c++

Error compiling Cython file:
------------------------------------------------------------
...

cdef LabelCompatibility* _labelcomp(compat) except NULL:
    if isinstance(compat, Number):
        return new PottsCompatibility(compat)
    elif memoryview(compat).ndim == 1:
        return new DiagonalCompatibility(eigen.c_vectorXf(compat))
                  ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:15:19: Operation only allowed in c++

Error compiling Cython file:
------------------------------------------------------------
...
    if isinstance(compat, Number):
        return new PottsCompatibility(compat)
    elif memoryview(compat).ndim == 1:
        return new DiagonalCompatibility(eigen.c_vectorXf(compat))
    elif memoryview(compat).ndim == 2:
        return new MatrixCompatibility(eigen.c_matrixXf(compat))
                  ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:17:19: Operation only allowed in c++

Error compiling Cython file:
------------------------------------------------------------
...
        return ptr

    # It might already be deleted by the library, actually.
    # Yeah, pretty sure it is.
    def __dealloc__(self):
        del self.thisptr
       ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:36:8: Operation only allowed in c++

Error compiling Cython file:
------------------------------------------------------------
...
        del self.thisptr


cdef class ConstUnary(Unary):
    def __cinit__(self, float[:,::1] u not None):
        self.thisptr = new ConstUnaryEnergy(eigen.c_matrixXf(u))
                          ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:41:27: Operation only allowed in c++

Error compiling Cython file:
------------------------------------------------------------
...
        self.thisptr = new ConstUnaryEnergy(eigen.c_matrixXf(u))


cdef class LogisticUnary(Unary):
    def __cinit__(self, float[:,::1] L not None, float[:,::1] f not None):
        self.thisptr = new LogisticUnaryEnergy(eigen.c_matrixXf(L), eigen.c_matrixXf(f))
                          ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:46:27: Operation only allowed in c++

Error compiling Cython file:
------------------------------------------------------------
...
        # 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)
                            ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:58:29: Operation only allowed in c++

Error compiling Cython file:
------------------------------------------------------------
...

    def __dealloc__(self):
        # Because destructors are virtual, this is enough to delete any object
        # of child classes too.
        if self._this:
            del self._this
           ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:69:12: Operation only allowed in c++

Error compiling Cython file:
------------------------------------------------------------
...
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)
                                           ^
------------------------------------------------------------

pydensecrf\densecrf.pyx:109:44: Operation only allowed in c++
Traceback (most recent call last):

  File "<ipython-input-6-5cbb70704c71>", line 1, in <module>
    runfile('C:/Users/konar/ECSE DEEPMEDIC/pydensecrf/densecrf3d.py', wdir='C:/Users/konar/ECSE DEEPMEDIC/pydensecrf')

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
    execfile(filename, namespace)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\spyder\utils\site\sitecustomize.py", line 87, in execfile
    exec(compile(scripttext, filename, 'exec'), glob, loc)

  File "C:/Users/konar/ECSE DEEPMEDIC/pydensecrf/densecrf3d.py", line 7, in <module>
    import pydensecrf.densecrf as dcrf

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\pyximport\pyximport.py", line 458, in load_module
    language_level=self.language_level)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\pyximport\pyximport.py", line 233, in load_module
    exec("raise exc, None, tb", {'exc': exc, 'tb': tb})

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\pyximport\pyximport.py", line 215, in load_module
    inplace=build_inplace, language_level=language_level)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\pyximport\pyximport.py", line 191, in build_module
    reload_support=pyxargs.reload_support)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\pyximport\pyxbuild.py", line 102, in pyx_to_dll
    dist.run_commands()

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\distutils\dist.py", line 953, in run_commands
    self.run_command(cmd)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\distutils\dist.py", line 972, in run_command
    cmd_obj.run()

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\Cython\Distutils\old_build_ext.py", line 186, in run
    _build_ext.build_ext.run(self)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\distutils\command\build_ext.py", line 340, in run
    self.build_extensions()

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\site-packages\Cython\Distutils\old_build_ext.py", line 194, in build_extensions
    self.build_extension(ext)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\distutils\command\build_ext.py", line 499, in build_extension
    depends=ext.depends)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\distutils\msvc9compiler.py", line 473, in compile
    self.initialize()

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\distutils\msvc9compiler.py", line 383, in initialize
    vc_env = query_vcvarsall(VERSION, plat_spec)

  File "C:\Users\konar\Anaconda3\envs\py27theano\lib\distutils\msvc9compiler.py", line 271, in query_vcvarsall
    raise DistutilsPlatformError("Unable to find vcvarsall.bat")

ImportError: Building module pydensecrf.densecrf failed: ['DistutilsPlatformError: Unable to find vcvarsall.bat\n']

Thanks,
Abhisek

Modify Q between inference steps

Hello,

I am using your code and for some reason, I would need to modify Q between the steps.
It means that I want to modify the initial point of each inference step (not let it be the output of the previous step by default). Is it something that can easily be handled with your implementation?

Let's say, for instance that I want to do something like:

for s in steps:
d.stepInference(Q, tmp1, tmp2)
Q = 0.5_Q + 0.5_my_Q

Of course, this doesn't work and I get the following error:

"Argument 'Q' has incorrect type (expected pydensecrf.eigen.MatrixXf, got numpy.ndarray)"

Cheers.

Pierre

Questions on CRF model edge

Hi, thank you very much for code. But I have some questions when I use this code.

My task is to cluster some points, not image. Here some points are connected but some are not. Say, I have 100 points. So I build a crf model by code below(in your demo).

d = dcrf.DenseCRF(100, 5) # npoints, nlabels

feats = np.array(...) # Get the pairwise features from somewhere.
print(feats.shape) # -> (7, 100) = (feature dimensionality, npoints)
print(feats.dtype) # -> dtype('float32')

dcrf.addPairwiseEnergy(feats)

My question is, here how could I set the point connectivity? For example, point 1 is connected with point 2, but not point 3. Can I set the edge?
If I can't, does this mean that all the points are connected?

Looking forward to your reply. Thank you!

confidence score

Hi,

I am not familiar with denseCRF but I am wondering would it be possible (or make sense) to obtain confidence score for prediction at each pixel from Q ? Thanks.

Best,
Zheng

About the compat parameter

Dear @lucasb-eyer
I am trying to apply dense CRF postprocessing to semantically labeled images (which are computed by deep learning techniques). Reading the commits in this repository i saw that the compat parameter denotes the compatibility function mentioned in the paper which adopts the Potts model [ related commit: https://github.com/lucasb-eyer/pydensecrf/commit/a9d7be19fc1a149915a15f084e9936aec5a52cef ]

However, I donot understand what does it mean to assign a constant value to this parameter. For example at the code below, what does it mean compatibility function is assigned as 3:

    d.addPairwiseGaussian(sxy=(3,3), compat=3,
                          kernel=dcrf.DIAG_KERNEL, normalization=dcrf.NORMALIZE_SYMMETRIC)

   d.addPairwiseBilateral(sxy=(30,30), compat=10,
                               kernel=dcrf.DIAG_KERNEL, normalization=dcrf.NORMALIZE_SYMMETRIC,
                               srgb=(3,3,3), rgbim=img[0])

Does it mean that only 3-pixel neighborhoods are considered to penalize differently labeled pixels? Because the equation given at the paper is mu(x_i,x_j) = 1 if x_i != x_j and 0 otherwise. So where we include that constant value in this equation???

Question about running my own data

Hi I have a quick question about how to run my own image data just like the example.

I have a prediction image from residual neural network, with two classes, 0 for background and 1 for target object. I try to run the the inference.py to refine my contour, but things goes ugly. The output value is "1" for all pixel.

I am guessing that my prediction results miss "unclear" or "unknown" value, thus can not run your method. Is that the case ?

Best
He Zhao

Running a dense CRF on classifier predictions from a neural network

Hi,

Thank you for sharing this code. I have a deep learning classifier that specifies probability values for three classes at each pixel in an image. I would like to run the dense CRF to clean up my predictions. Here is the code that I'm trying to use.

`

Define the CRF (width, height, nlabels)

Predictions is a numpy array from my classifier, for a three class classification problem

d = dcrf.DenseCRF2D(predictions.shape[1], predictions.shape[0], 3)

Unary potentials

U = predictions.reshape((3, -1))
d.setUnaryEnergy(-np.log(U))

Pairwise potentials

d.addPairwiseGaussian(sxy=(3,3), compat=3, kernel=dcrf.DIAG_KERNEL, normalization = dcrf.NORMALIZE_SYMMETRIC)

Inference

Q = d.inference(5)

map = np.argmax(Q, axis=0).reshape((predictions.shape[0], predictions.shape[1]))

proba = np.array(map)

Write to a MAT file

scipy.io.savemat("CRF_Predictions.mat", mdict={'proba': proba})`

Here is my original predictions:
image

This is the ground truth:
image

This is what I get after I run the code above:
image

If anyone can tell me where I am making a mistake, that will be really helpful.

Thanks,
Chaitanya

How to use gradient function in densecrf.pyx?

Hi, I tried to use the commented out gradient function in densecrf.pxd. Now I can call it in python but it fails and the python stops working. Is there any advice for me to continue or turn to other methods to implement it in a learning?Thank u very much

Issue with inference method

Just like what I've described before. Here attached the example code and the images. You can put them in the same folder and have a try. I'm using 3D images. The test image is the labeled image after training a random forest regressor and testing the origin image. What I want to do is to perform a post process of the labeled image to reduce the noise and increase the classification rate and dice metric.
origin.nii.gz
test.nii.gz
Issue.txt
You need to change the 'Issue.txt' to 'Issue.py' as GitHub doesn't allow me to upload a Python file.

Thanks a lot.

Bad shape for unary energy

Hi Lukas,

I see the above error while running the densecrf. i will list down the steps here:

d = dcrf.DenseCRF2D(224, 224, 8)
U = unary_from_softmax(unary) # Unary is output of softmax
d.setUnaryEnergy(U)

Here is get the above error: Bad shape for unary energy (Need (224, 224), got (8, 50176))

I think a similar bug is fixed in a commit (b5e13a9). could you please update the same for the setUnaryEnergy method also?

addPairwiseBilateral for densecrf2d in densecrf.pyx file

Hey, I was going through the original cpp code for the addPairwiseBilateral for denseCRF2D and there the array they pass, im, seem to be of the dimension [(w_*h_*3), 1], but in the .pyx file it checks for the size of the im array to be of [w_ , h_ , 3]. Can someone please explain to me this part? Sorry, I am kind of new to this. So, having an issue understanding how the stuff actually works.

Thanks,

ImportError: No module named densecrf

Hai,

I installed densecrf module using
python setup.py install

It got installed succesfully.
import pydensecrf---->works
import pydensecrf.densecrf as dcrf----> fails with Import error..

Kindly suggest how to go further

Package import problem

I've successfully installed the library using:

pip install git+https://github.com/lucasb-eyer/pydensecrf.git

Now I've got 4 files in /usr/lib64/python2.7/site-packages/pydensecrf:

densecrf.so  eigen.so  utils.py  utils.pyc

However, I cannot import the library in Python. Both:

import pydensecrf.densecrf
import densecrf

are unsuccessful (/usr/lib64/python2.7/site-packages/ is in sys.path). If I explicitly append /usr/lib64/python2.7/site-packages/pydensecrf to sys.path, then Python can locate the densecrf library (import densecrf), but I get an import error:

ImportError: No module named pydensecrf.eigen

The problem has been observed under CentOS 7 and Debian Jessie.

How to train CRF on multiple images

Hello,

I'm testing this CRF implementation and was wondering is there an easy way to train CRF on multiple images. Do you just fill the crf object with new unary and pairwise potentials and repeat training with new objective function?

Luka

Always getting image with zero MAP after inference

I am using the library to post process road segmentation, which is just pixel-level binary classification problem, to classify each pixel as 'road' or 'no road'.

My code looks as following:

pil_im = np.asarray(Image.open('example_image.jpg', 'r'))
probs = model.predict(pil_im.reshape((1,1024,1024,3))/255)

unary = softmax_to_unary(probs)
unary = np.ascontiguousarray(unary)

d = dcrf.DenseCRF(pil_im.shape[0] * pil_im.shape[1], 1)
d.setUnaryEnergy(unary)

feats = create_pairwise_gaussian(sdims=(10, 10), shape=pil_im.shape[:2])

d.addPairwiseEnergy(feats, compat=3,
                    kernel=dcrf.DIAG_KERNEL,
                    normalization=dcrf.NORMALIZE_SYMMETRIC)
feats = create_pairwise_bilateral(sdims=(50, 50), schan=(20, 20, 20),
                                   img=pil_im, chdim=2)
d.addPairwiseEnergy(feats, compat=10,
                     kernel=dcrf.DIAG_KERNEL,
                     normalization=dcrf.NORMALIZE_SYMMETRIC)

Q = d.inference(10)
res = np.argmax(Q, axis=0).reshape((pil_im.shape[0], pil_im.shape[1]))
print(res.max())

I always get res to be matrix of 0.0 . I have tried following things:

  1. Change it to use 2 channels with probability of foreground and background.
  2. Changing sdims params.
  3. Running inference longer.

Nothing helps and I always get matrix with 0.0 values.

If it helps, pil_img looks like this and probs looks like this after thresholding at 0.5.

Also I tried to print KL values at each step of inference. Doesn't seem like it's improving at all.

KL-divergence at 0: 30498.999462480373
KL-divergence at 1: 30498.999462480373
KL-divergence at 2: 30498.999462480373
KL-divergence at 3: 30498.999462480373
KL-divergence at 4: 30498.999462480373
KL-divergence at 5: 30498.999462480373
KL-divergence at 6: 30498.999462480373
KL-divergence at 7: 30498.999462480373
KL-divergence at 8: 30498.999462480373
KL-divergence at 9: 30498.999462480373
KL-divergence at 10: 30498.999462480373
KL-divergence at 11: 30498.999462480373
KL-divergence at 12: 30498.999462480373
KL-divergence at 13: 30498.999462480373
KL-divergence at 14: 30498.999462480373
KL-divergence at 15: 30498.999462480373
KL-divergence at 16: 30498.999462480373
KL-divergence at 17: 30498.999462480373
KL-divergence at 18: 30498.999462480373
KL-divergence at 19: 30498.999462480373

EDIT:
I tried with original cpp code by changing the label counts M to be 2 and making the library. I tried both dense_learning.cpp and dense_inference.cpp using following command:

./dense_learning image.ppm mask.ppm final_mask.ppm

I still get the final image as just background color.

win64 python3.5 support?

Failed to compile on win 64bit, python 3.5. Python 3.6 seems to compile. Using Anaconda, VC++ 14

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:C:\Users\Adi\Miniconda3\envs\python35\libs /LIBPATH:C:\Users\Adi\Miniconda3\envs\python35\PCbuild\amd64 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\lib\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.10240.0\ucrt\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\8.1\lib\winv6.3\um\x64" /EXPORT:PyInit_pydensecrf/densecrf build\temp.win-amd64-3.5\Release\pydensecrf/densecrf.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/src/densecrf.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/src/unary.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/src/pairwise.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/src/permutohedral.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/src/optimization.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/src/objective.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/src/labelcompatibility.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/src/util.obj build\temp.win-amd64-3.5\Release\pydensecrf/densecrf/external/liblbfgs/lib/lbfgs.obj /OUT:build\lib.win-amd64-3.5\pydensecrf/densecrf.cp35-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.5\Release\pydensecrf\densecrf.cp35-win_amd64.lib
> LINK : error LNK2001: unresolved external symbol PyInit_pydensecrf/densecrf

Unable to Import in conda environment, throws undefined symbol "PyFPE_jbuf" pydensecrf/densecrf.so. How to resolve?

I installed the library using pip and it was installed successfully. It works fine in root conda, but when I tried to access in one of conda environment it throws the following error:

/.local/lib/python2.7/site-packages/pydensecrf/densecrf.so: undefined symbol: PyFPE_jbuf

While initial search on google it ask for some conflict in numpy. I tried uninstalling and installing using pip but still the same issue. I would appreciate, if you can let me know for any clues to resolve this.

Thanks

Unary potential

@lucasb-eyer Hi lucas, can you tell me how does unary potential calculated in your code? It seems that you just use the "class probabilities per pixel" to calculate unary potential. While the paper use information of the original image, e.g. color, location... Can you give me tips? Thanks!
image

gt_prob question

Hello,

How is the gt_prob parameter in unary_from_labels() used in the original paper?

Is it only applied to MSRC-21 dataset?

Hi lucasb-eyer,

I am working on post-processing the output of CNN using densecrf on PASCAL VOC dataset. It seems your code doesn't works on it. Is it only applied to MSRC-21 dataset? If so, would you be willing to public your training/learning code?

Looking forward your reply. Thank you in advance.

                                                                                                            Carrie

Bad shape for unary energy

Hi Lucas,

I'm trying to run pydensecrf on a new computer. I just installed everything and I get a new bug (everything was working fine with previous installation a few months ago).

I think the easiest way to confirm the problem is to run the example: Non RGB Example. Stepping through this example, in Cell #4 I get the following error:

ValueError: Bad shape for unary energy (Need (400, 512), got (2, 204800))

Looking into the code a little bit further, I see the following "TODO" item (copied at end of message). I'm rather confused, because it seems like my unary energy is the correct shape. Please advise.

Thanks,
Dave

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!

Fail to build library in virtualenv due to redeclaration of round() function

Hi Luca,
I tried to build/install library inside a virtual environment created by Anaconda3 but it failed, the error is:

pydensecrf/densecrf/src/permutohedral.cpp:31:26: error: ambiguating new declaration of 'int round(double)'
inline int round(double X) {
^
Looks like there is another round() function inside , I commented the following lines in permutohedral.cpp so It could build just fine.

//#ifdef WIN32
//inline int round(double X) {
// return int(X+.5);
//}
//#endif

Is it correct to do so?
Thanks,

Difference in colors

Hello,

I am getting the following result after running inference.py in /examples:
000057_kitti
out2

There is a missmatch between the colors. Is there a quick way to fix this?

Regards,
Atanas

Error when using own image for addPairwiseBilateral

Hi, I have tried to use my own image for the addPairwiseBilateral(sxy=80, srgb=13,, rgbim=own_image,compat=10) but I keep getting the following error.
I have tried reading my image from OpenCV as well as skimage.
My image dtype and shape returns the following:

uint8
(315, 480, 3)

And below is the error. Has anyone faced this before?

Traceback (most recent call last):
  File "postCRF.py", line 60, in <module>
    main()
  File "postCRF.py", line 54, in main
    d.addPairwiseBilateral(sxy=80, srgb=13, rgbim=image_sk, compat=10)
  File "pydensecrf/densecrf.pyx", line 118, in pydensecrf.densecrf.DenseCRF2D.addPairwiseBilateral (pydensecrf/densecrf.cpp:4343)
ValueError: Bad shape for pairwise bilateral (Need (480, 315, 3), got [315, 480, 3, 0, 0, 0, 0, 0])

Why is this package not on PyPI?

Why is this package not on PyPI, is there a particular reason? It would be extremely useful if it was, I know it is unrelated but I am having a lot of trouble getting to work as dependency for my own package because of it.

Import error for densecrf.so: "undefined symbol"

Using python 2.7.13 Anaconda 4.4.0 (64 bit) on Ubuntu 16.04
Installed pydensecrf from git as per instructions: no installation errors. However, when I issue

import pydensecrf.densecrf as dcrf

I get the following error

ImportError: /home/ryanelima/anaconda2/lib/python2.7/site-packages/pydensecrf/densecrf.so: undefined symbol: _ZTINSt8ios_base7failureB5cxx11E

I have tried uninstalling and reinstalling system cython and pip cython (both as user and root), but problem persists. Also tried

nm -C  /home/ryanelima/anaconda2/lib/python2.7/site-packages/pydensecrf/densecrf.so

Please advise

Thanks

buf2matf makes a copy of the feature map

In the experiments I'm currently running, the setup (call to addPairwiseEnergy) takes nearly as long as the inference itself. If the feature map is built transposed relative to the C++ code's convention, then we could simply wrap the raw data in an Eigen::MatrixXf and no copying would be necessary.

I'm planning to change this in my fork, and would be happy to create a PR, but it will break backwards compatibility by changing the interface. Specifically, the features that go into addPairwiseEnergy would need to have shape (npixels, nlabels).

How to get the hyperparameters?

Thanks for you wonderful work. I have trying inferring using your code, but it works not good. I'm wondering how to find the best hyperparameters? Have you implemented the learning procedure?

Help with wrapping learning

Hey, I'd like to use the learning part of the code and might as well come up with a wrapper. Any pointers on how/where to start?

ValueError: Buffer dtype mismatch, expected 'float' but got 'double'

Try below code and get ValueError.

import numpy as np
import pydensecrf.densecrf as dcrf
d = dcrf.DenseCRF(80, 2)
U = np.random.random(size=(2, 80))
d.setUnaryEnergy(U)
Traceback (most recent call last):
File "", line 1, in
d.setUnaryEnergy(U)
File "pydensecrf/densecrf.pyx", line 80, in pydensecrf.densecrf.DenseCRF.setUn
aryEnergy (pydensecrf/densecrf.cpp:3370)
ValueError: Buffer dtype mismatch, expected 'float' but got 'double'

Example Issue

In your example, the labels after relabelling is ranged from 0 - 2 and the M is equal to 3. But the map computed is ranged from 1 - 2 which means there is a class gone?
The result of the computation is quite wield in my case.

Getting segmentation fault for 3D crf

Hi,
I'm trying to run pydensecrf for 3D case, but getting segmentation fault when I call inference. Here's how I'm running it (not sure if this is the correct way):

# probs of shape 3d image per class: Nb_classes x Height x Width x Depth
# assume the image has shape (69, 51, 72)
shape = image.shape
new_image = np.empty(shape)
d = dcrf.DenseCRF(np.prod(shape), probs.shape[0])
U = unary_from_softmax(probs)
d.setUnaryEnergy(U)
feats = create_pairwise_gaussian(sdims=(1.0, 1.0, 1.0), shape=shape)
d.addPairwiseEnergy(feats, compat=3, kernel=dcrf.FULL_KERNEL, normalization=dcrf.NORMALIZE_SYMMETRIC)
Q = d.inference(5) 
new_image = np.argmax(Q, axis=0).reshape((shape[0], shape[1],shape[2]))

..and here is the backtrace:

#0  __memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S:116
#1  0x00007ffec011e4f9 in memcpy (__len=60, __src=0x15e11fdc, __dest=<optimized out>) at /usr/include/x86_64-linux-gnu/bits/string3.h:53
#2  Permutohedral::sseCompute (this=0x432e330, out=0x14ded4d0, in=0x14ded4d0, value_size=15, reverse=false) at pydensecrf/densecrf/src/permutohedral.cpp:546
#3  0x00007ffec0117f17 in DenseKernel::filter (transpose=false, in=..., out=..., this=0x432e320) at pydensecrf/densecrf/src/pairwise.cpp:74
#4  DenseKernel::apply (Q=..., out=..., this=0x432e320) at pydensecrf/densecrf/src/pairwise.cpp:124
#5  PairwisePotential::apply (this=0x95187c0, out=..., Q=...) at pydensecrf/densecrf/src/pairwise.cpp:174
#6  0x00007ffec010ee1f in DenseCRF::inference (this=0x4c10b50, n_iterations=n_iterations@entry=3) at pydensecrf/densecrf/src/densecrf.cpp:125
#7  0x00007ffec00fd23c in __pyx_pf_10pydensecrf_8densecrf_8DenseCRF_10inference (__pyx_v_self=0x7ffec067e378, __pyx_v_niter=3) at pydensecrf/densecrf.cpp:3364
#8  __pyx_pw_10pydensecrf_8densecrf_8DenseCRF_11inference (__pyx_v_self=0x7ffec067e378, __pyx_arg_niter=<optimized out>) at pydensecrf/densecrf.cpp:3340
#9  0x00000000004ca15e in PyEval_EvalFrameEx ()
#10 0x00000000004c2765 in PyEval_EvalCodeEx ()
#11 0x00000000004c2509 in PyEval_EvalCode ()
#12 0x00000000004f1def in ?? ()
#13 0x00000000004ec652 in PyRun_FileExFlags ()
#14 0x00000000004eae31 in PyRun_SimpleFileExFlags ()
#15 0x000000000049e14a in Py_Main ()
#16 0x00007ffff7811830 in __libc_start_main (main=0x49dab0 <main>, argc=2, argv=0x7fffffffe218, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, 
    stack_end=0x7fffffffe208) at ../csu/libc-start.c:291
#17 0x000000000049d9d9 in _start ()

Could you please help me to figure out what am I doing wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.