Understanding Histogram in Matlab - matlab

I got the following results after applying:[h,bins]=hist(data), such that, the data will contain the LBP (Local Binary Pattern) values.
h =
221 20 6 4 1 1 2 0 0 1
bins =
Columns 1 through 7
8.2500 24.7500 41.2500 57.7500 74.2500 90.7500 107.2500
Columns 8 through 10
123.7500 140.2500 156.7500
I want to ask the following:
Does the first bin represent the values 0-8.25 and the second bin the values 8.26-24.75, and so forth?
For the h value 221, does it mean that we have computed 221 an LBP value ranging from 0-8.25?

1) No. The bin location is in the center value of the bin, that is, for the first bin the values are 0-16.5, the second bin is 16.5-33, etc. Use histc if it is more natural to specify bin edges instead of centers.
2) h(1)=221 means that from your entire data set (that has 256 elements according to your question), 221 elements had values ranging between 0-16.5 .

Related

How to create a matrix which contains a selected set of pixels from another matrix based on a third one?

I have a grayscale matrix A with certain values that are black(i.e., pixel values of 0). I have another grayscale matrix B which is of the same size as A.
I want to create a matrix C which contains only those values of B where A is 0 and the rest of the values in B turn to white. For example,
A = [0 35 0 0 88];
B = [22 3 34 99 4];
The matrix C should be
C= [22 255 34 99 255];
I'm trying to use logical indexing as follows but it has errors.
C(A==0)=B;
C(A~=0)=255;
How do I change the above line to get the desired results?
You are trying to assign the whole of B to the smaller matrix of just locations where A==0.
In order to use only the correct number of values for assignment, the first line needs to be
C(A==0)=B(A==0);
It should be noted however that the same result can be gained simply by setting all of C to the corresponding B values (C = B) and then just modifying those where A~=0 as in your 2nd line.

sparse matrix matlab unexpected behavior

I am creating a sparse matrix
sp = sparse(I,J,Val,X,Y)
My Val matrix is a ones matrix. Much to my surprise the sp matrix does not contain only zeros and ones. I suppose that this happens because in some cases there are duplicates in I,J. I mean the sp(1,1) is set to 1 2 times, and this makes it 2.
Question 1: Is my assumption true? Instead of overwriting the value, does MATLAB really add it?
Question 2: How can we get around this, given that it would be very troublesome to manipulate I and J. Something I can think of, is to use find (thus guaranteeing uniqueness) and then recreate the matrix using ones once more. Any better suggestion?
Question 1: Is my assumption true? Instead of overwriting the value, does Matlab really add it?
Correct. If you have duplicate row and column values each with their own values, MATLAB will aggregate them all into the same row and column location by adding them.
This is clearly seen in the documentation but as a reproducible example, suppose I have the following row and column locations and their associated values at these locations:
i = [6 6 6 5 10 10 9 9].';
j = [1 1 1 2 3 3 10 10].';
v = [100 202 173 305 410 550 323 121].';
Note that these are column vectors as this shape is the expected input. In a neater presentation:
>> [i j v]
ans =
6 1 100
6 1 202
6 1 173
5 2 305
10 3 410
10 3 550
9 10 323
9 10 121
We can see that there are three values that get mapped to location (6, 1), two values that get mapped to location (10, 3) and finally two that get mapped to location (9, 10).
By creating the sparse matrix and displaying it, we thus get:
>> S = sparse(i,j,v)
S =
(6,1) 475
(5,2) 305
(10,3) 960
(9,10) 444
As you can see, the three values mapped to (6, 1) are summed: 100 + 202 + 173 = 475. You can verify this with the other duplicate row and column locations.
Question 2: How can we get around this, given that it would be very troublesome to manipulate I and J. Something I can think of, is to use find (thus guaranteeing uniqueness) and then recreate the matrix using ones once more. Any better suggestion?
There are two possible ways to mitigate this if it is truly your desire to only have a binary matrix.
The first way which may be more preferable to you as you mentioned that manipulating the row and column locations is troublesome is to create the matrix that you have now, but then convert it to logical so that any values that are non-zero are set to 1:
>> S = S ~= 0
S =
10×10 sparse logical array
(6,1) 1
(5,2) 1
(10,3) 1
(9,10) 1
If you require that the precision of the matrix be back in its original double form, cast the result after you convert to logical:
>> S = double(S ~= 0)
S =
(6,1) 1
(5,2) 1
(10,3) 1
(9,10) 1
The second way if you wish is to work on your row and column locations so that you filter out any indices that are non-unique, then create a vector of ones for val that is as long as the unique row and column locations. You can use the unique function to help you do that. Concatenate the row and column locations in a two column matrix and specify that you want to operate on 'rows'. This means that each row is considered an input rather than individual elements in a matrix. Once you find the unique row and column locations, use these as input for creating the sparse matrix:
>> unique_vals = unique([i j], 'rows')
unique_vals =
5 2
6 1
9 10
10 3
>> vals = ones(size(unique_vals, 1));
>> S = sparse(unique_vals(:, 1), unique_vals(:, 2), vals)
S =
(6,1) 1
(5,2) 1
(10,3) 1
(9,10) 1

Calculate the average of elements in a matrix that correspond to a value in a separate matrix

I have a 333 x 333 adjacency matrix which consists of values that I would like to average according to the identity of each cell, which is defined in a separate 333x1 vector. There are a total of 13 different groups defined in the second vector, so ideally, I'd be able to calculate a new 13 x 13 matrix in which each cell contained the average value of the corresponding values from the larger matrix.
matrix_1: 333 x 333 --> contains values for each pairwise interaction
vector_2: 333 x 1 --> contains the identity (range: 1 - 13) for each of the elements in matrix_1 (elements are the same in both the rows and columns)
ideal output = matrix_2: 13 x 13 --> contains values in each cell which reflect the mean score for all examples of the specific identity comparison.
e.g. matrix_2(1,1) --> should contain mean score of all 1 to 1 values from matrix_1
e.g. matrix_2(1,2) --> should contain mean score of all 1 to 2 values (and 2 to 1 values) from matrix_1
Thanks in advance
Mac
I'm not 100% certain from your description, but I guess you want:
[I,J] = ndgrid(V);
out = accumarray([I(:),J(:)], M(:), [], #mean);

Matlab: Array of random integers with no direct repetition

For my experiment I have 20 categories which contain 9 pictures each. I want to show these pictures in a pseudo-random sequence where the only constraint to randomness is that one image may not be followed directly by one of the same category.
So I need something similar to
r = randi([1 20],1,180);
just with an added constraint of two numbers not directly following each other. E.g.
14 8 15 15 7 16 6 4 1 8 is not legitimate, whereas
14 8 15 7 15 16 6 4 1 8 would be.
An alternative way I was thinking of was naming the categories A,B,C,...T, have them repeat 9 times and then shuffle the bunch. But there you run into the same problem I think?
I am an absolute Matlab beginner, so any guidance will be welcome.
The following uses modulo operations to make sure each value is different from the previous one:
m = 20; %// number of categories
n = 180; %// desired number of samples
x = [randi(m)-1 randi(m-1, [1 n-1])];
x = mod(cumsum(x), m) + 1;
How the code works
In the third line, the first entry of x is a random value between 0 and m-1. Each subsequent entry represents the change that, modulo m, will give the next value (this is done in the fourth line).
The key is to choose that change between 1 and m-1 (not between 0 and m-1), to assure consecutive values will be different. In other words, given a value, there are m-1 (not m) choices for the next value.
After the modulo operation, 1 is added to to transform the range of resulting values from 0,...,m-1 to 1,...,m.
Test
Take all (n-1) pairs of consecutive entries in the generated x vector and count occurrences of all (m^2) possible combinations of values:
count = accumarray([x(1:end-1); x(2:end)].', 1, [m m]);
imagesc(count)
axis square
colorbar
The following image has been obtained for m=20; n=1e6;. It is seen that all combinations are (more or less) equally likely, except for pairs with repeated values, which never occur.
You could look for the repetitions in an iterative manner and put new set of integers from the same group [1 20] only into those places where repetitions have occurred. We continue to do so until there are no repetitions left -
interval = [1 20]; %// interval from where the random integers are to be chosen
r = randi(interval,1,180); %// create the first batch of numbers
idx = diff(r)==0; %// logical array, where 1s denote repetitions for first batch
while nnz(idx)~=0
idx = diff(r)==0; %// logical array, where 1s denote repetitions for
%// subsequent batches
rN = randi(interval,1,nnz(idx)); %// new set of random integers to be placed
%// at the positions where repetitions have occured
r(find(idx)+1) = rN; %// place ramdom integers at their respective positions
end

Full range of values on x-axis - matlab

I'm trying to check the full range of values on the x-axis of a histogram, especially while I expected the full range to be [0, 255], when I used the following command for the histogram [h, bins] = hist(H), I got the following:
h =
221 20 6 4 1 1 2 0 0 1
bins =
Columns 1 through 7
8.2500 24.7500 41.2500 57.7500 74.2500 90.7500 107.2500
Columns 8 through 10
123.7500 140.2500 156.7500
This implies that the maximum range I got here is up to 165.
If we look at the histogram below, we can see that 165 seems to be the maximum number of frequency value. How do I know the maximum value (range) of the x-axis?
I think you need either one of these 3 options:
max(H)
Or
numel(unique(H))
or
numel(H)
I would start at the top till you find the one you need.