This is a Python implementation of Moisan's periodic-plus-smooth decomposition of an image (L. Moisan, Periodic Plus Smooth Image Decomposition, Journal of Mathematical Imaging and Vision 39(2), 161–179) see doi:10.1007/s10851-010-0227-1 (published version), or hal-00388020 (archived version). See also the series of posts “On the periodic-plus-smooth decomposition of an image” on my blog.
The moisan2011 module is released under a BSD 3-clause license (see
LICENSE).
This module works with both Python 3 and Python 2.7. You need a fairly recent version of numpy and scipy.
Clone this repository
git clone https://github.com/sbrisard/moisan2011.git
then run the following command
python setup.py install
You can also run the tests (requires pytest and pillow)
python setup.py test
Let us start with loading an image that we would like to decompose into its periodic and smooth components. Assuming that you launch the Python REPL in the root directory of this project:
import numpy as np
from skimage.io import imread
u = imread('./images/hut-648x364.png')which loads the following image:
This image is not periodic, owing to discontinuities at the boundaries. This is best illustrated by swapping the quadrants of the image.
np.fft.fftshift(u)which produces:
Computing the periodic-plus-smooth decomposition of u is as simple as:
from moisan2011 import per
p, s = per(u)The periodic (resp. smooth) components of u are p and s. Here is
what p looks like:
Swapping the quadrants indeed shows that periodization did occur:
Sometimes, further analyses of the periodized image require the DFT of p
(rather than p itself). You can then spare the moisan2011.per function
one last inverse DFT by passing the inverse_dft=False argument like so:
dft_p, dft_s = per(u, inverse_dft=False)(the default value of inverse_dft is True).
Several versions of the “per” operator are implemented in the moisan2011
module, namely: _per, per, per2, rper and rper2. All share
the same interface
per(u, inverse_dft)All return the pair (p, s) if inverse_dft == True.
If inverse_dft == False, then _per, per and per2 return the pair
(numpy.fft.fft2(p), numpy.fft.fft2(s))while rper and rper2 return the pair
(numpy.fft.rfft2(p), numpy.fft.rfft2(s))Now, the differences
_per,perandrperimplement Algorithm 1 in Moisan's paper,per2andrper2implement Algorithm 2 in Moisan's paper,_per,perandper2use the complex DFT and apply to both complex and real images,rperandrper2use the real DFT and apply to real images,_peris a direct implementation of Algorithm 1, and is slightly less efficient thanper,- Algorithm 2 turns out to be slightly slower and less accurate that Algorithm 1.
In short, most users will probably want to use per and rper functions.
Moisan's energy of the decomposition can be computed by means of the function
energy. This energy turns out to be a quadratic form, which is implemented
in the present module as scipy.sparse.linalg.LinearOperator
(documentation):
see moisan2011.OperatorQ and moisan2011.OperatorQ1.



