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.
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);
I have the following matrix which keeps track of the starting and ending points of data ranges (the first column represents "starts" and the second column represents the "ends"):
myMatrix = [
162 199; %// this represents the range 162:199
166 199; %// this represents the range 166:199
180 187; %// and so on...
314 326;
323 326;
397 399;
419 420;
433 436;
576 757;
579 630;
634 757;
663 757;
668 757;
676 714;
722 757;
746 757;
799 806;
951 953;
1271 1272
];
I need to eliminate all the ranges (ie. rows) which are contained within a larger range present in the matrix. For example the ranges [166:199] and [180:187] are contained within the range [162:199] and thus, rows 2 and 3 would need to be removed.
The solution I thought of was to calculate a sort of "running" max on the second column to which subsequent values of the column are compared to determine whether or not they need to be removed. I implemented this with the use of a for loop as follows:
currentMax = myMatrix(1,2); %//set first value as the maximum
[sizeOfMatrix,~] = size(myMatrix); %//determine the number of rows
rowsToRemove = false(sizeOfMatrix,1); %//pre-allocate final vector of logicals
for m=2:sizeOfMatrix
if myMatrix(m,2) > currentMax %//if new max is reached, update currentMax...
currentMax = myMatrix(m,2);
else
rowsToRemove(m) = true; %//... else mark that row for removal
end
end
myMatrix(rowsToRemove,:) = [];
This correctly removes the "redundant" ranges in myMatrix and produces the following matrix:
myMatrix =
162 199
314 326
397 399
419 420
433 436
576 757
799 806
951 953
1271 1272
Onto the questions:
1) It would seem that there has to be a better way of calculating a "running" max than a for loop. I looked into accumarray and filter, but could not figure out a way to do it with those functions. Is there a potential alternative that skips the for loop (some kind of vectorized code that is more efficient)?
2) Is there a completely different (that is, more efficient) way to accomplish the final goal of removing all the ranges that are contained within larger ranges in myMatrix? I don't know if I'm over-thinking this whole thing...
Approach #1
bsxfun based brute-force approach -
myMatrix(sum(bsxfun(#ge,myMatrix(:,1),myMatrix(:,1)') & ...
bsxfun(#le,myMatrix(:,2),myMatrix(:,2)'),2)<=1,:)
Few explanations on the proposed solution:
Compare all starts indices against each other for "contained-ness" and similarly for ends indices. Note that the "contained-ness" criteria has to be for either of these two :
Greater than or equal to for starts and lesser than or equal to for ends
Lesser than or equal to for starts and greater than or equal to for ends.
I just so happen to go with the first option.
See which rows satisfy at least one "contained-ness" and remove those to have the desired result.
Approach #2
If you are okay with an output that has sorted rows according to the first column and if there are lesser number of local max's, you can try this alternative approach -
myMatrix_sorted = sortrows(myMatrix,1);
col2 = myMatrix_sorted(:,2);
max_idx = 1:numel(col2);
while 1
col2_selected = col2(max_idx);
N = numel(col2_selected);
labels = cumsum([true ; diff(col2_selected)>0]);
idx1 = accumarray(labels, 1:N ,[], #(x) findmax(x,col2_selected));
if numel(idx1)==N
break;
end
max_idx = max_idx(idx1);
end
out = myMatrix_sorted(max_idx,:); %// desired output
Associated function code -
function ix = findmax(indx, s)
[~,ix] = max(s(indx));
ix = indx(ix);
return;
I ended up using the following for the "running maximum" problem (but have no comment on its efficiency relative to other solutions):
function x = cummax(x)
% Cumulative maximum along dimension 1
% Adapted from http://www.mathworks.com/matlabcentral/newsreader/view_thread/126657
% Is recursive, but magically so, such that the number of recursions is proportional to log(n).
n = size(x, 1);
%fprintf('%d\n', n)
if n == 2
x(2, :) = max(x);
elseif n % had to add this condition relative to the web version, otherwise it would recurse infinitely with n=0
x(2:2:n, :) = cummax(max(x(1:2:n-1, :), x(2:2:n, :)));
x(3:2:n, :) = max(x(3:2:n, :), x(2:2:n-1, :));
end
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 .
I have a Matlab program that generates a list x = 6.1692 8.1863 5.8092 8.2754 6.0891 the program also outputs another list aspl = 680 637 669 599 693.
The two lists are on equal length and the first element in list x is related to the first element in list aspl. I need to graph the two lists but want list aspl to be in order from smallest to largest. How would I go about doing this? If I need to move the first element in aspl to position 4 in the list, then the first element of list x also needs to be moved to position 4 in list x. The numbers above are not important they are just examples, the actual program generates hundereds of numbers.
for example x = 6.1692 8.1863 5.8092 8.2754 initially
aspl = 680 637 669 599 693
after changing aspl to ascending order this is how x should look.
x = 5.8092 8.1863 5.8092 6.1692 8.2754
aspl = 599 637 669 680 693
Use the second output of sort:
%# sort aspl, get new order of aspl
[sortedAspl, sortOrder] = sort(aspl);
%# reorder x the same way as aspl
sortedX = x(sortOrder);