How to create more than one matrix in a row using matlab - matlab

I am trying to get a series of vectors which come from the same original, to make an easy example, suppose this vector V= (1,2,3,4,5,6,7,8,9,10) (of course mine is bigger)
The first vector has to look like this:
R1=(1,3,5,7,9)= V(1:1:end)
The second vector:
R2=(2,4,6,8,10)=V(2:1:end)
The third vector:
R3=(3,5,7,9)=V(3:1:end)
The fourth vector:
R4=(4,6,8,10)=V(4:1:end)
...
R8=(8,10)=V(8:1:end)
So my questions are:
Is there an easier way to get this result?
How can I know the total number of Ri vectors with distance = 1 that can obtained from V?

Use Matlab's cell object which can hold a vector in every cell.
Use a for loop to fill this cell object gradually.
Code example:
%initialize V
V= [1,2,3,4,5,6,7,8,9,10];
%initialize an empty cell of size [10,1]
R= cell(length(V)-2,1);
%fill the cell
for ii=1:length(R)
R{ii} = V(ii:2:end);
end
%prints results
for ii=1:length(R)
R{ii}
end
Results (each row is a different vector):
1 3 5 7 9
2 4 6 8 10
3 5 7 9
4 6 8 10
5 7 9
6 8 10
7 9
8 10

Related

Directly create sparse adjacency matrix - (matrix exceeds maxium array size preference)

Problem
I am using an adjacency matrix in my algorithm, which worked fine as long as I tested it an small matrixes (3000) points. But my actual problem includes 167620 points and I would like to create an adjacency matrix for that problem.
But obviously due to the length I get the following problem:
Requested 167620x167620 (209.3GB) array exceeds maximum array size preference. Creation of arrays greater than this limit may take a
long time and cause MATLAB to become unresponsive.
I use the following code:
adjMat = zeros(size(NB_list_all,1));
for ind = 1:size(NB_list_all,1)
adjMat(ind, nonzeros(NB_list_all(ind,2:end))) = 1;
end
adjMatS=sparse(adjMat);
G=digraph(adjMatS);
E=table2array(G.Edges);
As you can see I basically need the Edge-list.
Question
Hence the question: Is there a way to directly compute a sparse adjacency matrix or is there a different way of getting the Edge list from an adjacency list ?
My NB_list_all contains the points in column 1 and neighbours in column 2-5?
EDIT
My NB_list_all is an adajency list of the following form:
1 2 0
2 3 1
3 4 2
4 5 3
5 6 4
6 7 5
7 8 6
8 9 7
9 0 8
Column one the point indize and columns 2:5 the indizes of the points it is adjacent to. 0 if there is no neighbour. The matrix I want to create an Edge list for is 167620x5. I created the edge list before using the E=table2array(G.Edges); graph function of matlab. Now I basically have two questions:
How would i create a sparse adjacency matrix from this adjacency list directly?
Is there an easier way of creating an edge list for this kind of adjacency list ?
Thanks a lot!
If you know all the indexes and values, and the end size of the matrix, a sparse matrix can be created with
adjMat = sparse(indexi,indexj,value,size1,size2);
in a single go. Actually, this is the preffered way of creating a sparse matrix.
Example:
You want the following matrix:
0 1 1
1 0 0
0 0 1
you would build it as:
sparse([1 1 2 3], [2 3 1 3],[1 1 1 1],3,3)
with the example you gave:
NB_list_all=[
1 2 0
2 3 1
3 4 2
4 5 3
5 6 4
6 7 5
7 8 6
8 9 7
9 0 8];
% if the first index contains all numbers we can safely do this
% this is almost indexJ, but we have some zeroes that we dont like
indexJ=NB_list_all(:,2:end);
% create indexI
indexI=repmat(1:size(indexJ,1),size(indexJ,2),1).';
% lets unroll the matrices
indexI=indexI(:);
indexJ=indexJ(:);
% lets remove the indexI and NB_list_all that have a zero somewhere, because those are not real
notzero=find(indexJ);
indexI=indexI(notzero);
indexJ=indexJ(notzero);
adjMat=sparse(indexI,indexJ,1,size(NB_list_all,1),size(NB_list_all,1));

Group matrix values into separate matrices based on values of another matrix

I am reading in images with imread which results in 768x1024x3 matrix with R,G,B values of each pixel.
I have a function that takes in an image and returns matrix of segment labels for each pixel so this matrix is 768x1024. the labels are just numbers 1,2,3,4 depending on how many different segments the function finds.
Now I want to calculate the average Red, Green and Blue value in each segment of the image. So I want to use the indices from the segment label matrix to find group all R,G,B values into separate arrays and then be able to calculate the mean.
Is there any smart way to do this? use the indices of each 1 value in the segment matrix to get the values from the imread matrix and group the segments into different arrays? I though of using for loops and brute force through this but is there a better way to do this?
Here's a code that you will get you everything without looping.
Code
%// img is your input RGB image (NxMx3)
%// L is your label matrix (NxM)
t1 = bsxfun(#eq,L,permute(unique(L),[3 2 1]));
t2 = bsxfun(#times,permute(img,[ 1 2 4 3]),t1);
t2(t2==0)=nan;
out = squeeze(nanmean(nanmean(t2)))
%// out is the desired output matrix that is (NLx3),
%// where NL is the number of labels. Thus, the mean of labels is
%// along the rows and the corresponding values for R, G and B are in the three
%// columns of it.
Explanation
Let's test out with some random values for img -
img = randi(9,3,4,3)
Giving us -
img(:,:,1) =
9 7 5 3
7 7 2 4
1 6 7 9
img(:,:,2) =
8 6 6 4
4 9 3 9
3 9 8 1
img(:,:,3) =
5 4 4 5
7 2 5 3
2 3 1 3
Some assumed values for L that goes from 1 to 8
L = [1 3 3 4;
4 5 8 8;
5 6 7 2]
The code output is -
out =
9 8 5
9 1 3
6 6 4
5 4 6
4 6 2
6 9 3
7 8 1
3 6 4
Let's see how to make sense of the output.
Looking at the input, let's choose the label 8, which is at locations (2nd row,3rd col) and (2nd row,4th col). The corresponding R values at these locations in img are [2 4], and thus the R mean/average value must be 3. Similarly for G it must be from [3 9], that is 6 and again for B would be from [5 3], that is 4.
Let's look at the 8th row of out that represents the label-8, we have [3 6 4], which are the mean values as calculated earlier. Similarly other mean values could be interpreted from out.
Edited to handle all channels at once.
Let img be your RGB image and labels the labels array.
You can mask the RGB image with the labels like this:
% create a 3-channels mask:
labelsRGB=repmat(labels, 1, 1, 3);
Segment1=img.*(labelsRGB==1);
The average values in the segment labeled as 1 is then:
avg=mean(mean(Segment1, 1), 2);
Get the average for re in avg(1), the average for green in avg(2), etc.
Idem for the other segments.
Here goes a general alternative.
In this case you do not need to loop over the different segments to get the average of each.
%simulated image and label
img=rand(10,12,3);
labeled=[ones(10,3),ones(10,3)*2,ones(10,3)*3,ones(10,3)*4];
% actual code for the mean
red_mean = regionprops(labeled, img(:,:,1), 'MeanIntensity')

matlab. copy values from one matrix based on values of another matrix

I have matrix a <500 x 500> and matrix b <500 x 2>.
Matrix b contains two types of values which are row and column coordinates for matrix a. I would like to use the values in matrix b to to copy all the values that fall on the row and column coordinates of matrix a.
see example below
matrix a matrix b output
1 2 3 4 5 1 5 1 2 3 4 5
6 7 8 9 10 2 5 7 8 9 10
11 12 13 14 15 1 3 11 12 13
Because every row will have a different length you'll need to save the values into a cell array.
Something like this should work:
output = cell( size(b,1),1);
for i = 1:size(a,1)
output{i} = a(i, b(i,1):b(i,2) )
end

How to convert 1D to 2D by Matlab program

I would like to ask a question about Matlab program.
I have vector a
a = [1 2 3 4 5 6 7 8 9 10 11 12];
I would like to convert vector a to 2D array. Normally, I use this code to convert it.
m =1;
for i=1:4
for j=1:3
b(i,j) = a(m);
m=m+1;
end
end
Then b is a 2D matrix.
b =
1 2 3
4 5 6
7 8 9
10 11 12
Anybody, have an idea to convert 1D to 2D without using loop.
Thanks,
Check out the reshape function and help page.
In particular,
B = reshape(A,m,n)
returns the m-by-n matrix B whose elements are taken column-wise from A. An error results if A does not have m*n elements.
Note that it is column-wise, so I suggest you make a matrix with 3 rows and 4 columns and then tip it on its side (A.' will take the transpose of a matrix).

Reconstruct matrix from diagonals in matlab

Given a vector of the counter-diagonals of a matrix in matlab, is there an easy way to reconstruct the matrix?
For example, given
x = [1 2 3 4 5 6 7 8 9]
is there any easy way to reconstruct it to the following?
1 2 4
3 5 7
6 8 9
This is made slightly easier by the fact that the dimensions of the original block are known. Reconstructing a rotation or transposition of the original matrix is fine, since rotating and transposing are easy to undo. Faster is better, this calculation has to be done on many xs.
Thanks!
You can create the corresponding Hankel matrix and use it for sorting (works only if the output is a square matrix!):
x = [1 2 3 4 5 6 7 8 9];
%# find size of output (works only with square arrays)
n=sqrt(length(x));
%# create Hankel matrix
hh = hankel(1:n,n:(2*n-1));
%# sort to get order of elements (conveniently, sort doesn't disturb ties)
[~,sortIdx]=sort(hh(:));
%# reshape and transpose
out = reshape(x(sortIdx),n,n)'; %'# SO formatting
out =
1 2 4
3 5 7
6 8 9