I have divied an Image into number of subimages. Now I want to compare the average intensity of each subimage with its 8 neighbors. But in some points there would be less than 8 neighbors. For example for the first block(i=1,J=1), the upperleft block(i-1,j-1) does not exist. How can I check this and skip to the next valid one?
file='myimg.bmp';
I=imread(file);
blockSizeR = 128; % Rows in block.
blockSizeC = 128; % Columns in block.
wholeBlockRows = floor(rows / blockSizeR);
blockVectorR = [blockSizeR * ones(1, wholeBlockRows), rem(rows, blockSizeR)];
wholeBlockCols = floor(columns / blockSizeC);
blockVectorC = [blockSizeC * ones(1, wholeBlockCols), rem(columns, blockSizeC)];
ca = mat2cell(I, blockVectorR, blockVectorC);
%get the mean value of each cell
meanValues = cellfun(#(x) mean(x(:)),ca);
for j=1:size(ca(2))
for i=1:size(ca(1))
currentSlice = ca(i,j);
MeanOfCurrentSlice = cellfun(#(x) mean(x(:)),currentSlice);
%here I want to minus the 8 neighbors average grayscale intensity from the currentSlice average grayscale inensity and take the absolute sum
end
end
A solution that give you the index of the nearest neighbor for each element:
%creation of the index matrix (here a 3x3 matrix)
M = reshape([1:9],3,3);
%subdivide the matrix into 3x3 array
IND = nlfilter(M,[3 3],#(x){x(:)});
%elimination of the value where IND == 0 or IND == index value of the element
for ii = 1:size(M,1)
for jj = 1:size(M,2)
IND{ii,jj}(IND{ii,jj}==0|IND{ii,jj}==sub2ind(size(M),ii,jj)) = [];
end
end
PS: nlfilteris part of the image processing toolbox, but it's easy to create your own similar function.
STEP 1:
M =
1 4 7
2 5 8
3 6 9
STEP 2:
IND =
{
[1,1] =
0 0 0 0 1 2 0 4 5
[2,1] =
0 0 0 1 2 3 4 5 6
[3,1] =
0 0 0 2 3 0 5 6 0
[1,2] =
0 1 2 0 4 5 0 7 8
[2,2] =
1 2 3 4 5 6 7 8 9
[3,2] =
2 3 0 5 6 0 8 9 0
[1,3] =
0 4 5 0 7 8 0 0 0
[2,3] =
4 5 6 7 8 9 0 0 0
[3,3] =
5 6 0 8 9 0 0 0 0
}
STEP 3:
IND =
{
[1,1] = %neighbors of the value M[1,1]
2 4 5
[2,1] =
1 3 4 5 6
[3,1] =
2 5 6
[1,2] =
1 2 5 7 8
[2,2] =
1 2 3 4 6 7 8 9
[3,2] =
2 3 5 8 9
[1,3] =
4 5 8
[2,3] =
4 5 6 7 9
[3,3] =
5 6 8
}
Related
To find the output of the following formula in Matlab, I need to get all elements of a matrix (PDA in the following code) except its first element without using any loop.
Formula(Goal): % EVec = (A11-B11).^2 - (A12-B12).^2 - .. - (Aij-Bij).^2
Ex:
A(:,:,1) = [1 2 3 4; 4 5 6 1];
A(:,:,2) = [0 5 4 3; 2 7 6 0];
A(:,:,3) = [1 2 3 9; 0 6 7 0];
B(:,:,1) = [4 0 3 4; 4 8 0 1];
B(:,:,2) = [0 5 6 1; 0 9 4 3];
B(:,:,3) = [2 0 3 5; 8 6 7 2];
PDA = (A-B).^2;
EVec = PDA(1,1,:) - sum(PDA(?, ?, :)); % The problem is sum(PDA(?, ?,:)).
The result of PDA is:
PDA(:,:,1) =
9 4 0 0
0 9 36 0
% All of them except Val(1,1) = 9.
PDA(:,:,2) =
0 0 4 4
4 4 4 9
% All of them except Val(1,1) = 0.
PDA(:,:,3) =
1 4 0 16
64 0 0 4
% All of them except Val(1,1) = 1.
And my problem is in the output of PDA(1,1,:) - sum(PDA(?, ?, :)) that should be:9-(4+0+0+0+0+9+36+0), 0-(0+4+4+4+4+4+9), 1-(4+0+16+64+0+0+4) = [-40, -29, -87]..Unfortunately it doesn't.
How to get all elements of a matrix except its first element in Matlab?
The first element minus the sum of the remaining elements is just twice the first element minus the sum of all elements, so
>> squeeze(2*PDA(1,1,:) - sum(sum(PDA,1),2))
ans =
-40
-29
-87
Or in newer releases
>> squeeze(2*PDA(1,1,:) - sum(PDA,[1,2]))
ans =
-40
-29
-87
Could you please tell me why this MATLAB code is wrong? I don't understand why. Thank you so much in advance.
function [mst, cost] = prim(A)
[n,n] = size(A);
A, n, pause,
if norm(A-A','fro') ~= 0 ,
disp(' Error: Adjacency matrix must be symmetric ')
return,
end;
intree = [1]; number_in_tree = 1;
number_of_edges = 0;
notintree = [2:n]'; number_notin_tree= n-1;
in = intree(1:number_in_tree),
out = notintree(1:number_notin_tree),
pause,
while number_in_tree < n,
mincost = Inf;
for i=1:number_in_tree,
for j=1:number_notin_tree,
ii = intree(i); jj =
notintree(j);
if A(ii,jj) < mincost,
mincost = A(ii,jj); jsave = j;
iisave = ii; jjsave = jj;
end;
end;
end;
number_of_edges = number_of_edges +1;
mst(number_of_edges,1) = iisave;
mst(number_of_edges,2) = jjsave;
costs(number_of_edges,1) = mincost;
number_in_tree = number_in_tree + 1;
intree = [intree; jjsave];
for j=jsave+1:number_notin_tree,
notintree(j-1) = notintree(j);
end;
number_notin_tree = number_notin_tree - 1;
in = intree(1:number_in_tree),
out = notintree(1:number_notin_tree),
pause,
end;
disp(' Edges in minimum spanning tree and their costs: ')
[mst costs]
cost = sum(costs)
When I click the run button says:
Not enough input arguments.
Error in prim (line 10)
[n,n] = size(A);
% The matrix is n by n, where n = # nodes.
However when I call the function in the Command window with
s=[1 1 2 2 2 3 3 4 4 4 5 5 6 7];
t=[2 3 4 5 3 5 6 5 7 8 6 8 7 8];
w=[3 5 4 7 4 9 8 3 11 8 3 9 8 7];
G = graph(s,t,w);
A = adjacency(G);
prim(A)
The code works 'correctly'
As a final answer returns
mst =
cost=
All zero sparse: 1-by-1
It should have returned
mst=
1 2
2 3
2 4
4 5
5 6
6 7
7 8
costs=32
Why did not returned that?
Whilst running the program went from 1 to 4 though it should have gone to 2. Then from 4 to 5, that was correct but I don't know why skipped 2 and 3 and went directly to 4,5,6,7,8.
Help me please.
If there is an alternative code that you know please provide it, perhaps an easier one.
The main problem with your function is that when you check to see if the current edge has lower cost than mincost, you don't verify that there's actually an edge there. If there's no edge, then the cost will be 0, which is naturally lower than any positive cost value. You need to change the line:
if A(ii,jj) < mincost,
to
if (A(ii,jj) > 0) && (A(ii,jj) < mincost), % A(ii,jj) is edge and lower cost than mincost
Adjacency matrix used as input:
A =
0 3 5 0 0 0 0 0
3 0 4 4 7 0 0 0
5 4 0 0 9 8 0 0
0 4 0 0 3 0 11 8
0 7 9 3 0 3 0 9
0 0 8 0 3 0 8 0
0 0 0 11 0 8 0 7
0 0 0 8 9 0 7 0
The output after this change is:
mst =
1 2
2 3
2 4
4 5
5 6
4 8
8 7
cost = 32
I have 3 variables, x, y, z.
I want to plot line with 3 colors, red at h=0, green at h=1, blue at h=2.
x = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14];
y = [0 1 2 1 3 4 7 9 8 6 5 3 2 1 0];
h = [0 0 0 0 0 1 1 1 1 1 2 2 2 2 2];
color = [1 0 0 ; 0 1 0 ; 0 0 1];
Try this:
x = [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14];
y = [0 1 2 1 3 4 7 9 8 6 5 3 2 1 0];
h = [0 0 0 0 0 1 1 1 1 1 2 2 2 2 2];
color = [1 0 0 ; 0 1 0 ; 0 0 1];
greens = h<1;
reds = h>=1;
blues = h>=2;
greenLine = y;
redLine = y;
blueLine = y;
greenLine(~greens) = NaN;
redLine(~reds) = NaN
blueLine(~blues) = NaN
plot(x,greenLine,'g',x,redLine,'r',x,blueLine,'b');
I have a square symmetric matrix A of dimension n in Matlab and I want to reorder the elements in each row in ascending order but preserving the symmetry and without touching the diagonal elements.
E.g.
n=4;
A=[10 9 8 7; 9 6 5 4; 8 5 3 2; 7 4 2 1];
%reorder A in order to obtain
B=[10 7 8 9; 7 6 4 5; 8 4 3 2; 9 5 2 1];
Could you provide some help?
you can use triu to sort only the upper triangle and then add the transpose to keep the symmetry. finally just set the diagonal as in the original matrix:
n=4;
A=[10 9 8 7; 9 6 5 4; 8 5 3 2; 7 4 2 1];
% upper triangle indexes
UI = triu(true(size(A)),1);
% upper triangle of A
B = triu(A,1);
% assign inf to diagonal and below - important if there are any negative values in A
B(~UI) = -inf;
% sort rows descending order
B = sort(B,2,'ascend');
% set infs to 0
B(isinf(B)) = 0;
% add lower triangle matrix
B = B + B.';
% set diagonal as original A
B(1:n+1:n^2) = diag(A)
A = [10 9 8 7;
9 6 5 4;
8 5 3 2;
7 4 2 1];
B = sort(triu(A,1),2) + diag(diag(A)) + sort(triu(A,1),2)';
Explain
triu(A,1) gets the upper triangular matrix above the main diagonal, that is
ans0 =
0 9 8 7
0 0 5 4
0 0 0 2
0 0 0 0
sort(triu(A,1),2) sorts the elements in each row of the above result in an ascending order, that is
ans1 =
0 7 8 9
0 0 4 5
0 0 0 2
0 0 0 0
diag(diag(A)) gets the diagonal of A, that is
ans2 =
10 0 0 0
0 6 0 0
0 0 3 0
0 0 0 1
sort(triu(A,1),2)' gets the transpose of the sorted upper triangular matrix, that is
ans =
0 0 0 0
7 0 0 0
8 4 0 0
9 5 2 0
Add ans1, ans2 and ans3 up, you will get B.
I'm trying to figure out a matrix-oriented way to perform the ismember function by row in MATLAB. That is, if I have matrices
[1 2 3 4 5 6]
[7 8 9 10 11 12]
And I put in
[3 4 5]
[10 11 12]
Into some ismember-ish function, I'd like it to return
[0 0 1 1 1 0]
[0 0 0 1 1 1]
Other than looping over each row of the matrix in a for loop, is there a way to do this?
Assuming that your data are available as matrices A and B
A = [
1 2 3 4 5 6
7 8 9 10 11 12
];
B = [
3 4 5
10 11 12];
you can convert them to cells and then use cellfun
cellA = mat2cell(A, ones(1, size(A,1)), size(A,2));
cellB = mat2cell(B, ones(1, size(B,1)), size(B,2));
membership = cell2mat(cellfun(#ismember, cellA, cellB, 'UniformOutput', false));
This returns
membership =
0 0 1 1 1 0
0 0 0 1 1 1
A = [5 3 4 2]; B = [2 4 4 4 6 8];
[Lia1,Locb1] = ismember(A,B)
Lia1 =
1 1 1 1 0 0
Locb1 =
4 3 3 3 0 0