<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Demonstration of Convolution Theorem
Illustrate the discrete convolution theorem.
F indicates Fourier transform operator and F{f} and F{g} are the fourier transform of "f" and "g" so we have
Step1:  Numeric sample
Step2:  See that f and h are periodic images and the period is (H,W) that is the shape of f.
At the following code, the F and H need to be the same shape
Step3:  gg and g need to be equal
Step4:  Using an image to illustrate the discrete convolution theorem
See the original image (keyb,tif) and h
Step5:  Convolution in frequency domain
Step6:  Convolution in space domain
Step7:  The convolution in frequency domain and space domain need to be equals
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
import numpy as np
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import sys,os
ia898path = os.path.abspath('/etc/jupyterhub/ia898_1s2017/')
if ia898path not in sys.path:
    sys.path.append(ia898path)
import ia898.src as ia
from numpy.fft import fft2
from numpy.fft import ifft2
Explanation: Demonstration of Convolution Theorem
Illustrate the discrete convolution theorem.
F indicates Fourier transform operator and F{f} and F{g} are the fourier transform of "f" and "g" so we have:
$$ F\left { f * g \right } = F\left { f \right } \cdot F\left { g \right } $$
$$ F(f\cdot g) = F\left {  f \right } * F\left {  g \right } $$
Importing
End of explanation
fr = np.linspace(-1,1,6)
f  = np.array([fr,2*fr,fr,fr])
print(f)
hh = np.array([-1,0,+1])
h = np.array([hh,2*hh,hh])
print(h)
g = ia.pconv(f,h)
print(g)
Explanation: Numeric sample
End of explanation
#Deixar o h (3,3) com o mesmo shape de f (4,6)
aux = np.zeros(f.shape)
r,c = h.shape
aux[:r,:c] = h
F = fft2(f)
H = fft2(aux)
G = F * H
gg = ifft2(G)
print("Result gg: \n",np.around(gg))
Explanation: See that f and h are periodic images and the period is (H,W) that is the shape of f.
At the following code, the F and H need to be the same shape
End of explanation
print('The discrete convolution theorem worked?', np.allclose(gg.real,g)) 
Explanation: gg and g need to be equal:
End of explanation
f = mpimg.imread('/home/lotufo/ia898/data/keyb.tif')
plt.imshow(f,cmap='gray');
plt.title('Original')
plt.colorbar()
plt.show()
hh = np.array([-1,0,+1])
h = np.array([hh,2*hh,hh])
print(h)
Explanation: Using an image to illustrate the discrete convolution theorem
See the original image (keyb,tif) and h
End of explanation
aux = np.zeros(f.shape)
r,c = h.shape
aux[:r,:c] = h
F = fft2(f)
H = fft2(aux)
x,y = f.shape
plt.figure(1)
plt.imshow(np.log(np.abs(ia.ptrans(F,(x//2,y//2))+1)),cmap='gray')
plt.title('DFT of f')
plt.colorbar()
plt.figure(2)
plt.imshow(np.log(np.abs(ia.ptrans(H,(x//2,y//2))+1)),cmap='gray')
plt.title('DFT of h')
plt.colorbar()
G = F * H
plt.figure(3)
plt.imshow(np.log(np.abs(ia.ptrans(G,(x//2,y//2))+1)),cmap='gray')
plt.title('F * H')
plt.colorbar()
gg = ifft2(G)
plt.figure(4)
plt.imshow(gg.real.astype(np.float),cmap='gray');
plt.title('Convolution in frequency domain')
plt.colorbar()
plt.show()
Explanation: Convolution in frequency domain:
End of explanation
g = ia.pconv(f,h)
plt.imshow(g.real.astype(np.float),cmap='gray');
plt.title('Convolution in space domain')
plt.colorbar()
plt.show()
Explanation: Convolution in space domain
End of explanation
print('The discrete convolution theorem worked?', np.allclose(gg.real,g)) 
Explanation: The convolution in frequency domain and space domain need to be equals
End of explanation
<END_TASK>