Is it possible to do interpolation over 4d data? - python

I am trying to implement this paper. I have to try to interpolate the latent code of an autoencoder, as mentioned in the paper. The latent code is the encoded input of an autoencoder. The shape of the latent code (for two samples) is (2, 64, 64, 128).
This is what I have done:
image1 = sel_train_encodings[0]
image2 = sel_train_encodings[1]
x = image1[:,0,0]
x_new = image2[:,0,0]
new_array = interp1d(x, image1, axis=0, fill_value='extrapolate', kind='linear')(x_new)
I basically took the encodings of two images and tried to interpolate( with extrapolation for some points as all points don't lie in the same range) and then did interpolation over one of the axes. But the results I later obtain with these interpolated values are not so good, am I doing something wrong/how else to do it?
According to one of the given answers, I also tried to do 2D interpolation in the following way:
image1 = sel_train_encodings[0]
image2 = sel_train_encodings[1]
new_array = griddata((x,z),y,(x_new, z_new), method='cubic', fill_value='extrapolate')
But this resulted in the error:
ValueError: shape mismatch: objects cannot be broadcast to a single shape

Scipy has a couple of 2D interpolation routines, depending on the spacing of the (x, y):
If your data is on a regular grid, try scipy.interpolate.RectBivariateSpline(). This is probably most applicable to images.
If your data is collected on a grid with uneven rectangular intervals, you want to use scipy.interpolate.interp2d().
If all bets are off and the (x, y) are scattered without any clear grid, try scipy.interpolate.griddata()

Related

How can I reverse .reshape() and get back to a 3D array?

I have a dataset of shape (256, 180, 360). I reshaped it to 2D, removed the 0 values, and applied PCA using:
data = data.reshape(data.shape[0], data.shape[1] * data.shape[2]).T
data = data[~np.all(data == 0, axis = 1)]
# Dataset is now of shape (27719, 256)
data = StandardScaler().fit_transform(data)
pca = PCA()
transformed = pca.fit_transform(data)
Now, the next step is to reshape the transformed dataset back to 3D and plot the PCA results. I tried:
transformed.reshape(360, 180, 256)
which gives me the error "cannot reshape array of size 7096064 into shape (360,180,256)". I understand I cannot get back to the original shape because I removed 0 values which changes that shape, of course, but I have tried other variations of this alongside using variations with the transpose but I cannot get it back to 3D (not necessarily the exact dimensions as before). Any recommendations?
You can't.
What you can do in this scenario is to not use fit_transform, and instead have two separate pipelines. One that uses fit to train on the dataset with all the zero entries removed, and then use transforms on the original dataset to get your transformed data.
flat_data = data.reshape(data.shape[0], data.shape[1] * data.shape[2]).T
nonzero_data = flat_data[~np.all(flat_data == 0, axis = 1)]
scaler = StandardScaler()
pca = PCA()
pca.fit(scaler.fit_transform(nonzero_data))
transformed = pca.transform(scaler.transform(flat_data)).reshape(data.shape)

CV2.approxPolyDP Function Returns an N x 1 x 2 Array Rather Than N x 2

I have a function that draws a polygon around some primary features in images by making use of OpenCV's contour detection. I simplify these contours using the approxPolyDP function in the snippet below to return a closed trapezoid around the regions, and it works fine:
top_poly = cv.approxPolyDP(top_cnt, 0.05 * top_perimeter, closed=True)
top_poly = np.squeeze(top_poly) # get rid of the singleton dimension
However, the approxPolyDP returns a strange type of ndarray which has a shape of N x 1 x 2, when the expected output according to the documentation linked below is an array of N x 2D points (N x 2). I had to debug for a while until I found that singleton dimension in there can be carved out using np.squeeze in the second line of the snippet. Thanks to this answer: What does cv2.approxPolydp() return?
My question is, what is the purpose of this singleton dimension? I worry I might be dropping some useful information and I don't enjoy having to use np.squeeze() in a way I don't completely understand. Thanks for any input that can shed some light on this.
https://docs.opencv.org/4.5.4/d3/dc0/group__imgproc__shape.html#ga0012a5fdaea70b8a9970165d98722b4c
The result shape happens because of OpenCV's requirements, i.e. it has to map numpy arrays to cv::Mat and back.
A cv::Mat is a 2D thing with channels, which can be color (RGB or whatever), 2D points, 3D points, 4D, ..., or any other purpose.
The shape is generally (height, width, channels).
OpenCV returns the points as a column vector (Nx1) of 2-channel data, hence (N, 1, 2).
OpenCV is somewhat tolerant of different shapes like (N, 2, 1) which is (N, 2) (N rows, 2 columns, single-channel).

python 2d contourf plot using 3d np array data

I have a problem here.
My data is a 3d shape of np array
(256, 256, 1) = (x coordinate, y coordinate, pressure value)
Now I would like to draw a contour plot using this np array.
But the problem is that the shape of my data does not fit into plt.contourf
Any idea on how to preprocess my data before feeding it to contourf?
Since you have a singular value for each position [M,N], you can simply squeeze out that dimension and have it represented by a matrix of shape [M,N].
data = data.squeeze(2)
plt.contourf(data)
The squeezed and original array contain the exact same data, but are just represented slightly differently.

Reshaping numpy array

What I am trying to do is take a numpy array representing 3D image data and calculate the hessian matrix for every voxel. My input is a matrix of shape (Z,X,Y) and I can easily take a slice along z and retrieve a single original image.
gx, gy, gz = np.gradient(imgs)
gxx, gxy, gxz = np.gradient(gx)
gyx, gyy, gyz = np.gradient(gy)
gzx, gzy, gzz = np.gradient(gz)
And I can access the hessian for an individual voxel as follows:
x = 100
y = 100
z = 63
H = [[gxx[z][x][y], gxy[z][x][y], gxz[z][x][y]],
[gyx[z][x][y], gyy[z][x][y], gyz[z][x][y]],
[gzx[z][x][y], gzy[z][x][y], gzz[z][x][y]]]
But this is cumbersome and I can't easily slice the data.
I have tried using reshape as follows
H = H.reshape(Z, X, Y, 3, 3)
But when I test this by retrieving the hessian for a specific voxel the, the value returned from the reshaped array is completely different than the original array.
I think I could use zip somehow but I have only been able to find that for making lists of tuples.
Bonus: If there's a faster way to accomplish this please let me know, I essentially need to calculate the three eigenvalues of the hessian matrix for every voxel in the 3D data set. Calculating the hessian values is really fast but finding the eigenvalues for a single 2D image slice takes about 20 seconds. Are there any GPUs or tensor flow accelerated libraries for image processing?
We can use a list comprehension to get the hessians -
H_all = np.array([np.gradient(i) for i in np.gradient(imgs)]).transpose(2,3,4,0,1)
Just to give it a bit of explanation : [np.gradient(i) for i in np.gradient(imgs)] loops through the two levels of outputs from np.gradient calls, resulting in a (3 x 3) shaped tensor at the outer two axes. We need these two as the last two axes in the final output. So, we push those at the end with the transpose.
Thus, H_all holds all the hessians and hence we can extract our specific hessian given x,y,z, like so -
x = 100
y = 100
z = 63
H = H_all[z,y,x]

How to represent a 2d array by matplotlib

I want to plot an array ndarray by matplotlib which is defined as
dataset = np.ndarray(shape=(len(image_files), image_size, image_size),
dtype=np.float32)
My question is what is the syntax of plt.plot() will be in case of plotting arrays like this?
Thank You
If your array is three dimensional you cannot directly plot it in two dimensions.
In your case it seems that you store several images along the first axis of the array. So for an array
dataset = np.ndarray(shape=(len(image_files), image_size, image_size),
dtype=np.float32)
You can plot the ith image out of it via
plt.imshow(dataset[i,:,:])
If this does not answer the question, you'd need to be more specific about what exactly you want to plot.

Categories