I am trying to fill some values in a table (1 row n columns). 1 and 0 must be inside the table but in random positions and the remaining cells have to be random values between 0 and 1.
e.g for n=4 P should look something like this
P = 0.0000 0.58177 1.00000 0.86008
What I have done is: filling the first two positions inside the table with 1 and 0 and the rest of n (if n>2) is filled with randomized values [0,1]. Any ideas how to fix my code are welcome.
function P=pairwise_matrix(n)
P=zeros(1,n);
a = 0; b = 1;
x = a + (b-a) .* rand(1,1);
P(1,1)=1
if (n==1)
printf("not applicable")
endif
if (n==2)
P(1,1)=0
P(1,2)=1
endif
for (i=3:n)
P(1,i)=rand(x);
endfor
endfunction
First fill the vector with random values, than define
two random positions for 0 and 1
function P=pairwise_matrix(n)
if (n<3) n=3; endif
P=rand(1,n); # fill vector with random numbers
n0=floor(n*rand()); # random integer between 0 and n-1
n1=mod(n0+1+floor((n-1)*rand()),n); # random integer different from n0
P(n0+1)=0;
P(n1+1)=1;
endfunction
so we have
octave:65> pairwise_matrix(3)
ans =
1.00000 0.73595 0.00000
octave:66> pairwise_matrix(7)
ans =
0.19995 0.01847 1.00000 0.31813 0.84074 0.00000 0.68086
Related
I have a square matrix MxN, with elements xij. Each of this values is used into a function of the form some_function(i,j).
That function is applied in column order. What I want to achieve is a kernel function k(i, j) that will be placed inside some_function:
def some_function(i, j):
i', j' = k(i, j)
I will return another set (i', j') so that (i'!=i, j'!=j) and (i', j') correspond to a real value on the initial square matrix. This function applied to each of the values (i,j) wont produce any repeated pairs. The numbers produced by the kernel function (i',j') should be distributed.
My first idea was to precompute the permutations in another list and pass that values to some_function. I would like to know if there is any better way to do it. Thank you.
Consider MxN matrix as one-dimensional array of length M*N. You want to create a transformation that uniquely maps every number in range 0..MN-1 to another number in this range (and after MN steps returns to initial index).
The simplest way to achieve this goal is to make steps of size P that is mutually prime with M and N and large than M
Example:
indx = M * i + j /start cell
for k = 0.. M*N - 1 do begin
indx = (indx + P) % (M*N) //integer modulus
i = indx / M //integer division
j = indx % M //integer modulus
end // indx returns to the start value
for M=2,N=4, P=5
indx i j
0 0 0
5 2 1
2 1 0
7 3 1
4 2 0
1 0 1
6 3 0
3 1 1
Note that both i and j changes every time.
I have the following array:
AA = zeros(5,3);
AA(1,3)=1;
AA(3,3)=1;
AA(4,2)=1;
and I want to place the value one in the collumns defined by the following
vector a = [0; 2; 0; 0; 1]. Each value of this vector refers to the collumn
index that we want to change in each row. When zero apears no changes should be made.
Desired output:
0 0 1
0 1 0
0 0 1
0 1 0
1 0 0
Could you please suggest a way to do this without for loop? The goal is
a faster execution.
Thanks!!!
Approach 1
nrows = size(AA,1) %// Get the no. of rows, as we would use this parameter later on
%// Calculate the linear indices with `a` as the column indices and
%// [1:nrows] as the row indices
idx = (a-1)*nrows+[1:nrows]' %//'
%// Select the valid linear indices (ones that have the corresponding a as non-zeros
%// and use them to index into AA and set those as 1's
AA(idx(a~=0))=1
Code output with given AA -
>> AA
AA =
0 0 1
0 1 0
0 0 1
0 1 0
1 0 0
Approach 2
AA(sub2ind(size(AA),find(a~=0),a(a~=0)))=1
Breaking it down to few steps for explanation:
find(a~=0) and a(a~=0) gets us the VALID row and columns indices respectively as needed for sub2ind(size(),row,column) format.
sub2ind gets us the linear indices, which we can use to index into input matrix AA and set those in AA as 1's.
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 wasn't quite sure how to phrase this question. Suppose I have the following matrix:
A=[1 0 0;
0 0 1;
0 1 0;
0 1 1;
0 1 2;
3 4 4]
Given row 1, I want to find all rows where:
the elements that are unique in row 1, are unique in the same column in the other row, but don't necessarily have the same value
and if there are elements with duplicate values in row 1, there are be duplicate values in the same columns in the other row, but not necessarily the same value
For example, in matrix A, if I was given row 1 I would like to find rows 4 and 6.
Can't test this right now, but I think the following will work:
A=[1 0 0;
0 0 1;
0 1 0;
0 1 1;
0 1 2;
3 4 4];
B = zeros(size(A));
for ii = 1:size(A,1)
r = A(ii,:);
B(ii,1) = 1;
for jj = 2:size(A,2)
c = find(r(1:jj-1)==r(jj));
if numel(c) > 0
B(ii,jj) = B(ii,c);
else
B(ii,jj) = B(ii,jj-1)+1;
end
end
end
At the end of this we have an array B in which "like indices have like values" and the rows you are looking for are now identical.
Now you can do
[C, ia, ic] = unique(B,'rows','stable');
disp('The answer you want is ');
disp(ia);
And the answer you want will be in the variable ia. See http://www.mathworks.com/help/matlab/ref/unique.html#btb0_8v . I am not 100% sure that you can use the rows and stable parameters in the same call - but I think you can.
Try it and see if it works - and ask questions if you need more info.
Here is a simple method
B = NaN(size(A)); %//Preallocation
for row = 1:size(A,1)
[~,~,B(row,:)] = unique(A(row,:), 'stable');
end
find(ismember(B(2:end,:), B(1,:), 'rows')) + 1
A simple solution without loops:
row = 1; %// row used as reference
equal = bsxfun(#eq, A, permute(A, [1 3 2]));
equal = reshape(equal,size(A,1),[]); %// linearized signature of each row
result = find(ismember(equal,equal(row,:),'rows')); %// find matching rows
result = setdiff(result,row); %// remove reference row, if needed
The key is to compute a "signature" of each row, meaning the equality relationship between all combinations of its elements. This is done with bsxfun. Then, rows with the same signature can be easily found with ismember.
Thanks, Floris. The unique call didn't work correctly and I think you meant to use matrix B in it, too. Here's what I managed to do, although it's not as clean:
A=[1 0 0 1;
0 0 1 3;
0 1 0 1;
0 1 1 0;
0 1 2 2;
3 4 4 3;
5 9 9 4];
B = zeros(size(A));
for ii = 1:size(A,1)
r = A(ii,:);
B(ii,1) = 1;
for jj = 2:size(A,2)
c = find(r(1:jj-1)==r(jj));
if numel(c) > 0
B(ii,jj) = B(ii,c);
else
B(ii,jj) = max(B(ii,:))+1; % need max to generalize to more columns
end
end
end
match = zeros(size(A,1)-1,size(A,2));
for i=2:size(A,1)
for j=1:size(A,2)
if B(i,j) == B(1,j)
match(i-1,j)=1;
end
end
end
index=find(sum(match,2)==size(A,2));
In the nested loops I check if the elements in the rows below it match up in the correct column. If there is a perfect match the row should sum to the row dimension.
When I generalize this for the specific problem I'm working on the matrix fills with a certain set of base size(A,2) numbers. So for base 4 and greater, a max statement is needed in the else statement for no matches. Otherwise, for certain number combinations in a given row, a duplication of an element may occur when there is none.
A overview would be to reduce each row into a "signature" counting element repeats, i.e., your row 1 becomes 1, 2. Then check for equal signatures.