using Fourier transforms to do convolution? - python

According to the Convolution theorem, we can convert the Fourier transform operator to convolution.
Using Python and Scipy, my code is below but not correct.
Can you help me and explain it?
import tensorflow as tf
import sys
from scipy import signal
from scipy import linalg
import numpy as np
x = [[1 , 2] , [7 , 8]]
y = [[4 , 5] , [3 , 4]]
print "conv:" , signal.convolve2d(x , y , 'full')
new_x = np.fft.fft2(x)
new_y = np.fft.fft2(y)
print "fft:" , np.fft.ifft2(np.dot(new_x , new_y))
The result of code:
conv: [[ 4 13 10]
[31 77 48]
[21 52 32]]
fft: [[ 20.+0.j 26.+0.j]
[ 104.+0.j 134.+0.j]]
I'm confused!

The problem may be in the discrepancy between the discrete and continuous convolutions. The convolution kernel (i.e. y) will extend beyond the boundaries of x, and these regions need accounting for in the convolution.
scipy.signal.convolve will by default pad the out of bounds regions with 0s, which will bias results:
https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.signal.convolve2d.html
The Fourier multiplication will not do this by default - you could test this by making padded x, y arrays and comparing the results.
The discrepancy between such techniques should diminish as the kernel size becomes much less than the image dimensions.
As a further note - you should not use the dot product between new_x, new_y. Instead, just multiply the arrays with the * operator.
Hope this helps.

I answer my question.
The correct code.
import sys
from scipy import signal
from scipy import linalg
import numpy as np
x = [[1 , 0 , 0 , 0] , [0 , -1 , 0 , 0] , [0 , 0 , 3 , 0] , [0 , 0 , 0 , 1]]
x = np.array(x)
y = [[4 , 5] , [3 , 4]]
y = np.array(y)
print "conv:" , signal.convolve2d(x , y , 'full')
s1 = np.array(x.shape)
s2 = np.array(y.shape)
size = s1 + s2 - 1
fsize = 2 ** np.ceil(np.log2(size)).astype(int)
fslice = tuple([slice(0, int(sz)) for sz in size])
new_x = np.fft.fft2(x , fsize)
new_y = np.fft.fft2(y , fsize)
result = np.fft.ifft2(new_x*new_y)[fslice].copy()
print "fft for my method:" , np.array(result.real , np.int32)
print "fft:" , np.array(signal.fftconvolve(x ,y) , np.int32)

Related

looping through two arrays and using jax.cond to apply different function when they have same index

I am struggling with the functional programming theme of Jax. I am trying to implement this using jax, especially how to build the pred of jax.cond for the index match for two arrays. The equivalent function/ minimal example is below.
odd = np.array([1,3,5,7,9])
even = np.array([0,2,6,8,10])
Kmat = np.zeros((even.shape[0], odd.shape[0]))
for i, elm1 in enumerate(odd):
for j, elm2 in enumerate(even):
if i==j:
Kmat[i,j] = 0
else:
Kmat[i,j] = elm1 - elm2
this is what i tried
arr1 = np.array([1,3,5,7,9])
arr2 = np.array([0,2,6,8,10])
x = np.arange(arr1.shape[0])
y = np.arange(arr2.shape[0])
f1 = lambda _ : 0
f2 = lambda x,y,arr1, arr2 : arr1[x]- arr2[y]
predVec = np.eye(arr1.shape[0], dtype=bool)
func = lambda pred : jax.lax.cond(pred,f1,f2, [x,y,arr1, arr2])
jax.vmap(func)(predVec)
I'd avoid loops and conditionals here and use numpy-style broadcasting instead. For example:
import jax.numpy as jnp
i = jnp.arange(len(odd))[:, None]
j = jnp.arange(len(even))
Kmat = jnp.where(i == j, 0.0, odd[:, None] - even)
print(Kmat)
[[ 0. -1. -5. -7. -9.]
[ 3. 0. -3. -5. -7.]
[ 5. 3. 0. -3. -5.]
[ 7. 5. 1. 0. -3.]
[ 9. 7. 3. 1. 0.]]
Alternatively, if you're working with functions f1 and f2 that require scalar inputs (and are JAX-compatible), you could express this using a nested vmap transform:
from jax import vmap
import jax.numpy as jnp
from functools import partial
odd = jnp.array([1,3,5,7,9])
even = jnp.array([0,2,6,8,10])
def f1(x, y):
assert x.ndim == y.ndim == 0
return 0
def f2(x, y):
assert x.ndim == y.ndim == 0
return x - y
#partial(vmap, in_axes=(0, None))
#partial(vmap, in_axes=(None, 0))
def g(i, j):
return jnp.where(i == j, f1(odd[i], even[j]), f2(odd[i], even[j]))
Kmat = g(jnp.arange(len(odd)), jnp.arange(len(even)))
print(Kmat)
[[ 0 -1 -5 -7 -9]
[ 3 0 -3 -5 -7]
[ 5 3 0 -3 -5]
[ 7 5 1 0 -3]
[ 9 7 3 1 0]]

Reformatting a numpy array

I have come across some code (which may answer this question of mine). Here is the code (from Vivek Maskara's solution to my issue):
import cv2 as cv
import numpy as np
def read(image_path, label):
image = cv.imread(image_path)
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
image_h, image_w = image.shape[0:2]
image = cv.resize(image, (448, 448))
image = image / 255.
label_matrix = np.zeros([7, 7, 30])
for l in label:
l = l.split(',')
l = np.array(l, dtype=np.int)
xmin = l[0]
ymin = l[1]
xmax = l[2]
ymax = l[3]
cls = l[4]
x = (xmin + xmax) / 2 / image_w
y = (ymin + ymax) / 2 / image_h
w = (xmax - xmin) / image_w
h = (ymax - ymin) / image_h
loc = [7 * x, 7 * y]
loc_i = int(loc[1])
loc_j = int(loc[0])
y = loc[1] - loc_i
x = loc[0] - loc_j
if label_matrix[loc_i, loc_j, 24] == 0:
label_matrix[loc_i, loc_j, cls] = 1
label_matrix[loc_i, loc_j, 20:24] = [x, y, w, h]
label_matrix[loc_i, loc_j, 24] = 1 # response
return image, label_matrix
Would it be possible for you to explain how this part of the code works and what it specifically does:
if label_matrix[loc_i, loc_j, 24] == 0:
label_matrix[loc_i, loc_j, cls] = 1
label_matrix[loc_i, loc_j, 20:24] = [x, y, w, h]
label_matrix[loc_i, loc_j, 24] = 1 # response
I will first create and explain a simplified example, and then explain the part you pointed.
First, we create the ndarray named label_matrix:
import numpy as np
label_matrix = np.ones([2, 3, 4])
print(label_matrix)
This code means that you wil get an array containing 2 arrays, each of these 2 arrays will contain 3 arrays, and each of these 3 arrays will contain 4 elements.
And because we used np.ones, all these elements will have a value of 1.
So, printing label_matrix wil output this:
[[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]]
Now, we will change the values of first 4 elements of the first array contained by the first array of label_matrix.
To acces the first array of label_matrix, we do: label_matrix[0]
To access the first array contained by the first array of label_matrix we do: label_matrix[0, 0]
To access the first element of the first array contained by the first array of label_matrix we do: label_matrix[0, 0, 0]
To access the second element of the first array contained by the first array of label_matrix we do: label_matrix[0, 0, 1]
etc.
So, now, we will change the values of first 4 elements of the first array contained by the first array of label_matrix:
label_matrix[0, 0, 0] = 100
label_matrix[0, 0, 1] = 200
label_matrix[0, 0, 2] = 300
label_matrix[0, 0, 2] = 400
Output of label_matrix:
[[[100. 200. 300. 400.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]
[[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]]
But we could have written it like this, instead of wrting 4 lines of codes:
label_matrix[0, 0, 0:4] = [100,200,300,400]
Writing label_matrix[0, 0, 0:4] means:
in the first array contained by the first array of label_matrix, select the 4 first elements (from index 0 to 4 (4 being not included))
So now you know the meaning of each line.
I'll explain the part of code you pointed:
if label_matrix[loc_i, loc_j, 24] == 0::
Test if the element at index 24 (the 23th element) has value 0
if yes, then:
label_matrix[loc_i, loc_j, cls] = 1:
assign the value 1 to the element at index cls. (If the variable named cls has value 4, it will assigne the value 1 to the element at index 4 of the first array contained by the first array of label_matrix)
label_matrix[loc_i, loc_j, 20:24] = [x, y, w, h]:
Say "x==100", "y==200", "w==300" and "h==400". So, in the first array contained by the first array of label_matrix, assign value 100 to the elemnt at index 20, value 200 to the elemnt at index 21, 300 at index 22 and 400 to index 23
label_matrix[loc_i, loc_j, 24] = 1:
in the first array contained by the first array of label_matrix, assign value 1 to the element at index 24

Numpy - Declare a specific nx1 array

I'm using numpy in python , in order to create a nx1 matrix . I want the 1st element of the matrix to be 3 , the 2nd -1 , then the n-1 element -1 again and at the end the n element 3. All the in between elements , i.e. from element 3 to element n-2 should be 0. I've made a drawing of the mentioned matrix , is like this :
I'm fairly new to python and using numpy but seems like a great tool for managing matrices. What I've tried so far is creating the nx1 array (giving n some value) and initializing it to 0 .
import numpy as np
n = 100
I = np.arange(n)
matrix = np.row_stack(0*I)
print("\Matrix is \n",matrix)
Any clues to how i proceed? Or what routine to use ?
Probably the simplest way is to just do the following:
import numpy as np
n = 10
a = np.zeros(n)
a[0] = 3
a[1] = -1
a[len(a)-1] = 3
a[len(a)-2] = -1
>>print(a)
output: [ 3. -1. 0. 0. 0. 0. 0. 0. -1. 3.]
Hope this helps ;)
In [97]: n=10
In [98]: arr = np.zeros(n,int)
In [99]: arr[[0,-1]]=3; arr[[1,-2]]=-1
In [100]: arr
Out[100]: array([ 3, -1, 0, 0, 0, 0, 0, 0, -1, 3])
Easily changed to (n,1):
In [101]: arr[:,None]
Out[101]:
array([[ 3],
[-1],
[ 0],
[ 0],
[ 0],
[ 0],
[ 0],
[ 0],
[-1],
[ 3]])
I guess something that works is :
import numpy as np
n = 100
I = np.arange(n)
matrix = np.row_stack(0*I)
matrix[0]=3
matrix[1]=-1
matrix[n-2]=-1
matrix[n-1]=3
print("\Matrix is \n",matrix)

MinMaxScaler in Scikit Learn seems to be returning scaled values not belonging to the range of values specified by the `feature_range` parameter

This is the example from official: http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html
>>> from sklearn.preprocessing import MinMaxScaler
>>>
>>> data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
>>> scaler = MinMaxScaler()
>>> print(scaler.fit(data))
MinMaxScaler(copy=True, feature_range=(0, 1))
>>> print(scaler.data_max_)
[ 1. 18.]
>>> print(scaler.transform(data))
[[ 0. 0. ]
[ 0.25 0.25]
[ 0.5 0.5 ]
[ 1. 1. ]]
>>> print(scaler.transform([[2, 2]]))
[[ 1.5 0. ]]
The official document is as below.
transform(X)[source] Scaling features of X according to feature_range.
Parameters: X : array-like, shape [n_samples, n_features]
Input data that will be transformed.
Why am I seeing [[ 1.5 0. ]] as an output when the default value for feature_range parameter is (0, 1)?
Consider the transform operation like this:
import numpy as np
data = np.array(data)
f1 = data[:,0]
mn = f1.min()
mx = f1.max()
(f1- mn)/ (mx - mn)
note: the transform operation is constructed from your initial data. once the tranform operation is constructed, it will operate on your secondary data and does not re-scale it again.
you may have problem with parameter feature_range. In that case you should know that after minmaxtransform it rescale the data.

How to get matrix rows by indexes?

Assuming that we have a matrix X and a target column y as following:
import numpy as np
X = np.ones([10,2])
for i in range(0,X.shape[0]):
X[i][0] = i
y = [0,1,2,1,0,0,1,2,3,3]
I want to get rows of X depending on the value of y. From the small example above:
For y == 0, I want to get rows of X as:
[[0 1]
[4 1]
[5 1]]
For y == 3, I want to get rows of X as:
[[8 1]
[9 1]]
And so on.
How can I solve this problem?
I also tried
print(X[y == 0][:])
But it did not work.
You must convert ordinary python array to numpy.ndarray, as follow
Y=np.array(y)
print(X[Y == 0][:])
you will get:
[[ 0. 1.]
[ 4. 1.]
[ 5. 1.]]

Categories