Restoring a 1D signal using Tikhonov regularization

\label{code:restore1d}

Code prerequisites


In [25]:
%matplotlib inline
"""
Deblurring and denoising a 1D signal.
"""
import numpy as np
import scipy.ndimage as spnd
import matplotlib.pyplot as plt

# using common functions for signal/image restoration
from restore_common import *

Artificial signal generation

The following code produces a signal with both soft and sharp variations


In [8]:
## produce a signal from a range input
def makesignal(mys):
    sig= 1.*(np.cos(mys*2)>0)+ 2*np.sin(mys/4.0) + 0.1*np.cos(mys*3+1.0)
    return sig

We illustrate how the signal looks like with the following:


In [9]:
## Produce some signal    
N1 = 250 # length of the signal 
myrange=np.linspace(0,3*np.pi,num=N1)
mysignal1=makesignal(myrange)

In [20]:
fig = plt.figure(figsize=(12,6), dpi=100)
plt.plot(myrange,mysignal1)


Out[20]:
[<matplotlib.lines.Line2D at 0x1158115d0>]

This signal is interesting because it shows some soft and hard transitions. We now blur the signal and add some noise.


In [11]:
n = 25 # quite a large kernel
k1 = np.zeros(n)
k1[n/2] = 1
mykernel=spnd.gaussian_filter1d(k1,sigma=n/6.0)  ## already normalized
mysignal = np.pad(mysignal1, n,'reflect')
N = mysignal.size
myconv=makespdiag(mykernel,N).toarray() ## degradation matrix
myblurred = np.dot(myconv,mysignal) ## Convolve the signal
observed = myblurred + np.random.normal(scale=0.05,size=N) ## add noise

Note that we pad the signal left and right with a reflective boundary condition. This ensures our result is as correct as possible near its start and its end. When we display it, we only show the unpadded middle part.


In [21]:
print("Condition number of base convolution matrix= %.3g\n" % np.linalg.cond(myconv))
fig = plt.figure(figsize=(12,6))
## better deblurring
plt.plot(myrange,mysignal[n:-n],'b')
plt.plot(myrange,observed[n:-n],'m.')
## Adding a "small vector" prior
deblurred_id = restore_tikh(observed, myconv,0.01,'Id')
# small gradient prior (mostly flat signal)
deblurred_grad = restore_tikh(observed, myconv,0.3,'Grad1')
# small Laplacian (mostly piecewise linear)
deblurred_lap = restore_tikh(observed, myconv,0.4, 'Lap')
plt.plot(myrange,deblurred_lap[n:-n],'k')


Condition number of base convolution matrix= 3.53e+04

Out[21]:
[<matplotlib.lines.Line2D at 0x115c36a50>]

The observed signal is represented by the purple dots. The restored signal is in black. The procedure we have used restores some of the sharp edges at the expense of some oscillations in the smooth regions. This is similar to the effect we observed on image deblurring.