identify the adjacent pixels in matlab - 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.

Related

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.

Creating an index matrix depending on Reference matrix and matrix of Data 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

Unique combinations of a beaded necklace [duplicate]

This question already has answers here:
Generate all possible combinations of the elements of some vectors (Cartesian product)
(4 answers)
Closed 8 years ago.
So I'm writing a program to determine the unique combinations of a beaded necklace, but I can't seem to get it right. The rules are you can't have the same necklace forwards and backwards, and you can't have the same necklace with one bead being slid around to the other end. I've attached some pictures to clarify.
I wrote the code for it, and I thought I had achieved what I was trying to do, but it's not working correctly.
n = [1 2 3 4 2 4];
% green = 1
% blue = 2
% yellow = 3
% red = 4
p = perms(n);
total = max(size(p));
for i = 1:max(size(p))
q = p;
q(i) = [];
for j = 1:max(size(q))
if isequal(p(i),fliplr(q(j)))
total = total - 1;
elseif isequal(p(i),circshift(q(j),[1,1]))
total = total - 1;
elseif isequal(p(i),circshift(q(j),[length(q(j))-1,length(q(j))-1]))
total = total - 1;
end
disp(total)
end
end
Logically, this makes sense to me, but I could just be crazy.
If the problem size is small, you can vectorize all the comparisons (using bsxfun):
n = [1 2 3 4 2 4];
%// green = 1
%// blue = 2
%// yellow = 3
%// red = 4
N = numel(n);
p = perms(n).'; %'// generate all permutations
p2 = NaN([size(p) N+1]); %// this will store permutations with flips and shifts
p2(:,:,1) = p; %// original
p2(:,:,2) = flipud(p); %// flips
for k = 1:N-1
p2(:,:,2+k) = circshift(p,k); %// circular shifts
end
eqElem = bsxfun(#eq, p, permute(p2, [1 4 2 3]));
eqMat = squeeze(any(all(eqElem, 1), 4)); %// 1 if equal
remove = any(tril(eqMat, -1), 1); %// remove permutations that are "similar"
%// to a previous one, where "similar" means "equal up to circular shifts or
%// flips"
result = p(:,~remove).'; %'// all valid arrangements; one per row
resultNum = size(result, 1); %// number of arrangements
Results:
result =
1 3 2 2 4 4
1 3 2 4 4 2
1 3 2 4 2 4
1 3 4 2 2 4
1 3 4 2 4 2
1 3 4 4 2 2
1 2 3 2 4 4
1 2 3 4 2 4
1 2 3 4 4 2
1 2 2 3 4 4
1 2 2 4 4 3
1 2 2 4 3 4
1 2 4 3 2 4
1 2 4 3 4 2
1 2 4 2 3 4
1 2 4 2 4 3
1 2 4 4 2 3
1 2 4 4 3 2
1 4 4 3 2 2
1 4 4 2 2 3
1 4 4 2 3 2
1 4 3 4 2 2
1 4 3 2 2 4
1 4 3 2 4 2
1 4 2 3 2 4
1 4 2 3 4 2
1 4 2 2 3 4
1 4 2 2 4 3
1 4 2 4 2 3
1 4 2 4 3 2
resultNum =
30
You should do p = unique(p,'rows') before any loops. To see why, call perms([1 1 1]) at the command line.
There are a few issues here:
1) p, the perms, is a 2D matrix, so to get each perm you need to do p(i,:) to get the row. p(i) is just a single number.
2) You don't remove wrong answers from your list, so you will check against them twice. For example, say the first in the list is [1 2 3 4 2 4]; and the second is [4 2 4 3 2 1];. The fliplr check will compare these two combinations twice, once in the first loop around, once in the second.
3) If you want to make sure that any permutation which is a rotation is excluded (not just moving one bead around), you'll need some more circshift.
Consider using ismember with rows option again to compare a single row (e.g. a flipped version of the row you're checking) to an entire matrix.

How to represent given adjacency matrix as undirected weighted graph in matlab?

For below given matrix,how it can be represented as undirected weighted graph G(V,E,W) where V is set of vertices,E is set of edges and W is set of weights.
4 2 3 1 4
2 2 3 1 4
2 3 3 1 4
1 2 3 1 4
4 2 3 1 5
Source code i tried:
%table2 is given matrix
bg = biograph(table2,[],'ShowArrows','off','ShowWeights','on');
h = view(bg);
Is this the right way to represent undirected weighted graph for my matrix?Iam getting 2 edges between same 2 verteces.Just like this
I got this output for your suggested code
Iam having 2 adjacency matrices.I have to perform below 2 operations:
1.I have to make 2 graphs from these 2 adjacency matrices.
2.Then i have to match vertices of 2 graphs depending on weights of edges in graph.
4 2 3 1 4
2 2 3 1 4
2 3 3 1 4
1 2 3 1 4
4 2 3 1 5
4 1 3 2 4
1 1 2 3 4
3 1 3 2 4
2 1 3 2 4
4 1 3 2 5
The way iam going is right or wrong?Please suggest me
To get only one edge between each vertex, you only want a triangular matrix.
If you try something like this:
table1 = (table2 + table2') - triu((table2 + table2'))
table1 =
0 0 0 0 0
4 0 0 0 0
5 6 0 0 0
2 3 4 0 0
8 6 7 5 0
bg = biograph(table1,[],'ShowArrows','off','ShowWeights','on');
h = view(bg);
Now I have assumed you want to sum up the weights from both edges. I.e. the weight of the edge between 1-2 equal the weight of the edge from 1->2 + 2->1, from your original matrix.

how to remove rows with same information but different representation?

given
A=1 1 0
1 2 0.563826213141399
1 3 1.18321595677734
1 4 1.95685972913029
2 1 0.563826213141399
2 2 0
2 3 0.830602192143995
2 4 1.65196852337589
2 5 1.77172232586001
3 1 1.18321595677734
3 2 0.830602192143995
3 3 0
3 4 0.821522975656861
3 5 1.12716458303105
3 6 1.78117938413852
as seen row 2 and 5 are same in real but not in the matrix. how can I remove one of the same rows?
using unique I couldn't do this.
It seems like you have a representation of a graph using a weighted adjacency matrix.
If I understand correctly, you wish to have a single entry per edge.
You can do this by taking only the upper triangle of the adjacency matrix
A = sparse( A(:,1), A(:,2), A(:,3), max(A(:,2)), max(A(:,2)) );
[ii jj wij] = find( triu( A ) ) ;
disp( [ii jj wij] )
outputs:
1 2 0.563826
1 3 1.183216
2 3 0.830602
1 4 1.956860
2 4 1.651969
3 4 0.821523
2 5 1.771722
3 5 1.127165
3 6 1.781179