Convolve2d just using numpy

I am studying image processing using Numpy and am facing a convolution filtering issue.

I would like to collapse the gray image. (flatten a 2d array with a smaller 2d array)

Anyone have an idea to refine my method?

I know that scipy supports convolve2d, but I want to make convolve2d only with Numpy.

What I've done

First I made a 2d array of submatrices.

a = np.arange(25).reshape(5,5) # original matrix submatrices = np.array([ [a[:-2,:-2], a[:-2,1:-1], a[:-2,2:]], [a[1:-1,:-2], a[1:-1,1:-1], a[1:-1,2:]], [a[2:,:-2], a[2:,1:-1], a[2:,2:]]]) 

the submatrices seem complicated, but what I'm doing is shown in the following figure.

submatrices

Then I multiplied each sub-matrix using a filter.

 conv_filter = np.array([[0,-1,0],[-1,4,-1],[0,-1,0]]) multiplied_subs = np.einsum('ij,ijkl->ijkl',conv_filter,submatrices) 

multiplied_subs

and let them down.

 np.sum(np.sum(multiplied_subs, axis = -3), axis = -3) #array([[ 6, 7, 8], # [11, 12, 13], # [16, 17, 18]]) 

Thus, this procedure can be called my convolve2d.

 def my_convolve2d(a, conv_filter): submatrices = np.array([ [a[:-2,:-2], a[:-2,1:-1], a[:-2,2:]], [a[1:-1,:-2], a[1:-1,1:-1], a[1:-1,2:]], [a[2:,:-2], a[2:,1:-1], a[2:,2:]]]) multiplied_subs = np.einsum('ij,ijkl->ijkl',conv_filter,submatrices) return np.sum(np.sum(multiplied_subs, axis = -3), axis = -3) 

However, I find this my_convolve2d unpleasant for 3 reasons.

  1. The generation of submatrices is too inconvenient, which makes it difficult to read, and it can be used only with a filter value of 3 * 3.
  2. The size of the variable submatrix seems too large because it is approximately 9 times larger than the original matrix.
  3. Summing up seems a bit unintuitive. Simply put, ugly.

Thanks for reading this far.

Type of update. I wrote conv3d for myself. I will leave it as the public domain.

 def convolve3d(img, kernel): # calc the size of the array of submatracies sub_shape = tuple(np.subtract(img.shape, kernel.shape) + 1) # alias for the function strd = np.lib.stride_tricks.as_strided # make an array of submatracies submatrices = strd(img,kernel.shape + sub_shape,img.strides * 2) # sum the submatraces and kernel convolved_matrix = np.einsum('hij,hijklm->klm', kernel, submatrices) return convolved_matrix 
+10
source share
4 answers

You can generate subarrays with as_strided [1] :

 import numpy as np a = np.array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [20, 21, 22, 23, 24]]) sub_shape = (3,3) view_shape = tuple(np.subtract(a.shape, sub_shape) + 1) + sub_shape strides = a.strides + a.strides sub_matrices = np.lib.stride_tricks.as_strided(a,view_shape,strides) 

To get rid of the second ugly sum, change your einsum so that the output array has only j and k . This implies your second summation.

 conv_filter = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]]) m = np.einsum('ij,ijkl->kl',conv_filter,sub_matrices) # [[ 6 7 8] # [11 12 13] # [16 17 18]] 
+11
source

You can also use FFT (one of the faster methods for doing convolution)

 from numpy.fft import fft2, ifft2 import numpy as np def fft_convolve2d(x,y): """ 2D convolution, using FFT""" fr = fft2(x) fr2 = fft2(np.flipud(np.fliplr(y))) m,n = fr.shape cc = np.real(ifft2(fr*fr2)) cc = np.roll(cc, -m/2+1,axis=0) cc = np.roll(cc, -n/2+1,axis=1) return cc 

cheers Dan

+5
source

Removed using as_strided and @Crispin einsum on top. Provides filter size in expanded form. Even if the indexes are compatible, allow even non-square inputs.

 def conv2d(a, f): s = f.shape + tuple(np.subtract(a.shape, f.shape) + 1) strd = numpy.lib.stride_tricks.as_strided subM = strd(a, shape = s, strides = a.strides * 2) return np.einsum('ij,ijkl->kl', f, subM) 
+2
source
 def conv2d(a, f): s = f.shape + tuple(np.subtract(a.shape, f.shape) + 1) strd = numpy.lib.stride_tricks.as_strided subM = strd(a, shape = s, strides = a.strides * 2) return np.einsum('ij,ijkl->kl', f, subM) 

It would be greatly appreciated if someone would help me by explaining this set of lines of code.

0
source

Source: https://habr.com/ru/post/1274898/


All Articles