Saving different 'graycoprops' properties values on a matrix [MATLAB] - matlab

I've a picture. I create the co-occurrence matrix (graycomatrix) to extract different properties (contrast, correlation) etc on it (graycoprops)
x = []
for a lot of pictures, do the same:
imgB = imread('currentLoopImage.jpg')
contrast = graycoprops(graycomatrix(rgb2gray(imgB)), 'Contrast')
correlation = graycoprops(graycomatrix(rgb2gray(imgB)), 'Correlation')
energy = graycoprops(graycomatrix(rgb2gray(imgB)), 'Energy')
homogeneity = graycoprops(graycomatrix(rgb2gray(imgB)), 'Homogeneity')
x = [x;contrast;correlation;energy;homogeneity]
The thing is that I need to save all the values on that matrix X, but I get the following error:
CAT arguments are not consistent in structure field names.
As this is the output I get from each type:
homogeneity =
Homogeneity: 0.8587
There are different types, so I can't save them on the X matrix.
The output matrix X, should save only the numbers, and ignore that "Homogenity"
Can someone tell me who can I do this?

From the graycoprops() example:
>> GLCM = [0 1 2 3;1 1 2 3;1 0 2 0;0 0 0 3];
>> stats = graycoprops(GLCM)
stats =
Contrast: 2.8947
Correlation: 0.0783
Energy: 0.1191
Homogeneity: 0.5658
Then just do:
>> x = struct2array(stats)
ans =
2.8947 0.0783 0.1191 0.5658
Also note that you can include all your images in an m x n x p matrix and process them all at once, instead of using the for loop. For example:
>> GLCM(:,:,2) = GLCM;
>> cell2mat(struct2cell(stats))
ans =
2.8947 2.8947
0.0783 0.0783
0.1191 0.1191
0.5658 0.5658

Related

How to get a 3D-matrix or cell array efficiently by using vectorized code?

Here is what I want, a 3-D matrix:
K = 2:2.5:10;
den = zeros(1,4,4);
for i = 1:1:4
den(:,:,i) = [1, 5, K(i)-6, K(i)];
end
Or, a cell array is also acceptable:
K = 2:2.5:10;
for i = 1:1:4
den{i} = [1, 5, K(i)-6, K(i)];
end
But I want to know if there is a more efficient way of doing this using vectorized code like:
K = 2:2.5:10;
den = [1, 5, K-6, K];
I know the last code will not get what I wanted. But, like I can use:
v = [1 2 3];
v2 = v.^2;
instead of:
v = [1 2 3];
for i = 1:length(v)
v(i) = v(i)^2;
end
to get the matrix I want. Is there a similar way of doing this so that I can get the 3-D matrix or cell array I mentioned at the beginning more efficiently?
You need to "broadcast" the scalar values in columns so they are of the same length as your K vector. MATLAB does not do this broadcasting automatically, so you need to repeat the scalars and create vectors of the appropriate size. You can use repmat() for this.
K = 2:2.5:10;
%% // transpose K to a column vector:
K = transpose(K);
%% // helper function that calls repmat:
f = #(v) repmat(v, length(K), 1);
%% // your matrix:
den = [f(1) f(5) K-6 K];
This should be more optimized for speed but requires a bit more intermediary memory than the loop does.
Just use reshape with a 1*3 size:
den = reshape([ones(1,length(K));ones(1,length(K))*5; K-6; K],[1 4 length(K)]);
I think the used extra memory by reshape should be low and constant (dependent only on the length of the vector of new sizes).
You can use the classic line equation y=a*x+b, extended to the matrix form:
k = 2:2.5:10 ;
fa = [0 0 1 1].' ; %' // "a" coefficients
fb = [1 5 -6 0].' ; %' // "b" coefficients
d(1,:,:) = fa*k + fb*ones(1,4) ;
The above is better for clarity, but if you're not bothered you can also pack everything in one line:
d(1,:,:) = [0 0 1 1].' * (2:2.5:10) + [1 5 -6 0].' * ones(1,4) ;
If you need to re-use the principle for many different values of k, then you can use an anonymous function to help:
fden = #(k) [0 0 1 1].' * k + [1 5 -6 0].' * ones(1,4) ; %// define anonymous function
k = 2:2.5:10 ;
d(1,:,:) = fden(k) ; %// use it for any value of "k"

Which one should I use for dimension reduction with PCA in MATLAB, pcacov or eigs?

I'm trying to reduce my training set dimension from 1296*70000 to 128*70000.
I wrote Below code:
A=DicH;
[M N]=size(A);
mu=mean(A,2);%mean of columns
Phi=zeros(M,N);
C=zeros(M,M);
for j=1:N
Phi(:,j)=A(:,j)-mu;
c=Phi(:,j)*(Phi(:,j))';
C=C+c;
end
C=C/N;%Covariance Dictionary
[V,landa] = eigs(C,128);%Eigen Vectors & Eigen Values
E=V'*Phi;%Reduced Dic
%*******************Using Pcacov*****************
%S=zeros(M,1);
%[U,landa] = pcacov(C);%Eigen Vectors & Eigen Values
% for k=1:128;
% S=V(:,k)+S;
% U(:,k)=S;
% end
%E=U'*Phi;%Reduced Dic
I get two different answers! Which one should I use "eigs" or "pcacov"??
You should take advantage of the built-in functions in Matlab, and use the pca function directly, or even the cov function if you want to compare eigs to pcaconv.
Now to answer your question, both return the same eigenvectors but not in the same order. See the following example:
>> load hald
>> covx = cov(ingredients);
>> [COEFF,latent] = pcacov(covx)
COEFF =
-0.0678 -0.6460 0.5673 0.5062
-0.6785 -0.0200 -0.5440 0.4933
0.0290 0.7553 0.4036 0.5156
0.7309 -0.1085 -0.4684 0.4844
latent =
517.7969
67.4964
12.4054
0.2372
>> [V, D] = eigs(covx)
V =
0.5062 0.5673 0.6460 -0.0678
0.4933 -0.5440 0.0200 -0.6785
0.5156 0.4036 -0.7553 0.0290
0.4844 -0.4684 0.1085 0.7309
D =
0.2372 0 0 0
0 12.4054 0 0
0 0 67.4964 0
0 0 0 517.7969
>>
In your code, you overwrite the result of pcavconv in the commented-out section with a transformation of the result of eigs so it is not clear what your are comparing at this point. When using pcacov, you just need to extract the 128 first columns of U.

Matlab convert columnar data into ndarray

Is there a simple (ideally without multiple for loops) way to group a vector of values according to a set of categories in Matlab?
I have data matrix in the form
CATEG_A CATEG_B CATEG_C ... VALUE
1 1 1 ... 0.64
1 2 1 ... 0.86
1 1 1 ... 0.74
1 1 2 ... 0.56
...
etc.
and what I want is an N-dimensional array
all_VALUE( CATEG_A, CATEG_B, CATEG_C, ..., index ) = VALUE_i
of course there may be any number of values with the same category combination, so size(end) would be the number of value in the biggest category -- and the remaining items would be padded with nan.
Alternatively I'd be happy with
all_VALUE { CATEG_A, CATEG_B, CATEG_C, ... } ( index )
i.e. a cell array of vectors. I suppose it's a bit like creating a pivot table, but with n-dimensions, and not computing the mean.
I found this function in the help
A = accumarray(subs,val,[],#(x) {x})
but I couldn't fathom how to make it do what I wanted!
This is also a mess, but works. It goes the ND-array way.
X = [1 1 1 0.64
1 2 1 0.86
1 1 1 0.74
1 1 2 0.56]; %// data
N = size(X,1); %// number of values
[~, ~, label] = unique(X(:,1:end-1),'rows'); %// unique labels for indices
cumLabel = cumsum(sparse(1:N, label, 1),1); %// used for generating a cumulative count
%// for each label. The trick here is to separate each label in a different column
lastInd = full(cumLabel((1:N).'+(label-1)*N)); %'// pick appropriate values from
%// cumLabel to generate the cumulative count, which will be used as last index
%// for the result array
sizeY = [max(X(:,1:end-1),[],1) max(lastInd)]; %// size of result
Y = NaN(sizeY); %// initiallize result with NaNs
ind = mat2cell([X(:,1:end-1) lastInd], ones(1,N)); %// needed for comma-separated list
Y(sub2ind(sizeY, ind{:})) = X(:,end); %// linear indexing of values into Y
The result in your example is the following 4D array:
>> Y
Y(:,:,1,1) =
0.6400 0.8600
Y(:,:,2,1) =
0.5600 NaN
Y(:,:,1,2) =
0.7400 NaN
Y(:,:,2,2) =
NaN NaN
It's a mess but here is one solution
[U,~,subs] = unique(X(:,1:end-1),'rows');
sz = max(U);
Uc = mat2cell(U, size(U,1), ones(1,size(U,2)));
%// Uc is converted to cell matrices so that we can take advantage of the {:} notation which returns a comma-separated-list which allows us to pass a dynamic number of arguments to functions like sub2ind
I = sub2ind(sz, Uc{:});
G = accumarray(subs, X(:,end),[],#(x){x});
A{prod(max(U))} = []; %// Pre-assign the correct number of cells to A so we can reshape later
A(I) = G;
reshape(A, sz)
On your example data (ignoring the ...s) this returns:
A(:,:,1) =
[2x1 double] [0.8600]
A(:,:,2) =
[0.5600] []
where A(1,1,1) is [0.74; 0.64]

Quantiles in Matlab

Would there be a function in matlab, or an easy way, to generate the quantile groups to which each data point belongs to?
Example:
x = [4 0.5 3 5 1.2];
q = quantile(x, 3);
ans =
1.0250 3.0000 4.2500
So I would like to see the following:
result = [2 1 2 3 1]; % The quantile groups
In other words, I am looking for the equivalent of this thread in matlab
Thanks!
You can go through all n quantiles in a loop and use logical indexing to find the quantile
n = 3;
q = quantile(x,n);
y = ones(size(x));
for k=2:n
y(x>=q(k)) = k;
end
Depending on how you define "quantile group", you could use:
If "quantile group" means how many values in q are less than x:
result = sum(bsxfun(#gt, x(:).', q(:)));
If "quantile group" means how many values in q are less than or equal to x:
result = sum(bsxfun(#ge, x(:).', q(:)));
If "quantile group" means index of the value in q which is closest to each value in x:
[~, result] = min(abs(bsxfun(#minus, x(:).', q(:))));
None of these returns the result given in your example, though: the first gives [2 0 1 3 1], the second [2 0 2 3 1], the third [3 1 2 3 1].

Obtain matrix of indices in octave / matlab

Given some multidimensional matrix A in Octave / Matlab,
What's the easiest way to get a matrix of the same size as A where all elements are replaced by their index along the k'th dimension
ie for the matrix
A =
ans(:,:,1) =
0.095287 0.191905
0.226278 0.749100
ans(:,:,2) =
0.076826 0.131639
0.862747 0.699016
I want a function f such that
f(A,1) =
ans(:,:,1) =
1 1
2 2
ans(:,:,2) =
1 1
2 2
f(A,2) =
ans(:,:,1) =
1 2
1 2
ans(:,:,2) =
1 2
1 2
and
f(A, 3) =
ans(:,:,1) =
1 1
1 1
ans(:,:,2) =
2 2
2 2
Also, given a sparse matrix B
What's the easiest way to get another sparse matrix of the same size where the nonzero elements are replaced by their index along the k'th dimension? (so same problem as above, but for only the nonzero elements)
Ideally I'm looking for a way which is well-vectorized for octave (meaning it doesn't explicitly loop over anything)
CLARIFICATION: For the sparse matrix one, I'm looking for a solution which does not involve creating a full size(B) matrix at any point
ndgrid() does what you want, although not in the format you are looking for. If you know the dims of the input A beforehand, you can use the following line to create the N-dimentional mesh grid:
% for matrix a where ndims(a) == 3
[x, y, z] = ndgrid (1:size(a,1), 1:size(a,2), 1:size(a,3));
% x is like f(a, 1)
% y is like f(a, 2)
% z is like f(a, 3)
You may be able to write a custom wrapper around ndgrid() to convert it to the function format you are looking for.
In case anyone's curious, since I didn't know about ndgrid, here's the answer I came up with:
function [y] = indices(a,k)
s = size(a);
n = s(k);
D = length(s);
x = permute(a,[k,1:(k-1),(k+1):D]);
y = reshape(x,n,[]);
y = diag(1:n) * ones(size(y));
y = reshape(y,size(x));
y = permute(y,[(2:k),1,(k+1):D]);
endfunction
function [y] = spindices(a,k)
s = size(a);
n = s(k);
D = length(s);
x = permute(a,[k,1:(k-1),(k+1):D]);
y = reshape(x,n,[]);
y = spdiag(1:n) * spones(y);
y = reshape(y,size(x));
y = permute(y,[(2:k),1,(k+1):D]);
endfunction