Understanding Matlab multidimentionnal array - matlab

I would like to have a better comprehension of Matlab mutidimensionnal arrays and the : operator with a quick question
So I ran this example
A = zeros(2,3,4,5);
size(A)
% ans = 2 3 4 5
%% 1.
size(A(:,:,1,1))
% ans = 2 3
%% 2.
size(A(1,1,:,:))
% ans = 1 1 4 5
%% 3.
size(reshape(A(1,1,:,:), 4, 5))
% ans = 4 5
1. is the behavior I actually expected for all operations.
I don't understand why do I kept unwanted dimension in 2.
Do I need to reshape like in 3. everytime I need a subarray ?

Matlab removes singleton trailing dimensions only, so what you see is normal.
In 1, you removed a 2D subset from a 4D array, but the first two dimensions were "row" and "column".
In 2, the "row" and "column" are both singleton, and the rest of the array is in the third and fourth dimensions, so Matlab keeps it that way.
Instead of reshapeing, you can squeeze(A(1,1,:,:)) to remove dimensions that have length one (except for dimensions 1 and 2, which are sort of hard-coded into Matlab).

You can use reshape or simply squeeze in this case.
MATLAB always removes trailing singleton dimensions (past the first two):
>> size(zeros(4,4,4,1,1))
ans =
4 4 4
But it also adds them when needed (or as Ander points out in the comment, they are always implicitly there):
>> a = zeros(4,4);
>> a(2,2,1,1); % is OK
>> size(a,100)
ans =
1
On the other hand, other singleton dimensions are kept. squeeze removes them.
For your particular application it makes sense to remove singleton dimensions, but other applications would have problems if this were the default behavior. Imagine code that extracts a certain sub-volume, and changing the direction of the data depending on how many rows or columns are selected. For example:
>> a(1:x,1:y,1:z)
would return an array of size (x,y,z) as long as x and y are larger than one. Make x=1, and now it's an array of size (y,z)? Bad idea!

Related

How does numel work in adding zeroes to change the dimension of a vector in matlab?

I am trying to add two vectors; however, they do not have the same dimensions. For example only (since the one I am doing have 1000+ values), the vectors are:
a = [1 2 3 4 5];
b = [1 2];
Since they do not have the same dimensions, I want to simply add zeroes to vector b to match the dimension of vector a.
Using the code b(numel(a)) = 0; I was able to do it. However, I am quite confused on how it worked as I only saw this code on the internet. I know that numel(a) is equal to 5, but I don't know how that code was able to add zeroes after 1 2 in variable b to match the dimension of variable a.
Can anyone explain?
When you set b(5) = 0, matlab can not simply leave the intervening elements b(3:4) unfilled, so they get zeros. If you did b(numel(a)) = 1, the intervening elements would still be filled with zero.
Keep in mind that this is a short cut that only works if you know for that fact that b is shorter than a. If not, you will be setting an element of b to 0, which is likely not what you want.

What to call (1 by n) plus (n by 1) operation?

I stumbled across an unexpected behavior of the addition operator.
a=[1 2 3];
b=[5; 7; 11];
a+b
Produces
ans =
6 7 8 % a(1)+b(1) a(1)+b(2) a(1)+b(3)
8 9 10 % a(2)+b(1) a(2)+b(2) a(2)+b(3)
12 13 14 % a(3)+b(1) a(3)+b(2) a(3)+b(3)
This behavior probably falls under the Add a Vector to a Matrix example in the documentation.
Create an array, A, and add a column vector to it. The vector is
treated as though it is a matrix of the same size as A, so that each
element in the vector is added to a row in A.
Although, b in my example cannot be treated as the same size as a. Both vectors must be duplicated.
What can I call this behavior when I am describing it to others? None of the definitions of Matrix Addition fit. Vector addition also has a different definition. The best I could come up with was the "sum of the elements in the cartesian product".
That's called binary singleton expansion. Starting with R2016b, MATLAB does it automatically with standard operators. See bsxfun for more details.

Average on contiguos segments of a vector

I'm sure this is a trivial question for a signals person. I need to find the function in Matlab that outputs averaging of contiguous segments of windowsize= l of a vector, e.g.
origSignal: [1 2 3 4 5 6 7 8 9];
windowSize = 3;
output = [2 5 8]; % i.e. [(1+2+3)/3 (4+5+6)/3 (7+8+9)/3]
EDIT: Neither one of the options presented in How can I (efficiently) compute a moving average of a vector? seems to work because I need that the window of size 3 slides, and doesnt include any of the previous elements... Maybe I'm missing it. Take a look at my example...
Thanks!
If the size of the original data is always a multiple of widowsize:
mean(reshape(origSignal,windowSize,[]));
Else, in one line:
mean(reshape(origSignal(1:end-mod(length(origSignal),windowSize)),windowSize,[]))
This is the same as before, but the signal is only taken to the end minus the extra values less than windowsize.

Matlab: Create a zero matrix with 1 in a particular place

For example, I can create a zeros(100). But I want the entry of row 58 and column 59 to be 1. But I need temporary variable and multiple lines to do this.
a. Let this matrix be M. How can I do this in one line? M = ....?
P.S.
b. Better still, sometimes I want two or more entries of the zero matrix be 1.
Again, how can I do this?
If I can do a. in one-line, of course I can add them up. But is there any special function to do fill zero matrix entries with 1?
First, remember that a one line expression isn't always the most effective. It could also be harder to read/understand.
One way to do this is by using a sparse matrix
The following example creates a 10x10 zero-matrix with ones at [5,2] (row 5, col 2) and [7 5]
full(sparse([5 7],[2 5],1,10,10))
Use full to convert it from a sparse matrix to a "full" one
Another (faster but maybe not as intuitive) alternative is to use accumarray
accumarray([5 2;7 5],1,[10,10])
Remember that the index values above is used directly in the expression to get on one line, the better option would be to create them separately
points = [5 2; 7 5]
or perhaps,
rowIdx = [5 7];
colIdx = [2 5];

Matlab Co-occurrence Matrix

I'm sure this is a very simple mistake by me somewhere! But when I use Matlab's graycomatrix function, I don't get the expected result. Instead of a matrix output I expect, I always get an 8 x 8 (nearly) zero matrix with one entry in the bottom right - usually equal to 16. I haven't changed the default settings or used 'offset', so I'm not too sure what the problem is.
That's because your image is not normalized!
Your image should be range 0-1, so:
I = [1 1 2; 2 2 3; 1 2 5]; %or any other I
glcm = graycomatrix(I/max(I(:))); % or I/255 , but it would not work for this example
should do the job.
In your case, Matlab interprets that everything avobe 1 is 1, therefore the co-occurrence matrix gives you a unique value in the max position.