Matlab "for loop" to create a matrix - matlab

I have a fairly large vector named blender. I have extracted n elements for which blender is greater than x (irrelevant). Now my difficulty is the following:
I am trying to create a (21 x n) matrix with each element of blender plus 10 things before, and the 10 things after.
element=find(blender >= 120);
I have been trying variations of the following:
for i=element(1:end)
Matrix(i)= Matrix(blender(i-10:i+10));
end
then I want to plot one column of the matrix at the time when I hit Enter.
This second part I can figure out later, but I would appreciate some help making the Matrix
Thanks

First, you can use "logical indexing" of your array, which uses a logical expression do address your vector. With blender = [2, 302, 35, 199, 781, 312, 8], it could look like this:
>> b_hi = blender(blender>=120)
b_hi =
302 199 781 312
Second, you can concatenate arrays like in b_padded = [1, 2, b_hi, 3, 4]. If b_hi was a column vector, you'd use semicolons instead of commas.
Third, there is a function reshape that allows you to turn the resulting vector into a matrix. doc reshape will tell you details. For example, to turn b_padded into a 2-by-4 matrix,
>> b_matrix = reshape(b_padded, 4, 2)
b_matrix =
1 302 781 3
2 199 312 4
will do. This means you can do all of the job without any for-loop. Note that transposing the result of reshape(b_padded, 2, 4) will give you the other possible 2-by-4 matrix. You obtain the transpose of a matrix A by A'. You will find out which one you want.

You need to create a new matrix, and use two indices so that Matlab knows it is assigning to a column in a 2D matrix.
NewMatrix = zeros(21, length(element));
for i = 1:length(element)
k = element(i);
NewMatrix(:,i)= Matrix(blender(k-10:k+10));
end

Related

Large image matrix: save to small matrices

I'm new to MATLAB and its development. I have a image which is 1134 (rows) X 1134 (columns). I want that image to save 3 (columns) X 3 (rows). In order to do that I need 378 cells. For that I used following code, but it gives me an error.
image=imread('C:\Users\ven\Desktop\test\depth.png');
I=reshape(image,1,1134*1134);
chunk_size = [3 3]; % your desired size of the chunks image is broken into
sc = sz ./ chunk_size; % number of chunks in each dimension; must be integer
% split to chunk_size(1) by chunk_size(2) chunks
X = mat2cell(I, chunk_size(1) * ones(sc(1),1), chunk_size(2) *ones(sc(2),1));
Error:
Error using mat2cell (line 97)
Input arguments, D1 through D2, must sum to each dimension of the input matrix size, [1 1285956].'
Unfortunately your code does not work as you think it would.
The ./ operator performs point wise division of two matrices. Short example:
[12, 8] ./ [4, 2] == [12/4, 8/2] == [3, 4]
In order for it to work both matrices must have exactly the same size. In your case you try to perform such an operation on a 1134x1134 matrix (the image) and a 1x2 matrix (chunk_size).
In other words you can not use it to divide matrices into smaller ones.
However, a solution to your problem is to use the mat2cell function to pick out subsets of the matrix. A explanation of how it is done can be found here (including examples): http://se.mathworks.com/matlabcentral/answers/89757-how-to-divide-256x256-matrix-into-sixteen-16x16-blocks.
Hope it helps :)
Behind the C=A./B command is loop over all elements of A(ii,jj,...) and B(ii,jj,..) and each C(ii,jj,..)=A(ii,jj,...)/B(ii,jj,...).
Therefore martices A and B must be of same dimension.
If you want to split matrix into groups you can use
sc=cell(1134/3,1);
kk=0;ll=0;
for ii=2:3:1133
kk=kk+1;
for jj=2:3:1133
ll=ll+1;
sc{kk,ll}=image(ii-1:ii+1,jj-1:jj+1);
end
end
The code allocates cell array sc for resulting submatrices and arbitrary counters kk and ll. Then it loops over ii and jj with step of 3 representing centers of each submatrices.
Edit
Or you can use mat2cell command (type help mat2cell or doc mat2cell in matlab shell)
sc=mat2cell(image,3,3);
In both cases the result is cell array and its iith and jjth elements (matrices) are accessible by sc{ii,jj}. If you want call iith anr jjth number in kkth and llth matrix, do it via sc{kk,ll}(ii,jj).
In short, you divided a 1134 x 1134 by 2 x 1 matrix. That doesn't work.
The error "Matrix dimensions must agree**" is from the dividing a matrix with another matrix that doesn't have the right dimensions.
You used the scalar divide "./" which divided a matrix by another matrix.
You want something like:
n = 1134 / 3 % you should measure the length of the image
I1=image(1:n,1:n); % first row
I2=image(1:n,n:2n);
I3=image(1:n,2n:3n);
I4=image(n:2n,1:n); % second row
I5=image(n:2n,n:2n);
I6=image(n:2n,2n:3n);
I7=image(2n:3n,1:n); % third row
I8=image(2n:3n,n:2n);
I9=image(2n:3n,2n:3n);
from here:
http://au.mathworks.com/matlabcentral/answers/46699-how-to-segment-divide-an-image-into-4-equal-halves
There would be a nice loop you could do it in, but sometimes thinking is hard.

Print the value of a multidimensional array with the output as compatible matlab code

For matrices with dimensions equal or less then 2 the command is:
For instance:
>> mat2str(ones(2,2))
ans =
[1 1;1 1]
However, as the help states, this does not work for higher dimensions:
>> mat2str(rand(2,2,2))
Error using mat2str (line 49)
Input matrix must be 2-D.
How to output matrices with higher dimensions than 2 with that is code compatible, without resorting to custom made for loops?
This isn't directly possible because there is no built-in character to represent concatenation in the third dimension (an analog to the comma and semicolon in 2D). One potential workaround for this would be to perform mat2str on all "slices" in the third dimension and wrap them in a call to cat which, when executed, would concatenate all of the 2D matrices in the third dimension to recreate your input matrix.
M = reshape(1:8, [2 2 2]);
arrays = arrayfun(#(k)mat2str(M(:,:,k)), 1:size(M, 3), 'uni', 0);
result = ['cat(3', sprintf(', %s', arrays{:}), ')'];
result =
'cat(3, [1 3;2 4], [5 7;6 8])'
isequal(eval(result), M)
1
UPDATE
After thinking about this some more, a more elegant solution is to flatten the input matrix, run mat2str on that, and then in the string used to recreate the data, we utilize reshape combined with the original dimensions to provide a command which will recreate the data. This will work for any dimension of data.
result = sprintf('reshape(%s, %s);', mat2str(M(:)), mat2str(size(M)));
So for the following 4D input
M = randi([0 9], 1, 2, 3, 4);
result = sprintf('reshape(%s, %s);', mat2str(M(:)), mat2str(size(M)));
'reshape([6;9;4;6;5;2;6;1;7;2;1;7;2;1;6;2;2;8;3;1;1;3;8;5], [1 2 3 4]);'
Now if we reconstruct the data using this generated string, we can ensure that we get the correct data back.
Mnew = eval(result);
size(Mnew)
1 2 3 4
isequal(Mnew, M)
1
By specifying both the class and precision inputs to mat2str, we can even better approximate the input data including floating point numbers.
M = rand(1,2,3,4,5);
result = sprintf('reshape(%s, %s);', mat2str(M(:),64,'class'), mat2str(size(M)));
isequal(eval(result), M)
1

Matlab - Access elements form each column using a vector containing the rows [duplicate]

I'm writing a MATLAB function to read out data into an n-dimensional array (variable dimension size). I need to be able to access a specific point in the Matrix (to write to it or read it, for example), but I don't know ahead of time how many indexes to specify.
Currently I have a current_point vector which I iterate through to specify each index, and a max_points vector which specifies the size of the array. So, if for example I wanted a 3-dimensional array of size 1000-by-15-by-3, max_points = [1000 15 3], and current_point iterates from [1, 1, 1] to [1000, 15, 3] ([1, 1, 1] -> [1000, 1, 1] -> [1, 2, 1] -> [1000, 2, 1] ->...). What I'd like to be able to do is feed current_point as an index to the matrix like so:
output_matrix(current_point) = val
But apparently something like output_matrix([1 2 3]) = val will just set outputmatrix(1:3) = 30. I can't just use dummy variables because sometimes the matrix will need 3 indexes, other times 4, other times 2, etc, so a vector of variable length is really what I need here. Is there a simple way to use a vector as the points in an index?
Using the function sub2ind to create a linear index is the typical solution to this problem, as shown in this closely-related question. You could also compute a linear index yourself instead of calling sub2ind.
However, your case may be simpler than those in the other questions I linked to. If you're only ever indexing a single point with your current_point vector (i.e. it's just an n-element vector of subscripts into your n-dimensional matrix), then you can use a simple solution where you convert current_point to a cell array of subscripts using the function num2cell and use it to create a comma-separated list of indices. For example:
current_point = [1 2 3 ...]; % A 1-by-n array of subscripts
subCell = num2cell(current_point); % A 1-by-n cell array of subscripts
output_matrix(subCell{:}) = val; % Update the matrix point
The operation subCell{:} creates the equivalent of typing subCell{1}, subCell{2}, ..., which is the equivalent of typing current_point(1), current_point(2), ....
I know it is too late but for anybody who will find this topic. the easiest way that work for me is to use: diag(A (x(:),y(:)) );
unfortunately this works only if you need to get values from the matrix, not for changing values
You can use the sub2ind function to get the linear index from the subscript.
Example:
A=magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
selectElement={2,3}; %# get the element at position 2,3 in A.
indx=sub2ind(size(A),selectElement{:});
A(indx)
ans =
10
In the above example, I've stored the subscripts (can be any number of dimensions) as a cell. If you have it stored as a vector, simply use num2cell() to convert it to a cell.
You can now easily assign a value to this as A(indx)=value;. I've used different variables than yours to keep the answer general, but the idea is the same and you just need to replace the variable names.
You also mentioned in your post that you're looping from (1,1,1) till some value, (1000,15,3) and assigning a value to each of these points. If you're looping along the columns, you can replace this entire operation with a vectorized solution.
Let finalElement={1000,15,3} be the final step of the loop. As before, find the linear index as
index=sub2ind(size(A),finalElement{:});
Now if you have the values you assign in the loop stored as a single vector, values, you can simply assign it in a single step as
A(1:index)=values;

How to use reshape in Matlab?

I want to reshape pixel intensity by imagesize*1(column vector).
Imvect = reshape(I,imsize,1);
But why these error comes?
Error using reshape
To RESHAPE the number of elements must not change.
Let's start with the syntax used in the documentation:
B = reshape(A,sz1,...,szN)
What reshape does is to take the matrix A, straightens it out, and gives it a new size, that's determined by the 2nd, 3rd to the Nth argument. For this to be possible, you need to have the same number of elements in the input matrix as you have in the output matrix. You can't make a 1x5 vector turn into a 2x3 vector, as one element would be missing. The number of elements in the output matrix will be proportional to the product of sz1, sz2, ..., szN. Now, if you know you want N rows, but don't know exactly how many columns you have, you might use the [] syntax, that tells MATLAB to use as many columns as necessary to make the number of elements be equal.
So reshape(A, 2, [], 3) will become a 2xNx3 matrix, where, for a matrix with 24 elements, N will be 4.
Now, in your case this is not the case. numel(I) ~= imsize. If mod(numel(I), imsize) ~= 0 then your imsize is definitely incorrect. However, if mod(numel(I), imsize) == 0, then your error might be that you want imsize number of rows, and a number of columns that makes this possible. If it's the latter, then this should work:
Imvect = reshape(I,imsize, []);
If you simply want to make you matrix I a vector of size (numel(I), 1), then you should use the colon operator :, as such:
Imvect = I(:);
An alternative, if you really want to use reshape, is to specify that you want a single column, and let MATLAB select the number of rows, as such:
Imvect = reshape(I, [], 1);

Use a vector as an index to a matrix

I'm writing a MATLAB function to read out data into an n-dimensional array (variable dimension size). I need to be able to access a specific point in the Matrix (to write to it or read it, for example), but I don't know ahead of time how many indexes to specify.
Currently I have a current_point vector which I iterate through to specify each index, and a max_points vector which specifies the size of the array. So, if for example I wanted a 3-dimensional array of size 1000-by-15-by-3, max_points = [1000 15 3], and current_point iterates from [1, 1, 1] to [1000, 15, 3] ([1, 1, 1] -> [1000, 1, 1] -> [1, 2, 1] -> [1000, 2, 1] ->...). What I'd like to be able to do is feed current_point as an index to the matrix like so:
output_matrix(current_point) = val
But apparently something like output_matrix([1 2 3]) = val will just set outputmatrix(1:3) = 30. I can't just use dummy variables because sometimes the matrix will need 3 indexes, other times 4, other times 2, etc, so a vector of variable length is really what I need here. Is there a simple way to use a vector as the points in an index?
Using the function sub2ind to create a linear index is the typical solution to this problem, as shown in this closely-related question. You could also compute a linear index yourself instead of calling sub2ind.
However, your case may be simpler than those in the other questions I linked to. If you're only ever indexing a single point with your current_point vector (i.e. it's just an n-element vector of subscripts into your n-dimensional matrix), then you can use a simple solution where you convert current_point to a cell array of subscripts using the function num2cell and use it to create a comma-separated list of indices. For example:
current_point = [1 2 3 ...]; % A 1-by-n array of subscripts
subCell = num2cell(current_point); % A 1-by-n cell array of subscripts
output_matrix(subCell{:}) = val; % Update the matrix point
The operation subCell{:} creates the equivalent of typing subCell{1}, subCell{2}, ..., which is the equivalent of typing current_point(1), current_point(2), ....
I know it is too late but for anybody who will find this topic. the easiest way that work for me is to use: diag(A (x(:),y(:)) );
unfortunately this works only if you need to get values from the matrix, not for changing values
You can use the sub2ind function to get the linear index from the subscript.
Example:
A=magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
selectElement={2,3}; %# get the element at position 2,3 in A.
indx=sub2ind(size(A),selectElement{:});
A(indx)
ans =
10
In the above example, I've stored the subscripts (can be any number of dimensions) as a cell. If you have it stored as a vector, simply use num2cell() to convert it to a cell.
You can now easily assign a value to this as A(indx)=value;. I've used different variables than yours to keep the answer general, but the idea is the same and you just need to replace the variable names.
You also mentioned in your post that you're looping from (1,1,1) till some value, (1000,15,3) and assigning a value to each of these points. If you're looping along the columns, you can replace this entire operation with a vectorized solution.
Let finalElement={1000,15,3} be the final step of the loop. As before, find the linear index as
index=sub2ind(size(A),finalElement{:});
Now if you have the values you assign in the loop stored as a single vector, values, you can simply assign it in a single step as
A(1:index)=values;