2

There are already some answers regarding the conv2(A,B,'same') function (e.g. here: 2D Convolution in Python similar to Matlab's conv2) but I was unable to find anything regarding conv2(h1,h2,A,'same').

To quote the MATLAB documentation:

C = conv2(h1,h2,A) first convolves A with the vector h1 along the rows and then with the vector h2 along the columns. The size of C is determined as follows: if n1 = length(h1) and n2 = length(h2), then mc = max([ma+n1-1,ma,n1]) and nc = max([na+n2-1,na,n2]).

Is there a way to achieve this behavior using python (or numpy, scipy, etc.)?

Context:

I try to achieve the following:

h1 = [ 0.05399097  0.24197072  0.39894228  0.24197072  0.05399097]
h2 = [ 0.10798193  0.24197072 -0.         -0.24197072 -0.10798193]
A  = img[:,:,1]
C  = conv2(h1, h2, A, 'same')

Where img is a rgb image.

Community
  • 1
  • 1
jnodorp
  • 217
  • 2
  • 10

1 Answers1

4

You probably want something like:

def conv2(v1, v2, m, mode='same'):
    """
    Two-dimensional convolution of matrix m by vectors v1 and v2

    First convolves each column of 'm' with the vector 'v1'
    and then it convolves each row of the result with the vector 'v2'.

    """
    tmp = np.apply_along_axis(np.convolve, 0, m, v1, mode)
    return np.apply_along_axis(np.convolve, 1, tmp, v2, mode)

Applying to the example in MATLAB's documentation of conv2:

A = np.zeros((10, 10))
A[2:8, 2:8] = 1
x = np.arange(A.shape[0])
y = np.arange(A.shape[1])
x, y = np.meshgrid(x, y)

u = [1, 0, -1]
v = [1, 2, 1]

Ch = conv2(u, v, A, 'same')
Cv = conv2(v, u, A, 'same')

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

plt.figure()
ax = plt.gca(projection='3d')
ax.plot_surface(x, y, Ch)

plt.figure()
ax = plt.gca(projection='3d')
ax.plot_surface(x, y, Cv)

Ch

Cv

Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
  • 1
    @Nikko I've updated the answer. Reproducing the example in MATLAB`s documentation – Saullo G. P. Castro Apr 17 '18 at 23:36
  • Thanks! I can run it. Sadly I can't plot the resulting image. (so my img is a grayscaled imaged (using Image.open.convert) and then applied your func. I am not sure how to transform back from Ch to an image – Nikko Apr 17 '18 at 23:57
  • ps: Ch.shape gives me (900,900,2) – Nikko Apr 18 '18 at 00:04
  • @Nikko perhaps you have to do: `img[:, :, 0] = conv2(u, v, img[:, :, 0])` and so forth... for indices `0, 1, 2` if you have an RGB image – Saullo G. P. Castro Apr 18 '18 at 00:44
  • super. Thank you for the answer. I am comparing the output from matlab and python. Although it worked, the output values (the matrix) are not the same. I'm not sure if I should create another question. But I need and appreciate your help. I'll continue tomorrow. thx again ps: the matlab output from conv2 gives me a 900x900 matrix. I am not sure why we have one more dimension in py. – Nikko Apr 18 '18 at 01:38
  • your solution works perfectly, with some minor changes (when the matrixes are cols=rows, everything works perfectly, but if not, I had to transpose and change some things. But overall this was the solution!. Thx very much! – Nikko Apr 19 '18 at 16:15
  • @Nikko, please suggest an update in this answer to correct what you've found thanks! – Saullo G. P. Castro Apr 19 '18 at 16:45
  • ok will do. Btw, I've been working on this but sadly the results from your method don't match 100% with the results in matlab. And I have no idea why. But when the values are small (O(1e-12)) the restults from matlab and python differ noticeably =/. – Nikko Apr 23 '18 at 21:40