## Matrix Convolution¶

• 2D Convolution

• $Y[m,n] = X[m,n] * H[m,n] = \sum_{j=-\infty}^{\infty}\sum_{i=-\infty}^{\infty} Y[i,j] \cdot H[m-i,n-j]$
• $Y$ is the convolved matrix
• $X$ is the input matrix
• $H$ is the kernel
• When calculating the convolution, the kernel matrix is flipped both horizontal and vertical direction.

• $X[0,0]$ is multiplied by the last element of the kernel matrix, $H[1,1]$.
• $X[2,2]$ is multiplied by the first element, $H[-1,-1]$.
• Matrix Convolution Example
In [1]:
import numpy as np
from scipy import ndimage

original = np.array(
[[1, 2],
[3, 4]])
k1 = np.array(
[[0, 0, 0],
[0, 1, 0],
[0, 0, 0]])
k2 = np.array(
[[1, 0, 1],
[0, 0, 0],
[1, 0, 1]])
k3 = np.array(
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])

c1 = ndimage.convolve(original, k1, mode='constant', cval=0.0)
c2 = ndimage.convolve(original, k2, mode='constant', cval=0.0)
c3 = ndimage.convolve(original, k3, mode='constant', cval=0.0)

print c1
print c2
print c3

[[1 2]
[3 4]]
[[4 3]
[2 1]]
[[10 10]
[10 10]]

In [2]:
original = np.array(
[[1, 2, 0, 0],
[5, 3, 0, 4],
[0, 0, 0, 7],
[9, 3, 0, 0]])
k1 = np.array(
[[0, 0, 0],
[0, 1, 0],
[0, 0, 0]])

c1 = ndimage.convolve(original, k1, mode='constant', cval=0.0)
print c1

[[1 2 0 0]
[5 3 0 4]
[0 0 0 7]
[9 3 0 0]]

In [3]:
original = np.array(
[[1, 2, 0, 0],
[5, 3, 0, 4],
[0, 0, 0, 7],
[9, 3, 0, 0]])
k2 = np.array(
[[1, 0, 1],
[0, 0, 0],
[1, 0, 1]])
c2 = ndimage.convolve(original, k2, mode='constant', cval=0.0)
print c2

[[ 3  5  7  0]
[ 2  1  9  0]
[ 6 14 10  0]
[ 0  0  7  0]]

In [4]:
original = np.array(
[[1, 2, 0, 0],
[5, 3, 0, 4],
[0, 0, 0, 7],
[9, 3, 0, 0]])
k3 = np.array(
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])

c3 = ndimage.convolve(original, k3, mode='constant', cval=0.0)
print c3

[[11 11  9  4]
[11 11 16 11]
[20 20 17 11]
[12 12 10  7]]

In [5]:
x1 = np.arange(9.0).reshape((3, 3))
print x1
x2 = np.arange(9.0).reshape((3, 3))
print x2
print np.multiply(x1, x2)

[[ 0.  1.  2.]
[ 3.  4.  5.]
[ 6.  7.  8.]]
[[ 0.  1.  2.]
[ 3.  4.  5.]
[ 6.  7.  8.]]
[[  0.   1.   4.]
[  9.  16.  25.]
[ 36.  49.  64.]]

In [6]:
original = np.array(
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
k3 = np.array(
[[-1, -2, 2],
[0, 0, 0],
[1, 2, 2]])
k4 = np.fliplr(k3)   # Flip array in the left/right (vertical) direction
k5 = np.flipud(k4)   # Flip array in the up/down (horizontal) direction
print k5
print
print np.multiply(original, k5)
print
print np.sum(np.multiply(original, k5))
print
c3 = ndimage.convolve(original, k3, mode='constant', cval=0.0)
print c3

[[ 2  2  1]
[ 0  0  0]
[ 2 -2 -1]]

[[  2   4   3]
[  0   0   0]
[ 14 -16  -9]]

-2

[[-13  -8  -2]
[-18  -2   8]
[ 13  24  22]]

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

try:
import urllib2
data = urllib2.urlopen(url) #PNG
except Exception:
import urllib.request
from io import BytesIO

plt.figure(figsize=(5, 5))
plt.imshow(im)
plt.show()

print(im.shape)

(100, 100, 3)

In [8]:
import scipy.signal
import numpy as np
import matplotlib.pyplot as plt
import urllib2

kernel = np.array(
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]) * 1.0 / 9.0

im_r = im[:,:,0]
print im_r.shape
print im_r
# convolve 2d the kernel with each channel
r = ndimage.convolve(im[:,:,0], kernel, mode='constant', cval=0.0)
g = ndimage.convolve(im[:,:,1], kernel, mode='constant', cval=0.0)
b = ndimage.convolve(im[:,:,2], kernel, mode='constant', cval=0.0)

# stack the channels back into a 8-bit colour depth image and plot it
im_out = (np.dstack([r, g, b]) * 255).astype(np.uint8)

plt.figure(figsize=(10, 5))
plt.subplot(1,2,1)
plt.imshow(im)
plt.subplot(1,2,2)
plt.imshow(im_out)
plt.show()

(100, 100)
[[ 0.51764709  0.50980395  0.49803922 ...,  0.58039218  0.57254905
0.58431375]
[ 0.50980395  0.5529412   0.50196081 ...,  0.58431375  0.55686277
0.57647061]
[ 0.5411765   0.57254905  0.61176473 ...,  0.59215689  0.56470591
0.58431375]
...,
[ 0.5529412   0.56470591  0.56862748 ...,  0.60392159  0.58039218
0.57647061]
[ 0.5529412   0.55686277  0.57254905 ...,  0.63529414  0.60784316
0.58039218]
[ 0.5529412   0.56862748  0.57647061 ...,  0.56862748  0.6156863
0.56862748]]