I need to reshape a 4D tensor of dimension a x b x c x d into a list of 3D ones, a * b x c x d. I need them to visualize filters after each convolutional layer, using the following code:
for k,v in pairs(model:findModules('cudnn.SpatialConvolution')) do
filters = v.weight
image.save("PathWhereToSave", image.scale(image.toDisplayTensor{input=filters}, 224, 224))
end
Unfortunately, due to the way the tensor are set up I receive this error:
packed must be a HxW or KxHxW or Kx3xHxW tensor, or a list of tensors
Do you have some suggestion or a better way to do what I need to do?
Thanks in advance
Related
I am converting numpy code to matlab. tensor is a 3D matrix of 6 x 2D matrices of the tensor components. This code appears to then split them back into those 6 separate 2D matrices.
gxx, gxy, gxz, gyy, gyz, gzz = tensor
Can I do this as eloquently in matlab?
re OmG: gxx, etc are the six tensor components of a gravity grid. xx for 2nd derivative of x in the x direction, xy is the 2nd derivative of x in the y direction, etc. Those components will be put through a simple equation to calculate the invariants which will then calculate the depth of the gravity anomaly.
As #Div-iL says, you could simply assign each variable to a slice of the 3D array:
tensor = rand(5,3,6); % Random data to play with
gxx = tensor(:,:,1);
gxy = tensor(:,:,2);
% etc
However if you really wanted to do it automatically you could generate a cell-array of 2D arrays (using mat2cell) and then assign them to variables using a comma-separated list assignment:
[nx,ny,nz] = size(tensor);
ca = mat2cell(tensor, nx, ny, ones(1,nz));
[gxx, gxy, gxz, gyy, gyz, gzz] = ca{:};
However, that all feels a bit hairy to me. If you're looking for a natively-supported one-liner (like your example) then I think you're out of luck.
The function to perform an N-dimensional convolution of arrays A and B in matlab is shown below:
C = convn(A,B) % returns the N-dimensional convolution of arrays A and B.
I am interested in a 3-D convolution with a Gaussian filter.
If A is a 3 x 5 x 6 matrix, what do the dimensions of B have to be?
The dimensions of B can be anything you want. There is no set restriction in terms of size. For the Gaussian filter, it can be 1D, 2D or 3D. In 1D, what will happen is that each row gets filtered independently. In 2D, what will happen is that each slice gets filtered independently. Finally, in 3D you will be doing what is expected in 3D convolution. I am assuming you would like a full 3D convolution, not just 1D or 2D.
You may be interested in the output size of convn. If you refer to the documentation, given the two N dimensional matrices, for each dimension k of the output and if nak is the size of dimension k for the matrix A and nbk is the size of dimension k for matrix B, the size of dimension of the output matrix C or nck is such that:
nck = max([nak + nbk - 1, nak, nbk])
nak + nbk - 1 is straight from convolution theory. The final output size of a dimension is simply the sum of the two sizes in dimension k subtracted by 1. However should this value be smaller than either of nak or nbk, we need to make sure that the output size is compatible so that any of the input matrices can fit in the final output. This is why you have the final output size and bounded by both A and B.
To make this easier, you can set the size of the filter guided by the standard deviation of the distribution. I would like to refer you to my previous Stack Overflow post: By which measures should I set the size of my Gaussian filter in MATLAB?
This determines what the output size of a Gaussian filter should be given a standard deviation.
In 2D, the dimensions of the filter are N x N, such that N = ceil(6*sigma + 1) with sigma being the desired standard deviation. Therefore, you would allocate a 3D matrix of size N x N x N with N = ceil(6*sigma + 1);.
Therefore, the code you would want to use to create a 3D Gaussian filter would be something like this:
% Example input
A = rand(3, 5, 6);
sigma = 0.5; % Example
% Find size of Gaussian filter
N = ceil(6*sigma + 1);
% Define grid of centered coordinates of size N x N x N
[X, Y, Z] = meshgrid(-N/2 : N/2);
% Compute Gaussian filter - note normalization step
B = exp(-(X.^2 + Y.^2 + Z.^2) / (2.0*sigma^2));
B = B / sum(B(:));
% Convolve
C = convn(A, B);
One final note is that if the filter you provide has any of its dimensions that are beyond the size of the input matrix A, you will get a matrix using the constraints of each nck value, but then the border elements will be zeroed due to zero-padding.
I have a matrix of A=[60x60],and two coefficients a,b. Since matrix A was moved by a,b, how to multiply the coefficients into matrix A so that I could obtain A_moved? Any function to do it?
Here's part of matlab code implemented:
A=rand(60); %where it's in 2D, A(k1,k2)
a=0.5; b=0.8;
[m, n]=size(A);
[M,N] = meshgrid(1:m,1:n);
X = [M(:), N(:)];
A_moved=A(:)(X)*[a b] %I know this is not valid but you get the idea
In another word A_moved is calculated by A_moved=a*k1+b*k2.
This line of code A_moved=A(:)(X)*[a b] is to represent my idea that a,b multiply back into the original A because X represent correspond coordinates of k1 and k2. The first column represent k1, and second column represent k2. Thus it become A_moved=a*k1+b*k2. But this couldn't get me anyway.
In the end A-moved is a 60x60 matrix which have been multiplied by coefficients a,b correspondingly. To make it clearer,A is the phase of image. a,b moved it phase.
Appreciate any help. Thank you!
Reference paper: Here
EDIT:
As suggested by Noel for better understanding.
A=[2 3;5 7], a=1.5 and b=2.5.
Since A is approximated as a*k1+b*k2
Thus,
A_moved=[1.5*k1_1+2.5k2_1 1.5*k1_2+2.5k2_2; 1.5*k1_2+2.5k2_1 1.5*k1_2+2.5k2_2];
where k1 and k2, If I'm understood correctly is the coordinates of the original A matrix, as defined in X above.
On the chat we found that your problem was matrix algebra related
What you want to obtain in A_moved is the x coordinate multiplied by a contant a plus the y coordinate multiplied by a constant b.
You already have this coordinates in M and N, so you can obtain A_moved as
A_moved = (a*M) + (b*N);
And it will retain same shape as A
I have a problem in constructing a vector from an image. I had used a 512 x 512 colour image and separated the rgb planes. Now i want to convert these three planes into three 1D vectors which should be as given in the following example.
Consider a 4x4x3 matrix. Converting it into RGB planes is easy. Now I need to convert these three planes into 1D vectors as given below
V=[r1g1b1....r6]
W=[g6b6r7...g11]
X=[b11r12...B16]
The program ive written is as follows. I used the reshape function to convert RGB planes into 1D vectors. Now I have trouble in regrouping them into different vectors.
A=imread('C:\Users\Desktop\lena.jpg');
% Extract the individual red, green, and blue color channels.
R = A(:, :, 1);
G = A(:, :, 2);
B = A(:, :, 3);
R1 = reshape(R.',1,[]);
G1 = reshape(G.',1,[]);
B1 = reshape(B.',1,[]);
I had converted the 2D matrices R G and B into 1D vectors R1, G1 and B1. Now I just need to create new vectores with all three values.I have no idea how to proceed...Please do help...Thanks in advance.
OK, given your example, what you want to do is given a RGB image, you want to separate the image into 3 vectors such that the RGB components are interleaved. This can easily be achieved by a permutation of the dimensions first. What you can do specifically is:
B = permute(A, [3 1 2]);
What permute does is that it rearranges the dimensions so that it produces another matrix. Specifically, what we're going to do is we are going to take each value in the third dimension and make them appear in the first dimension. Next we will take the rows of A and make them unroll into the columns, and finally the columns of A and make them go over each plane.
The result is that each column will be a unique RGB pixel that describes your image. How the unrolling will work though is that it will go in column-major order. We can then use linear indexing to split them up into arrays like so:
N = numel(A)/3;
V = B(1 : N);
W = B(N + 1 : 2*N);
X = B(2*N + 1 : end);
The job of linear indexing is that you access elements using a single index, rather than indexing each dimension separately. How linear indexing would work here is that if we had an image that was X x Y x 3, after permutation, the image would be reshaped such that it became a 3 x X x Y matrix. N in our case would be the total number of elements in a single plane. Because you are trying to split up the image into 3 vectors, the above operation where it's calculating N should be able to evenly divide by 3 as we have three colour planes to deal with.
By doing B(1 : N), we would access all of the elements from the first slice, second slice, in column-major format up until we retrieve N elements. These get placed into V. We then continue from this point and grab N more elements and place them into W, and finally the rest go into X.
If you want to access the pixels in row-major order, you simply need to change the way permute is accessing the dimensions like so:
B = permute(A, [3 2 1]);
You would then just access the elements with the above code normally. If you don't want to use linear indexing, you could use reshape to reshape the matrix such that it becomes a three-column matrix, where each column would be the desired vector:
C = reshape(B, [], 3);
V = C(:,1);
W = C(:,2);
X = C(:,3);
From your 4x4x3 example it's clear that you want to index first with the color index. I assume you then want row and then column. In that case, if A is your image (3D array), your desired three vectors are the columns of
B = reshape(permute(A,[3 1 2]),[],3);
So, if you need those vectors as explicit variables,
vector1 = B(:,1);
vector2 = B(:,2);
vector3 = B(:,3);
If the desired index order is color, then column, then row, use
B = reshape(permute(A,[3 2 1]),[],3);
There is a system of 3 linear equations composing of matrices which are represented by RGB image. Say
A = A1*x1 + A2*x2 + A3*x3 ......(Eq 1)
B= A1*x4 + A2*x5 + A3*x6 ........(Eq 2)
C= A1*x7 + A2*x8 + A3*x9 ........(Eq 3)
each are of equal dimension say 3D. I performed the following
A11=rgb2gray(A1);
x11=rgb2gray(x1);
A11 =double(A1) ; x11 = double(x11); b = A1*x1;
opts.UT = true; opts.TRANSA = false;
y1 = linsolve(x1,b,opts);
imshow(y1);
% The objective is to obtain A1,A2,A3
On doing this, following issues have surfaced:
1. Error
The output y1 is not the same as A1, which should have been. Why is it so? Please help
The R,G and B spaces are orthogonal. So you can solve each of those sets independently. The problem here is that mtimes, which is your matrix multiplication operator, doesn't accept 3D inputs.
To solve this, you can loop through each of R, G and B and use linsolve for each of the resulting 2D matrices. Normally, I wouldn't recommend loops for anything in MATLAB, but here, there won't be any discernable overhead as there are only 3 iterations in the loop.
Your answer will not be any different from what it would be if you were to solve them all in one go (if that were possible), because the three spaces are independent.
EDIT
The way you've written your equations, the xi's form the coefficient matrix and Ai's are the unknowns. The system of equations can be written compactly as XY=Z, where X is a 3D matrix composed of the coefficients, xi for each color space,RGB; Y is a 2D matrix, with a vector [A1, A2, A3]' in each color space, and Z is also a 2D matrix with vectors [A, B, C]' in each color space.
Assuming that the colorspace is the last dimension, you can try
[xPixels,yPixels,colorSpace]=size(X);
Y=zeros(yPixels,colorspace);
opts.UT=true; opts.TRANSA=false;
for i=1:colorspace
Y(:,i)=linsolve(X(:,:,i),Z(:,i),opts);
end
You'll have to setup the matrices X, Y and Z according to your problem. It is helpful to keep the looped dimension (in this case, colorspace) as the outermost dimension, as otherwise, you'll have to use squeeze to remove the singleton dimensions.