Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
python-version: ["3.12", "3.13"]
os: [ubuntu-latest, macOS-latest, windows-latest]

steps:
Expand Down
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Version 0.2.2 (unreleased)

• Removed deprecated sporco.fista modules
• Removed deprecation warning redirects for functions renamed in 0.2.0
• Resolved a number of deprecation warnings
• Fixed bugs in a number of example scripts


Version 0.2.1 (2022-02-17)
Expand Down
1 change: 1 addition & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
future
scipy
filetype
matplotlib
sphinx>=5.0.0
numpydoc
Expand Down
12 changes: 9 additions & 3 deletions docs/source/docntbk.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import os
import os.path
from pathlib import Path
from glob import glob
import re
import pickle
Expand Down Expand Up @@ -68,11 +69,14 @@ def fetch_intersphinx_inventory(uri):

# See https://stackoverflow.com/a/30981554
class MockConfig(object):
intersphinx_cache_limit = None
intersphinx_timeout = None
tls_verify = False
tls_cacerts = None
user_agent = None

class MockApp(object):
srcdir = ''
srcdir = Path('')
config = MockConfig()

def warn(self, msg):
Expand Down Expand Up @@ -126,6 +130,8 @@ def preprocess_script_string(str):

# Remove header comment
str = re.sub(r'^(#[^#\n]+\n){5}\n*', r'', str)
# Remove r from r""" ... """
str = re.sub('^r"""', '"""', str, flags=re.MULTILINE)
# Insert notebook plotting configuration function
str = re.sub(r'from sporco import plot', r'from sporco import plot'
'\nplot.config_notebook_plotting()',
Expand Down Expand Up @@ -500,7 +506,7 @@ def write_notebook_rst(txt, res, fnm, pth):
# Partial path for current output image
rpth = os.path.join(extfnm, rnew)
# In RST text, replace old output name with the new one
txt = re.sub('\.\. image:: ' + r, '.. image:: ' + rpth, txt, re.M)
txt = re.sub(r'\.\. image:: ' + r, '.. image:: ' + rpth, txt, re.M)
# Full path of the current output image
fullrpth = os.path.join(pth, rpth)
# Write the current output image to disk
Expand Down Expand Up @@ -818,7 +824,7 @@ def __init__(self, env, inv, baseurl):
self.citeid = {}
if not hasattr(env, 'bibtex_cache'):
for cite in env.domaindata['cite']['citations']:
self.citenum[cite.key] = cite.label
self.citenum[cite.key] = cite.citation_id[2:]
self.citeid[cite.key] = cite.citation_id


Expand Down
6 changes: 3 additions & 3 deletions examples/scripts/cdl/cbpdndl_grd.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Convolutional Dictionary Learning
=================================

This example demonstrating the use of :class:`.dictlrn.DictLearn` to construct a dictionary learning algorithm with the flexibility of choosing the sparse coding and dictionary update classes. In this case they are :class:`.cbpdn.ConvBPDNGradReg` and :func:`.admm.ccmod.ConvCnstrMOD` respectively, so the resulting dictionary learning algorithm is not equivalent to :class:`.dictlrn.cbpdndl.ConvBPDNDictLearn`. Sparse coding with a CBPDN variant that includes a gradient regularization term on one of the coefficient maps :cite:`wohlberg-2016-convolutional2` enables CDL without the need for the usual lowpass/highpass filtering as a pre-processing of the training images.
This example demonstrates the use of :class:`.dictlrn.DictLearn` to construct a dictionary learning algorithm with the flexibility of choosing the sparse coding and dictionary update classes. In this case they are :class:`.cbpdn.ConvBPDNGradReg` and :func:`.admm.ccmod.ConvCnstrMOD` respectively, so the resulting dictionary learning algorithm is not equivalent to :class:`.dictlrn.cbpdndl.ConvBPDNDictLearn`. Sparse coding with a CBPDN variant that includes a gradient regularization term on one of the coefficient maps :cite:`wohlberg-2016-convolutional2` enables CDL without the need for the usual lowpass/highpass filtering as a pre-processing of the training images.
"""


Expand Down Expand Up @@ -53,15 +53,15 @@
cri = cnvrep.CDU_ConvRepIndexing(D0.shape, S)


"""
r"""
Set up weights for the $\ell_1$ norm to disable regularization of the coefficient map corresponding to the impulse filter.
"""

wl1 = np.ones((1,)*4 + (D0.shape[2:]), dtype=np.float32)
wl1[..., 0] = 0.0


"""
r"""
Set of weights for the $\ell_2$ norm of the gradient to disable regularization of all coefficient maps except for the one corresponding to the impulse filter.
"""

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/cdl/cbpdndl_jnt_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Convolutional Dictionary Learning
=================================

This example demonstrating the use of :class:`.dictlrn.DictLearn` to construct a dictionary learning algorithm with the flexibility of choosing the sparse coding and dictionary update classes. In this case they are :class:`.cbpdn.ConvBPDNJoint` and :func:`.admm.ccmod.ConvCnstrMOD` respectively, so the resulting dictionary learning algorithm is not equivalent to :class:`.dictlrn.cbpdndl.ConvBPDNDictLearn`. The example uses colour input images and a greyscale dictionary :cite:`wohlberg-2016-convolutional`.
This example demonstrates the use of :class:`.dictlrn.DictLearn` to construct a dictionary learning algorithm with the flexibility of choosing the sparse coding and dictionary update classes. In this case they are :class:`.cbpdn.ConvBPDNJoint` and :func:`.admm.ccmod.ConvCnstrMOD` respectively, so the resulting dictionary learning algorithm is not equivalent to :class:`.dictlrn.cbpdndl.ConvBPDNDictLearn`. The example uses colour input images and a greyscale dictionary :cite:`wohlberg-2016-convolutional`.
"""


Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/cdl/cbpdndl_md_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
Sw = W * S


"""
r"""
$\ell_2$-TV denoising with a spatial mask as a non-linear lowpass filter.
"""

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/cdl/cbpdndl_md_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
Sw = W * S


"""
r"""
$\ell_2$-TV denoising with a spatial mask as a non-linear lowpass filter.
"""

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/cdl/cbpdndl_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
frmlst = []
for i, frm in enumerate(reader):
if i >= 250:
frm = zoom(signal.rgb2gray(frm.astype(np.float32)/255.0), 0.25)
frm = zoom(signal.rgb2gray(np.array(frm, dtype=np.float32)/255.0), 0.25)
frmlst.append(frm[20:-20, 70:-70])
vid = np.stack(frmlst, axis=2)

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_ams_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
imgwp = spad(imgw)


"""
r"""
$\ell_2$-TV denoising with a spatial mask as a non-linear lowpass filter. The highpass component is the difference between the test image and the lowpass component, multiplied by the mask for faster convergence of the convolutional sparse coding (see :cite:`wohlberg-2017-convolutional3`).
"""

Expand Down
4 changes: 2 additions & 2 deletions examples/scripts/csc/cbpdn_ams_grd_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
Di = np.dstack((di, D))


"""
r"""
Set up weights for the $\ell_1$ norm to disable regularization of the coefficient map corresponding to the impulse filter intended to represent lowpass image components (not to be confused with the AMS impulse filter used to implement spatial masking).
"""

Expand All @@ -87,7 +87,7 @@
wl1i = np.concatenate((wl1, np.zeros(wl1.shape[0:-1] + (1,))), axis=-1)


"""
r"""
When representing lowpass image components using an impulse filter together with an $\ell_2$ norm on the gradient of its coefficient map, we usually want to set the weight array for this norm (specified by the ``GradWeight`` option) to disable regularization of all coefficient maps except for the one corresponding to that impulse filter (not to be confused with the AMS impulse filter used to implement spatial masking). In this case set a non-zero value for the weights of the other coefficient maps size this improves performance in this inpainting problem.
"""

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_ams_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
imgwp = spad(imgw)


"""
r"""
$\ell_2$-TV denoising with a spatial mask as a non-linear lowpass filter. The highpass component is the difference between the test image and the lowpass component, multiplied by the mask for faster convergence of the convolutional sparse coding (see :cite:`wohlberg-2017-convolutional3`).
"""

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_clr_cd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Multi-channel CSC
=================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_clr_gd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Multi-channel CSC
=================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_clr_pd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Multi-channel CSC
=================

Expand Down
4 changes: 2 additions & 2 deletions examples/scripts/csc/cbpdn_grd_cuda.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@
D = np.concatenate((di, Db), axis=2)


"""
r"""
Set up weights for the $\ell_1$ norm to disable regularization of the coefficient map corresponding to the impulse filter.
"""

wl1 = np.ones((1,)*2 + (D.shape[2:]), dtype=np.float32)
wl1[..., 0] = 0.0


"""
r"""
Set of weights for the $\ell_2$ norm of the gradient to disable regularization of all coefficient maps except for the one corresponding to the impulse filter.
"""

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Single-channel CSC
==================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_jnt_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Multi-channel CSC
=================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_md_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
imgwp = spad(imgw)


"""
r"""
$\ell_2$-TV denoising with a spatial mask as a non-linear lowpass filter. The highpass component is the difference between the test image and the lowpass component, multiplied by the mask for faster convergence of the convolutional sparse coding (see :cite:`wohlberg-2017-convolutional3`).
"""

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_pgm_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
PGM CBPDN Solver
==================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdn_pgm_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
PGM CBPDN Solver
==================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdnin_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Single-channel CSC With Lateral Inhibition / No Self Inhibition
===============================================================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cbpdnin_wgt_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Single-channel CSC With Weighted Lateral Inhibition / No Self Inhibition
========================================================================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cminl1_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Single-channel CSC (Constrained Data Fidelity)
==============================================

Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/csc/cprjl1_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Single-channel CSC (Constrained Penalty Term)
=============================================

Expand Down
7 changes: 3 additions & 4 deletions examples/scripts/csc/gwnden_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""

r"""
Gaussian White Noise Restoration via CSC
========================================

Expand Down Expand Up @@ -50,7 +49,7 @@ def crop(x, n=8):
return x[n:-n, n:-n]


"""
r"""
Load a reference image and corrupt it with Gaussian white noise with $\sigma = 0.1$. (The call to ``numpy.random.seed`` ensures that the pseudo-random noise is reproducible.)
"""

Expand All @@ -76,7 +75,7 @@ def crop(x, n=8):
D = util.convdicts()['G:8x8x128']


"""
r"""
Set solver options. See Section 8 of :cite:`wohlberg-2017-convolutional2` for details of construction of $\ell_1$ weighting matrix $W$.
"""

Expand Down
6 changes: 3 additions & 3 deletions examples/scripts/csc/gwnden_gry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Gaussian White Noise Restoration via CSC
========================================

Expand Down Expand Up @@ -47,7 +47,7 @@ def crop(x, n=8):
return x[n:-n, n:-n]


"""
r"""
Load a reference image and corrupt it with Gaussian white noise with $\sigma = 0.1$. (The call to ``numpy.random.seed`` ensures that the pseudo-random noise is reproducible.)
"""

Expand All @@ -73,7 +73,7 @@ def crop(x, n=8):
D = util.convdicts()['G:8x8x128']


"""
r"""
Set solver options. See Section 8 of :cite:`wohlberg-2017-convolutional2` for details of construction of $\ell_1$ weighting matrix $W$.
"""

Expand Down
6 changes: 3 additions & 3 deletions examples/scripts/csc/implsden_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and user license can be found in the 'LICENSE.txt' file distributed
# with the package.

"""
r"""
Impulse Noise Restoration via CSC
=================================

Expand Down Expand Up @@ -67,7 +67,7 @@ def crop(x, n=8):
D = np.concatenate((Di, Di, D0), axis=3)


"""
r"""
The problem is solved using class :class:`.admm.cbpdn.ConvBPDNGradReg`, which implements the form of CBPDN with an additional gradient regularization term, as defined above. The regularization parameters for the $\ell_1$ and gradient terms are ``lmbda`` and ``mu`` respectively. Setting correct weighting arrays for these regularization terms is critical to obtaining good performance. For the $\ell_1$ norm, the weights on the filters that are intended to represent the impulse noise are tuned to an appropriate value for the impulse noise density (this value sets the relative cost of representing an image feature by one of the impulses or by one of the filters in the learned dictionary), the weights on the filters that are intended to represent low frequency components are set to zero (we only want them penalised by the gradient term), and the weights of the remaining filters are set to zero. For the gradient penalty, all weights are set to zero except for those corresponding to the filters intended to represent low frequency components, which are set to unity.
"""

Expand Down Expand Up @@ -128,7 +128,7 @@ def crop(x, n=8):



"""
r"""
The previous method gave good results, but the weight on the filter representing the impulse noise is an additional parameter that has to be tuned. This parameter can be avoided by switching to an $\ell_1$ data fidelity term instead of including dictionary filters to represent the impulse noise, as in the problem :cite:`wohlberg-2016-convolutional2`

$$\mathrm{argmin}_{\{\mathbf{x}_m\}} \;
Expand Down
Loading
Loading