I have a N×N general matrix H with rank n(<N).
Is there any way to get a n×n matrix with rank n from H?
For example,
|1 2 3|
H = |4 8 6|
|0 0 1|
has three eigenvalues 0,1,9 and its rank is 2. I want to get a 2×2 matrix with rank 2 which corresponds to the eigenspace sappaned by eigenvectors of 1,9.
We are given a 3x3 matrix H that is known to have rank r < 3:
1 2 3
4 8 6
0 0 1
One can obtain an nxn matrix comprised of the intersection of rows and columns of H that has rank n by computing the reduced row echelon form (RREF) of H (also called the row canonical form).
After doing so, for each of n row indices i there will be a column in the RREF that contains a 1 in row i (i.e., the row having index i) and zeroes in all other rows. It is seen here that the RREF of H is the following.
1 2 0
0 0 1
0 0 0
As column 0 (i.e., the column having index 0) in the RREF has a 1 in row 0 and zeroes in all other rows, and column 2 has a 1 in row 1 and zeroes in all other rows, and no other column has a 1 in one row and zeroes in all other rows, we conclude that:
H has rank 2; and
the nxn matrix comprised of elements in H that are in rows 0 and 1 and columns 0 and 2 has rank n.
Here an nxn matrix with rank n is therefore found to be
1 3
4 6
The same procedure is followed regardless of the size of H (which need not be square) and the rank of H need not be known in advance.
Using the RowEchelon.jl package, we can apply the method described in #CarySwoveland's answer pretty easily. (This is not my area of expertise though, so any corrections to it are welcome; specifically, the choice of rows as 1 to number of pivots is an educated guess based on some trials.)
julia> H = [1 2 3
4 8 6
0 0 1];
julia> using RowEchelon
julia> _, pivotcols = rref_with_pivots(H)
([1.0 2.0 0.0; 0.0 0.0 1.0; 0.0 0.0 0.0], [1, 3])
julia> result = H[1:length(pivotcols), pivotcols]
2×2 Matrix{Int64}:
1 3
4 6
The package is just a home for code that used to be in Base Julia, so you can even just copy the code if you don't want to add it as a dependency.
For a project I am working on, I am loading in large image files, which Matlab inputs as LxWx3 arrays of uint8s. I have a function which concatenates these component-wise into a LxWx1 array of uint32s, but I can't find a way to do the reverse without using nested for loops, which is far too slow for the matrices I am working with.
Could anyone recommend a way to accomplish this effuciently? Basically, given a LxW Matrix of uint32s, I want to return a LxWx3 matrix of uint8s, where the (x, y,1:3) components are the three most significant bytes in the corresponding uint32.
You can do that with typecast:
A = uint32([2^16 2^30; 256 513]);
B = permute(reshape(typecast(A(:), 'uint8'), [], size(A,1), size(A,2)), [2 3 1]);
B = flipdim(B, 3); %// flip 3rd dim to bring MSB first, if needed (depends on computer)
B = B(:,:,2:4);
Example: for A = uint32([2^16 2^30; 256 513]);
A =
65536 1073741824
256 513
the result is
B(:,:,1) =
1 0
0 0
B(:,:,2) =
0 0
1 2
B(:,:,3) =
0 0
0 1
I would like to calculate a couple of texture features (namely: small/ large number emphasis, number non-uniformity, second moment and entropy). Those can be computed from Neighboring gray-level dependence matrix. I'm struggling with understanding/implementation of this. There is very little info on this method (publicly available).
According to this paper:
This matrix takes the form of a two-dimensional array Q, where Q(i,j) can be considered as frequency counts of grayness variation of a processed image. It has a similar meaning as histogram of an image. This array is Ng×Nr where Ng is the number of possible gray levels and Nr is the number of possible neighbours to a pixel in an image.
If the image function f(i,j) is discrete, then it is easy to computer the Q matrix (for positive integer d, a) by counting the number of times the difference between each element in f(i,j) and its neighbours is equal or less than a at a certain distance d.
Here is the example from the same paper (d = 1, a = 0):
Input (image) matrix and output matrix Q:
I've been looking at this example for hours now and still can't figure out how they got that Q matrix. Anyone?
The method was originally created by C. Sun and W. Wee and was described in a paper called: "Neighboring gray level dependence matrix for texture classification" to which I got access, but can't download (after pressing download the page reloads and that's it).
In the example that you have provided, d=1 and a=0. When d=1, we consider pixels in an 8-pixel neighbourhood. When a=0, this means that we look for pixels that have the same value as the centre of the neighbourhood.
The basic algorithm is the following:
Initialize your NGLDM matrix to all zeroes. The total number of rows corresponds to the total number of possible intensities / values in your image. The total number of columns corresponds to how many pixels are in your neighbourhood plus 1. As such for d=1, we have an 8-pixel neighbourhood and so 8 + 1 = 9. Because there are 4 possible intensities (0,1,2,3), we thus have a 4 x 9 matrix. Let's call this matrix M.
For each pixel in your matrix, take note of this pixel. This goes in the Ng row.
Write out how many valid neighbours there are that surround this pixel.
Count how many times you see the neighbouring pixels matching that pixel in Step #1. This is your Nr column.
Once you figure out the numbers in Step #1 and Step #2, increment this location by 1.
Here's a slight gotcha: They ignore the border locations. As such, you don't do this procedure for the first row, last row, first column or last column. My guess is that they want to be sure that you have an 8-pixel neighbourhood all the time. This is also dictated by the distance d=1. You must be able to grab every valid pixel given a centre location at d=1. If d=2, then you would have to make sure that every pixel in the centre of the neighbourhood has a 25 pixel neighbourhood and so on.
Let's start from the second row, second column location of this matrix. Let's go through the steps:
Ng = 1 as the location is 1.
Valid neighbours - Starting from the top left pixel in this neighbourhood, and scanning left to right and omitting the centre, we have: 1, 1, 2, 0, 1, 0, 2, 2.
How many values are equal to 1? Three times. Therefore Nr = 3
M(Ng,Nr) += 1. Access row Ng = 1, and access row Nr = 3, and increment this spot by 1.
Want to know how I figured out they don't count the borders? Let's do the bottom left pixel. That location is 0, so Ng = 0. If you repeat the algorithm that I just said, you would expect Ng = 0, Nr = 1, and so you would expect at least one entry in that location in your matrix... but you don't! If you do similar checks around the border of the image, you'll see that entries that are supposed to be there... aren't. Take a look at the third row, fifth column. You would think that Ng = 1 and Nr = 1, but we don't see that in the matrix.
One more example. Why is M(Ng,Nr) = 4, Ng = 2, Nr = 4? Well, take a look at every pixel that has a 2 in it. The only valid locations where we can capture an 8 pixel neighbourhood successfully are the row=2, col=4, row=3, col=3, row=3, col=4, row=4, col=3, and row=4, col=4. By applying the same algorithm that we have seen, you'll see that for each of those locations, Nr = 4. As such, we see this combination of Ng = 2, Nr = 4 four times, and that's why the location is set to 4. However, in row=3, col=4, this actually is Nr = 5, as there are five 2s in that neighbourhood at that centre. That's why you see Ng = 2, Nr = 5, M(Ng,Nr) = 1.
As an example, let's do one of the locations. Let's do the 2 smack dab in the middle of the matrix (row=3, col=3):
Ng = 2
What are the valid neighbouring pixels? 1, 1, 2, 0, 2, 3, 2, 2 (omit the centre)
Count how many pixels equal to 2. There are four of them, so Nr = 4
M(Ng,Nr) += 1. Take Ng = 2, Nr = 4 and increment this spot by 1.
If you do this with the other valid locations that have 2, you'll see that Nr = 4 each time with the exception of the third row and fourth column, where Nr = 5.
So how would we implement this in MATLAB? What you can do is use im2col to transform each valid neighbourhood into columns. What I'm also going to do is extract the centre of each neighbourhood. This is actually the middle row of the matrix. We will then figure out how many pixels for each neighbourhood equal the centre, sum them up, and this will determine our Nr values. The Ng values will be the middle row values themselves. Once we do this, we can compute a histogram based on these values just like how the algorithm is doing to get our matrix. In other words, try doing this:
% // Your example
A = [1 1 2 3 1; 0 1 1 2 2; 0 0 2 2 1; 3 3 2 2 1; 0 0 2 0 1];
B = im2col(A, [3 3]); %//Convert neighbourhoods to columns - 3 x 3 means d = 1
C = bsxfun(#eq, B, B(5,:)); %//Figure out a logical matrix where each column tells
%//you how many elements equals the one in each centre
D = sum(C, 1) - 1; %// Must subtract by 1 to discount centre pixel
Ng = B(5,:).' + 1; % // We must make this into a column vector, and we also must
% // offset by 1 as MATLAB starts indexing by 1.
%// Column vector is for accumarray input
Nr = D.' + 1; %// Do the same for Nr. We could have simply left out the + 1 here and
%// took out the subtraction of -1 for D, but I want to explicitly show
%// the steps
Q = accumarray([Ng Nr], 1, [4 9]); %// 4 unique intensities, 9 possible locations (0-8)
... and here is our matrix:
Q =
0 0 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0
0 0 0 0 4 1 0 0 0
0 1 0 0 0 0 0 0 0
If you check this, you'll see this matches with Q.
Bonus
If you want to be able to accommodate for the algorithm in general, where you specify d and a, we can simply follow the guidelines of your text. For each neighbourhood, you find the difference between the centre pixel and all of the other pixels. You count how many pixels are <= a for any positive integer d. Note that this will create a 2*d + 1 x 2*d + 1 neighbourhood we need to examine. We can also make this into a function. Without further ado:
%// Set A up yourself, then use a and d as inputs
%// Precondition - a and d are both integers. a can be 0 and d is positive!
function [Q] = calculateGrayDepMatrix(A, a, d)
neigh = 2*d + 1; % //Calculate rows/columns of neighbourhood
numTotalNeigh = neigh*neigh; % //Calculate total number of pixels in neighbourhood
middleRow = ceil(numTotalNeigh / 2); %// Figure out which index the middle row is
B = im2col(A, [neigh neigh]); %// Make into columns
Cdiff = abs(bsxfun(#minus, B, B(middleRow,:))); %// For each neighbourhood, subtract with its centre
C = Cdiff <= a; %// For each neighbourhood, figure out which differences are <= a
D = sum(C, 1) - 1; % //For each neighbourhood, add them up
Ng = B(middleRow,:).' + 1; % // Determine Ng and Nr, and find Q
Nr = D.' + 1;
Q = accumarray([Ng Nr], 1, [max(Ng) numTotalNeigh]);
end
We can recreate the scenario we showed above with the example matrix by:
A = [1 1 2 3 1; 0 1 1 2 2; 0 0 2 2 1; 3 3 2 2 1; 0 0 2 0 1];
Q = calculateGrayDepMatrix(A, 0, 1);
Q is thus:
Q =
0 0 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0
0 0 0 0 4 1 0 0 0
0 1 0 0 0 0 0 0 0
Hope this helps!
creating an MxN matrix of random integer values in GNU Octave is very easy:
K = randi(k, M, N)
where k is the maximum value.
However, I have the requirement that each column vector in this matrix should be unique. Is there a clever way to ensure this in Octave? I could, of course, loop over all columns and calculate the pair-wise difference between all possible pairing of column vectors. But that seems a bit cumbersome.
Does anyone have a better idea?
One options would be to use unique to eliminate duplicate columns, and compare the dimensions of the result with the dimensions of the original matrix. Note that we need to transpose the matrix to be able to use the rows parameter to unique.
# Non unique columns
octave> K=[1 2 1; 2 2 2]
K =
1 2 1
2 2 2
octave> isequal(size(unique(K','rows')), size(K'))
ans = 0
# Unique columns
octave> K=[1 2 3; 2 2 2]
K =
1 2 3
2 2 2
octave> isequal(size(unique(K','rows')), size(K'))
ans = 1
I here by post the code why I came across while exploring one technique.
Y = repmat((1:m)', [1 n]);
X = repmat(1:n, [m 1]) - labels_left;
X(X<1) = 1;
indices = sub2ind([m,n],Y,X);
final_labels = labels_left;
final_labels(abs(labels_left - labels_right(indices))>=1) = -1;
In above code labels left is single channel image.[m n] is the size of that image. I want to know how this sub2ind works in above code.And Iam also facing problem in the last statement which contains
labels_right(indices)
what the above expression evaluates to.Here labels right is also an image
Maybe a smaller example could help understand:
%# image matrix
M = rand(4,3)
[m n] = size(M)
%# meshgrid, and convert to linear indices
[X,Y] = meshgrid(1:n,1:m)
indices = sub2ind([m,n],Y,X)
%# extract those elements
M(indices)
The matrix M:
>> M
M =
0.95717 0.42176 0.65574
0.48538 0.91574 0.035712
0.80028 0.79221 0.84913
0.14189 0.95949 0.93399
the grid of (x,y) coordinates of all points:
>> X,Y
X =
1 2 3
1 2 3
1 2 3
1 2 3
Y =
1 1 1
2 2 2
3 3 3
4 4 4
converted to linear indices:
>> indices
indices =
1 5 9
2 6 10
3 7 11
4 8 12
then we index into the matrix using those indices.
>> M(indices)
ans =
0.95717 0.42176 0.65574
0.48538 0.91574 0.035712
0.80028 0.79221 0.84913
0.14189 0.95949 0.93399
Note that: M(indices(i,j)) = M(Y(i,j)),X(i,j)).