Deconvolution/2D+: Difference between revisions
Content added Content deleted
(Python example) |
|||
Line 1,558: | Line 1,558: | ||
</pre> |
</pre> |
||
The version shipped in demo\rosetta contains the full 5 test sets: note that 5D takes a minute or two to complete. |
The version shipped in demo\rosetta contains the full 5 test sets: note that 5D takes a minute or two to complete. |
||
=={{header|Python}}== |
|||
Tested on all 5 test cases. |
|||
Blows up with divide by zero error on 4d deconv(g,f) because |
|||
the fft(f) returns 0 for a sample. This shows the limits of |
|||
doing a deconvolution with fft. |
|||
https://math.stackexchange.com/questions/380720/is-deconvolution-simply-division-in-frequency-domain |
|||
<lang python> |
|||
""" |
|||
https://rosettacode.org/wiki/Deconvolution/2D%2B |
|||
Working on 3 dimensional example using test data from the |
|||
RC task. |
|||
Python fft: |
|||
https://docs.scipy.org/doc/numpy/reference/routines.fft.html |
|||
""" |
|||
import numpy |
|||
import pprint |
|||
h = [ |
|||
[[-6, -8, -5, 9], [-7, 9, -6, -8], [2, -7, 9, 8]], |
|||
[[7, 4, 4, -6], [9, 9, 4, -4], [-3, 7, -2, -3]]] |
|||
f = [ |
|||
[[-9, 5, -8], [3, 5, 1]], |
|||
[[-1, -7, 2], [-5, -6, 6]], |
|||
[[8, 5, 8],[-2, -6, -4]]] |
|||
g = [ |
|||
[ |
|||
[54, 42, 53, -42, 85, -72], |
|||
[45, -170, 94, -36, 48, 73], |
|||
[-39, 65, -112, -16, -78, -72], |
|||
[6, -11, -6, 62, 49, 8]], |
|||
[ |
|||
[-57, 49, -23, 52, -135, 66], |
|||
[-23, 127, -58, -5, -118, 64], |
|||
[87, -16, 121, 23, -41, -12], |
|||
[-19, 29, 35, -148, -11, 45]], |
|||
[ |
|||
[-55, -147, -146, -31, 55, 60], |
|||
[-88, -45, -28, 46, -26, -144], |
|||
[-12, -107, -34, 150, 249, 66], |
|||
[11, -15, -34, 27, -78, -50]], |
|||
[ |
|||
[56, 67, 108, 4, 2, -48], |
|||
[58, 67, 89, 32, 32, -8], |
|||
[-42, -31, -103, -30, -23, -8], |
|||
[6, 4, -26, -10, 26, 12]]] |
|||
def trim_zero_empty(x): |
|||
""" |
|||
Takes a structure that represents an n dimensional example. |
|||
For a 2 dimensional example it will be a list of lists. |
|||
For a 3 dimensional one it will be a list of list of lists. |
|||
etc. |
|||
Actually these are multidimensional numpy arrays but I was thinking |
|||
in terms of lists. |
|||
Returns the same structure without trailing zeros in the inner |
|||
lists and leaves out inner lists with all zeros. |
|||
""" |
|||
if len(x) > 0: |
|||
if type(x[0]) != numpy.ndarray: |
|||
# x is 1d array |
|||
return list(numpy.trim_zeros(x)) |
|||
else: |
|||
# x is a multidimentional array |
|||
new_x = [] |
|||
for l in x: |
|||
tl = trim_zero_empty(l) |
|||
if len(tl) > 0: |
|||
new_x.append(tl) |
|||
return new_x |
|||
else: |
|||
# x is empty list |
|||
return x |
|||
def deconv(a, b): |
|||
""" |
|||
Returns function c such that b * c = a. |
|||
https://en.wikipedia.org/wiki/Deconvolution |
|||
""" |
|||
# Convert larger polynomial using fft |
|||
ffta = numpy.fft.fftn(a) |
|||
# Get it's shape so fftn will expand |
|||
# smaller polynomial to fit. |
|||
ashape = numpy.shape(a) |
|||
# Convert smaller polynomial with fft |
|||
# using the shape of the larger one |
|||
fftb = numpy.fft.fftn(b,ashape) |
|||
# Divide the two in frequency domain |
|||
fftquotient = ffta / fftb |
|||
# Convert back to polynomial coefficients using ifft |
|||
# Should give c but with some small extra components |
|||
c = numpy.fft.ifftn(fftquotient) |
|||
# Get rid of imaginary part and round up to 6 decimals |
|||
# to get rid of small real components |
|||
trimmedc = numpy.around(numpy.real(c),decimals=6) |
|||
# Trim zeros and eliminate |
|||
# empty rows of coefficients |
|||
cleanc = trim_zero_empty(trimmedc) |
|||
return cleanc |
|||
print("deconv(g,h)=") |
|||
pprint.pprint(deconv(g,h)) |
|||
print(" ") |
|||
print("deconv(g,f)=") |
|||
pprint.pprint(deconv(g,f)) |
|||
</lang> |
|||
Output: |
|||
<pre> |
|||
deconv(g,h)= |
|||
[[[-9.0, 5.0, -8.0], [3.0, 5.0, 1.0]], |
|||
[[-1.0, -7.0, 2.0], [-5.0, -6.0, 6.0]], |
|||
[[8.0, 5.0, 8.0], [-2.0, -6.0, -4.0]]] |
|||
deconv(g,f)= |
|||
[[[-6.0, -8.0, -5.0, 9.0], [-7.0, 9.0, -6.0, -8.0], [2.0, -7.0, 9.0, 8.0]], |
|||
[[7.0, 4.0, 4.0, -6.0], [9.0, 9.0, 4.0, -4.0], [-3.0, 7.0, -2.0, -3.0]]] |
|||
</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |