Creating an index matrix depending on Reference matrix and matrix of Data matlab - matlab

given matrix A of size 6 by 6 contain blocks of numbers,each block of size 2 by 2, and outher reference matrix R of size 2 by 12 also contain blocks of numbers, each block of size 2 by 2. the perpse of the whole process is to form a new matrix, called the Index matrix, contain index's that refer to the position of the blocks within the matrix A based on the order of the blocks within the reference matrix R. and here is an exemple
matrix A:
A =[1 1 2 2 3 3;
1 1 2 2 3 3;
1 1 3 3 4 4;
1 1 3 3 4 4;
4 4 5 5 6 6;
4 4 5 5 6 6 ]
matrix R:
R=[1 1 2 2 3 3 4 4 5 5 6 6;
1 1 2 2 3 3 4 4 5 5 6 6 ]
the new matrix is:
Index =[1 2 3;
1 3 4;
4 5 6]
any ideas ?

With my favourite three guys - bsxfun, permute, reshape for an efficient and generic solution -
blksz = 2; %// blocksize
num_rowblksA = size(A,1)/blksz; %// number of blocks along rows in A
%// Create blksz x blksz sized blocks for A and B
A1 = reshape(permute(reshape(A,blksz,num_rowblksA,[]),[1 3 2]),blksz^2,[])
R1 = reshape(R,blksz^2,1,[])
%// Find the matches with "bsxfun(#eq" and corresponding indices
[valid,idx] = max(all(bsxfun(#eq,A1,R1),1),[],3)
%// Or with PDIST2:
%// [valid,idx] = max(pdist2(A1.',reshape(R,blksz^2,[]).')==0,[],2)
idx(~valid) = 0
%// Reshape the indices to the shapes of blocked shapes in A
Index = reshape(idx,[],num_rowblksA).'
Sample run with more random inputs -
>> A
A =
2 1 1 2
1 2 2 1
1 1 1 1
2 2 2 2
1 2 2 1
1 2 1 1
>> R
R =
2 1 1 1 1 2 2 2 1 1 1 1
2 1 2 1 1 2 2 1 2 2 2 1
>> Index
Index =
0 0
5 5
3 0

Related

How do I create a symmetric matrix with a linearly decreasing diagonal in MatLab?

I'm trying to create a symmetric n by n matrix where the symmetry line is linearly decreasing from n to 1.
For example a 5 by 5 would be:
5 4 3 2 1
4 4 3 2 1
3 3 3 2 1
2 2 2 2 1
1 1 1 1 1
Thanks
Using implicit expansion, the min function will generate a square matrix from the combination of a row and a column vector, so the result can be gained by doing:
N = 5;
A = min( (N:-1:1).', (N:-1:1) );
You may use:
numRows = 5;
mI = repmat((1:numRows)', 1, numRows);
mJ = repmat((1:numRows), numRows, 1);
mA = flip(flip(min(mI, mJ), 1), 2)
With the answer given by:
mA =
5 4 3 2 1
4 4 3 2 1
3 3 3 2 1
2 2 2 2 1
1 1 1 1 1

Find the rows of a matrix with conditions concerning the values of certain columns in matlab

As the title says, I want to find all rows in a Matlab matrix that in certain columns the values in the row are equal with the values in the previous row, or in general, equal in some row in the matrix. For example I have a matrix
1 2 3 4
1 2 8 10
4 5 7 9
2 3 6 4
1 2 4 7
and I want to find the following rows:
1 2 3 4
1 2 3 10
1 2 4 7
How do I do something like that and how do I do it generally for all the possible pairs in columns 1 and 2, and have equal values in previous rows, that exist in the matrix?
Here's a start to see if we're headed in the right direction:
>> M = [1 2 3 4;
1 2 8 10;
4 5 7 9;
2 3 6 4;
1 2 4 7];
>> N = M; %// copy M into a new matrix so we can modify it
>> idx = ismember(N(:,1:2), N(1,1:2), 'rows')
idx =
1
1
0
0
1
>> N(idx, :)
ans =
1 2 3 4
1 2 8 10
1 2 4 7
Then you can remove those rows from the original matrix and repeat.
>> N = N(~idx,:)
N =
4 5 7 9
2 3 6 4
this will give you the results
data1 =[1 2 3 4
1 2 8 10
4 5 7 9
2 3 6 4
1 2 4 7];
data2 = [1 2 3 4
1 2 3 10
1 2 4 7];
[exists,position] = ismember(data1,data2, 'rows')
where the exists vector tells you wheter the row is on the other matrix and position gives you the position...
a less elegant and simpler version would be
array_data1 = reshape (data1',[],1);
array_data2 = reshape (data2',[],1);
matchmatrix = zeros(size(data2,1),size(data1,1));
for irow1 = 1: size(data2,1)
for irow2 = 1: size(data1,1)
matchmatrix(irow1,irow2) = min(data2(irow1,:) == data1(irow2,:))~= 0;
end
end
the matchmatrix is to read as a connectivity matrix where value of 1 indicates which row of data1 matches with which row of data2

identify the adjacent pixels in matlab

Let's assume A be,
1 1 1 1 1 1
1 2 2 3 3 3
4 4 2 2 3 3
4 4 2 2 2 3
4 4 4 4 3 3
5 5 5 5 5 5
I need to identify all the numbers which are adjacent to a particular intensity value. E.g. the intensities 1, 3, and 4 are adjacent to the intensity value 2.
What is the effective way to do it in Matlab?
I can use the following,
glcm = graycomatrix(A)
But if A have a larger number of intensity values e.g. 10000 graycomatrix will not be an efficient method.
You can build a mask with a 2D convolution, select the values according to that mask, and then reduce them to unique values:
% // Data:
A = [ 1 1 1 1 1 1
1 2 2 3 3 3
4 4 2 2 3 3
4 4 2 2 2 3
4 4 4 4 3 3
5 5 5 5 5 5 ];
value = 2;
adj = [0 1 0; 1 0 1; 0 1 0]; %// define adjacency. [1 1 1;1 0 1;1 1 1] to include diagonals
%// Let's go
mask = conv2(double(A==value), adj, 'same')>0; %// pixels adjacent to those equal to `value`
result = unique(A(mask));
In the example, this produces
result =
1
2
3
4
Note that the result includes 2 because some pixels with value 2 have adjacent pixels with that value.

Dividing a vector to form different matrices

I have a two long vector. Vector one contains values of 0,1,2,3,4's, 0 represent no action, 1 represent action 1 and 2 represent the second action and so on. Each action is 720 sample point which means that you could find 720 consecutive twos then 720 consecutive 4s for example. Vector two contains raw data corresponding to each action. I need to create a matrix for each action ( 1, 2, 3 and 4) which contains the corresponding data of the second vector. For example matrix 1 should has all the data (vector 2 data) which occurred at the same indices of action 1. Any Help??
Example on small amount of data:
Vector 1: 0 0 1 1 1 0 0 2 2 2 0 0 1 1 1 0 0 2 2 2
Vector 2: 6 7 5 6 4 6 5 9 8 7 9 7 0 5 6 4 1 5 8 0
Result:
Matrix 1:
5 6 4
0 5 6
Matrix 2:
9 8 7
5 8 0
Here is one approach. I used a cell array to store the output matrices, hard-coding names for such variables isn't a good plan.
V1=[0 0 1 1 1 0 0 2 2 2 0 0 1 1 1 0 0 2 2 2]
V2=[6 7 5 6 4 6 5 9 8 7 9 7 0 5 6 4 1 5 8 0]
%// Find length of sequences of 1's/2's
len=find(diff(V1(find(diff(V1)~=0,1)+1:end))~=0,1)
I=unique(V1(V1>0)); %// This just finds how many matrices to make, 1 and 2 in this case
C=bsxfun(#eq,V1,I.'); %// The i-th row of C contains 1's where there are i's in V1
%// Now pick out the elements of V2 based on C, and store them in cell arrays
Matrix=arrayfun(#(m) reshape(V2(C(m,:)),len,[]).',I,'uni',0);
%// Note, the reshape converts from a vector to a matrix
%// Display results
Matrix{1}
Matrix{2}
Since, there is a regular pattern in the lengths of groups within Vector 1, that could be exploited to vectorize many things while proposing a solution. Here's one such implementation -
%// Form new vectors out of input vectors for non-zero elements in vec1
vec1n = vec1(vec1~=0)
vec2n = vec2(vec1~=0)
%// Find positions of group shifts and length of groups
df1 = diff(vec1n)~=0
grp_change = [true df1]
grplen = find(df1,1)
%// Reshape vec2n, so that we end up with N x grplen sized array
vec2nr = reshape(vec2n,grplen,[]).' %//'
%// ID/tag each group change based on their unique vector 2 values
[R,C] = sort(vec1n(grp_change))
%// Re-arrange rows of reshaped vector2, s.t. same ID rows are grouped succesively
vec2nrs = vec2nr(C,:)
%// Find extents of each group & use those extents to have final cell array output
grp_extent = diff(find([1 diff(R) 1]))
out = mat2cell(vec2nrs,grp_extent,grplen)
Sample run for the given inputs -
>> vec1
vec1 =
0 0 1 1 1 0 0 2 2 2 ...
0 0 1 1 1 0 0 2 2 2
>> vec2
vec2 =
6 7 5 6 4 6 5 9 8 7 ...
9 7 0 5 6 4 1 5 8 0
>> celldisp(out)
out{1} =
5 6 4
0 5 6
out{2} =
9 8 7
5 8 0
Here is another solution:
v1 = [0 0 1 1 1 0 0 2 2 2 0 0 1 1 1 0 0 2 2 2];
v2 = [6 7 5 6 4 6 5 9 8 7 9 7 0 5 6 4 1 5 8 0];
m1 = reshape(v2(v1 == 1), 3, [])'
m2 = reshape(v2(v1 == 2), 3, [])'
EDIT: David's solution is more flexible and probably more efficient.

MATLAB Matrix Transformation

I need to transform a matrix:
X = [1 2; 3 4]
X = 1 2
3 4
to
X = [1 2; 1 2; 1 2; 3 4; 3 4; 3 4]
X = 1 2
1 2
1 2
3 4
3 4
3 4
and do this operation for a matrix with any number of rows.
How can I achieve this in MATLAB?
Here is a nice and easy way to do this using kron
kron(X,[1 1 1]')
this produces
1 2
1 2
1 2
3 4
3 4
3 4