PEL304 - Aplicações em Processamento de Sinais

Prof. Ivandro Sanches

IPython Notebook, Python 3.4.3


Aula 1: Sinais e Sistemas - noções básicas Python/Numpy

Sinais amostrados transformam-se em sequências de números. A linha abaixo, cria uma sequência (lista) com 5 números

In [1]:
x = [4, 3, 7, -9, 1]

Ilustra-se a seguir algumas formas de se selecionar elementos da sequência

In [2]:
x[0] # primeiro elemento (índices iniciam em 0)
Out[2]:
4
In [3]:
x[1] # segundo elemento (índice 1)
Out[3]:
3
In [4]:
x[-1] # último elemento (neste caso, índice 4)
Out[4]:
1
In [5]:
x[-2] # penúltimo elemento (neste caso, índice 3)
Out[5]:
-9
In [6]:
x[1:4] # fatia (slice) do índice 1 ao índice 3 (4-1)
Out[6]:
[3, 7, -9]
In [7]:
x[1:-1] # idem acima; fatia do segundo ao penúltimo elemento
Out[7]:
[3, 7, -9]
In [8]:
x[1:] # fatia do segundo ao último elemento
Out[8]:
[3, 7, -9, 1]
In [9]:
x[::2] # fatia pode conter um 'passo'
Out[9]:
[4, 7, 1]
In [10]:
x[::-1] # o 'passo' pode ser negativo
Out[10]:
[1, -9, 7, 3, 4]
In [11]:
x[::-2]
Out[11]:
[1, 7, 4]

Em Python importam-se módulos à medida que forem necessários. O módulo numpy é conveniente para manipulação de vetores e matrizes, dentre muitas outras funcionalidades

In [12]:
import numpy as np
x = np.array([4, 3, 7, -9, 1])
print(x)
[ 4  3  7 -9  1]
In [13]:
print(x.dtype)  # data type
int32
In [14]:
print(x.itemsize)  # tamanho em bytes de cada elemento (int32)
4
In [15]:
print(x.size)  # número de elementos em x
5
In [16]:
print(x.itemsize * x.size)  # tamanho de x em bytes
20
In [17]:
print(x.nbytes)  # idem acima
20
In [18]:
print(x.ndim)  # número de dimensões (1: array, 2: matriz, etc. )
1
In [19]:
print(x.shape)  # array unidimensional com 5 elementos
(5,)
In [20]:
print(1/x)  # inverso elemento a elemento de x
[ 0.25        0.33333333  0.14285714 -0.11111111  1.        ]
In [21]:
print(x*x)  # produto elemento a elemento de x por ele mesmo
[16  9 49 81  1]
In [22]:
print(x**2)  # idem acima
[16  9 49 81  1]
In [23]:
x.dot(x) # produto escalar de `x` com `x`: 16+9+49+81+1
Out[23]:
156
In [24]:
from numpy import pi
y = np.array([x, 2*x, x/pi])
print(y)
[[  4.           3.           7.          -9.           1.        ]
 [  8.           6.          14.         -18.           2.        ]
 [  1.27323954   0.95492966   2.2281692   -2.86478898   0.31830989]]
In [25]:
print(y.dtype)  # devido à divisão, o elemento agora é do tipo float
float64
In [26]:
print(y.shape)
(3, 5)
In [27]:
z = y.transpose()  # atenção: transpose() retorna uma `view` de y e não uma cópia
print(z)
[[  4.           8.           1.27323954]
 [  3.           6.           0.95492966]
 [  7.          14.           2.2281692 ]
 [ -9.         -18.          -2.86478898]
 [  1.           2.           0.31830989]]
In [28]:
z[0,0] = 1
In [29]:
print('z:\n', z,'\ny:\n', y)  # note que a atribuição a z[0,0] afetou y[0,0]!
z:
 [[  1.           8.           1.27323954]
 [  3.           6.           0.95492966]
 [  7.          14.           2.2281692 ]
 [ -9.         -18.          -2.86478898]
 [  1.           2.           0.31830989]] 
y:
 [[  1.           3.           7.          -9.           1.        ]
 [  8.           6.          14.         -18.           2.        ]
 [  1.27323954   0.95492966   2.2281692   -2.86478898   0.31830989]]
In [30]:
print(z[1:-1, :])
[[  3.           6.           0.95492966]
 [  7.          14.           2.2281692 ]
 [ -9.         -18.          -2.86478898]]
In [31]:
o = z/z
print(o)
[[ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]]
In [32]:
print(o.shape)
(5, 3)
In [33]:
o.resize(3,5)  # resize é um método (atua diretamente em `o`)
print(o)
[[ 1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.]
 [ 1.  1.  1.  1.  1.]]
In [34]:
print(o.shape)
(3, 5)
In [35]:
m = np.arange(1,13)
print(m)
[ 1  2  3  4  5  6  7  8  9 10 11 12]
In [36]:
m = m.reshape(4,3)  # reshape é uma função (retorna o novo objeto)
print(m)
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
In [37]:
n = m.T  # atributo .T tem mesmo efeito que função transpose()
print(n)
[[ 1  4  7 10]
 [ 2  5  8 11]
 [ 3  6  9 12]]
In [38]:
print(n.flatten())  # flatten retorna uma nova cópia
[ 1  4  7 10  2  5  8 11  3  6  9 12]
In [39]:
print(n.ravel())  # cuidado: retorna uma `view` e não uma cópia
[ 1  4  7 10  2  5  8 11  3  6  9 12]
In [40]:
p = n[::2,::2]  # atenção: p é uma 'view' de n (não é uma cópia)
print(p)
[[1 7]
 [3 9]]
In [41]:
p[0,0] = 0  # modificando p causará modificação em n
print(p)
[[0 7]
 [3 9]]
In [42]:
print(n)  # note que n foi modificado (cuidado com 'views' formadas por slices)
[[ 0  4  7 10]
 [ 2  5  8 11]
 [ 3  6  9 12]]

Números complexos são representados por j

In [43]:
b = np.array([1 - 1.j, 3 + 4.j])
print(b)
[ 1.-1.j  3.+4.j]
In [44]:
print(b.real)  # parte real de b; também np.real(b)
[ 1.  3.]
In [45]:
print(np.real(b))
[ 1.  3.]
In [46]:
print(b.imag)  # parte imaginária de b; também np.imag(b)
[-1.  4.]
In [47]:
print(b.conj())  # conjugado de b; também np.conj(b)
[ 1.+1.j  3.-4.j]
In [48]:
print(abs(b))  # absoluto de b; também np.abs(b)
[ 1.41421356  5.        ]
In [49]:
print(np.angle(b, deg=True))  # retorna fase; deg=True em graus, deg=False em radianos (default)
[-45.          53.13010235]
In [50]:
print(np.angle(b))  # retorna fase; deg=True em graus, deg=False em radianos (default)
[-0.78539816  0.92729522]

Vetores e matrizes

In [51]:
r = np.random.rand(3, 3)
print(r)
[[ 0.91544732  0.13841704  0.81977654]
 [ 0.01300714  0.99227949  0.5006404 ]
 [ 0.13009451  0.252738    0.45349451]]
In [52]:
s = np.ones((3,1))
print(s)
[[ 1.]
 [ 1.]
 [ 1.]]
In [53]:
print(r * s)
[[ 0.91544732  0.13841704  0.81977654]
 [ 0.01300714  0.99227949  0.5006404 ]
 [ 0.13009451  0.252738    0.45349451]]
In [54]:
print(s * r)
[[ 0.91544732  0.13841704  0.81977654]
 [ 0.01300714  0.99227949  0.5006404 ]
 [ 0.13009451  0.252738    0.45349451]]
In [55]:
t = np.dot(r, s)  # produto da matriz r (3x3) pelo vetor s (3x1) resultando t (3x1)
print(t)
[[ 1.8736409 ]
 [ 1.50592703]
 [ 0.83632702]]
In [56]:
u = np.dot(s.T, r)  # produto do vetor s (1x3) pela matriz r (3x3) resultando u (1x3)
print(u)
[[ 1.05854897  1.38343453  1.77391145]]
In [57]:
v = np.dot(r, r.T)
print(v)
[[ 1.52923665  0.559669    0.52584208]
 [ 0.559669    1.23542858  0.47951656]
 [ 0.52584208  0.47951656  0.28645835]]
In [58]:
vinv = np.linalg.inv(v)
print(np.dot(v, vinv).round())
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]
In [59]:
d = np.linalg.det(v)  # determinante de v
print(d)
0.0404739637418
In [60]:
w = np.linalg.solve(v, s)  # solução de sistema de equações lineares
print(np.dot(v, w))
[[ 1.]
 [ 1.]
 [ 1.]]
In [61]:
z = np.zeros((1,3))
print(z)
[[ 0.  0.  0.]]
In [62]:
z += 1
print(z)
[[ 1.  1.  1.]]
In [63]:
print(z[0])
[ 1.  1.  1.]
In [64]:
print(np.vstack((z[0], 2*z[0], 3*z[0])))
[[ 1.  1.  1.]
 [ 2.  2.  2.]
 [ 3.  3.  3.]]
In [65]:
print(np.vstack((z, 2*z, 3*z)))
[[ 1.  1.  1.]
 [ 2.  2.  2.]
 [ 3.  3.  3.]]
In [66]:
print(np.hstack((z[0], 2*z[0], 3*z[0])))
[ 1.  1.  1.  2.  2.  2.  3.  3.  3.]
In [67]:
print(np.hstack((z[0], 2*z[0], 3*z[0])).ndim)
1
In [68]:
print(np.hstack((z, 2*z, 3*z)))
[[ 1.  1.  1.  2.  2.  2.  3.  3.  3.]]
In [69]:
print(np.hstack((z, 2*z, 3*z)).ndim)
2

Exemplos complementares ao material da primeira aula

In [70]:
import matplotlib.pyplot as plt
%matplotlib inline

Slide 25 - Imagem

In [71]:
import scipy.misc
img = scipy.misc.lena()
maxi = 255
R = len(img)
C= len(img[0])
plt.imshow(img/maxi)
plt.show()
In [72]:
imgd = abs(np.diff(img,axis=0))/maxi
plt.imshow(imgd)
plt.show()

Slide 26 - Texto

In [73]:
s = [ 67, 111, 110, 102, 105, 114, 109, 101,  32, 113, 117, 101,  32, 117, 109,
      32, 116, 101, 120, 116, 111,  32, 112, 111, 100, 101,  32, 115, 101, 114,
      32,  99, 111, 110, 115, 105, 100, 101, 114,  97, 100, 111,  32, 117, 109,
      32, 115, 105, 110,  97, 108,  32, 110, 111,  32, 116, 101, 109, 112, 111, 33]
In [74]:
print(len(s))
texto = '' . join(chr(v) for v in s)
print(texto)
61
Confirme que um texto pode ser considerado um sinal no tempo!
In [75]:
plt.plot(s);

Slide 30 - Amostragem

In [76]:
# geracao de forma de onda
fs = 10000  # freq de amostragem
T = 2  # duracao em segundos
t = np.arange(fs*T)/fs  # tempo
f1 = 100  # feq de sinal 1 em Hz
f2 = 95  # feq de sinal 2 em Hz
In [77]:
# ref signal
y = np.sin(2*pi*f1*t)

# resample ref sinal with f2
yn = y[::f2]
In [78]:
Y = np.abs(np.fft.fft(y))
f = t / T * fs
plt.plot(f[0:400], Y[0:400])
plt.grid()
plt.xlabel('$f \,$, Hz')
plt.title('$|Y(e^{j \, 2 \pi \, f})|$')
plt.show()
In [79]:
plt.figure(figsize=(12, 5))
dt = 2000  # faixa de observacao
plt.plot(t[:dt], y[:dt])
plt.title('y(t)')
plt.xlabel('t,s')
plt.grid()
# sinal discreto no tempo
plt.stem(t[:dt:f2], yn[:(dt//f2+1)], 'k')
plt.plot(t[:dt:f2], yn[:(dt//f2+1)], 'g:')
plt.show()