find contiguous region with highest values

13 visualizzazioni (ultimi 30 giorni)
amen45
amen45 il 21 Ott 2016
Commentato: Walter Roberson il 23 Ott 2016
I'm trying to get the indexes of the region covering 10% of an m x n graph that has the highest values.
For example:
0 0 0 0 0 3
2 2 2 0 0 0
0 0 0 0 0 1
0 0 0 0 1 2
0 0 0 0 0 0
Should give me rows 2,2,2 and columns 1,2,3 (the output format doesn't matter for my purposes).
The region needs to be contiguous, and not just the region with the single highest value. Could someone point me in the right direction?
  4 Commenti
amen45
amen45 il 22 Ott 2016
Modificato: amen45 il 22 Ott 2016
I'm sorry about the confusion! It's the total over the region. I think perhaps it's better if I explain the actual problem I'm trying to solve.
I have a series of images that are 20 x 200 with floating point values generated by a previous analysis (not set by me). I've identified a 30x 3 "pixel" region (ie all values at indices (7:9,60:90) that I want to evaluate across all my figures). Within that region, I want to find the "cluster" pixels of size ~5 that has the highest values. They need to be next to each other, because in my data a regional relationship is required for them to be part of the same phenomenon (so pulling out the k highest values won't work). Again, the regional value is the important part so finding the location of the maximum values won't work either.
I have some preliminary code that I'll post in a separate comment. Please let me know if I can clarify anything else?
Walter Roberson
Walter Roberson il 23 Ott 2016
This does not answer to the question of what happens for a tie, and does not answer to the question of how you determine which cluster has the "highest values" across clusters of different sizes and where simple maximum is not the key. Is the key the mean over the cluster? Is the key the sum over the cluster?

Accedi per commentare.

Risposte (3)

Chaya N
Chaya N il 21 Ott 2016
Modificato: Chaya N il 21 Ott 2016
There may be a nice (but slightly complicated) way of getting the linear indices here. The idea is something like this: Get connected components ( blobs shall we say?) --> Get pixel index list --> For each set of pixels, compute their pixel sum --> Find the index of the maximum pixelsum --> Get linear indices for the blob with the maximum pixelsum.
The code would be something like this:
x = [0 0 0 0 0 3 % your example here
2 2 2 0 0 0
0 0 0 0 0 1
0 0 0 0 1 2
0 0 0 0 0 0];
CC = bwconncomp(x); % Blobs and their data
SumPixels = cell2mat(cellfun(@(y) sum(x(y)),CC.PixelIdxList,'UniformOutput',0)); % Get Pixelsum
[~,idx] = max(SumPixels);
LinIdx = CC.PixelIdxList{idx};
And Voila! I get:
LinIdx =
2
7
12
You could find the row and column indices from the above, but this is where I leave you.
PS: For pedagogical reasons, I suggest you look up the bwconncomp and cellfun functions. To learn more about linear indices, please look at the "More About" section here .
  2 Commenti
amen45
amen45 il 22 Ott 2016
I think this doesn't quite do what i need- it's not a binary array, and i actually don't even always have ints. any thoughts?
Chaya N
Chaya N il 22 Ott 2016
Modificato: Chaya N il 22 Ott 2016
It would depend on how you separate your regions of interest. How do you define that certain pixels or a certain contiguous region belongs to your object of interest and not the background?
Also, you could always adapt/modify your non-integer-valued array long enough to get your program running. You could even change all your background values to zeros with a logical statement. My point is, the entire logic of the code depends on where the 'edges' of your regions lie, and a handful of pixels more or less makes a big difference to the region that you would obtain.

Accedi per commentare.


Image Analyst
Image Analyst il 22 Ott 2016
Try ismember() and you can do it in 2 lines. See this well commented demo:
% Define sample data consisting of integers
% (Slightly different than your example)
m = [0 0 0 0 0 3
2 2 2 0 0 0
0 0 0 0 0 1
0 3 3 0 1 2
0 0 0 0 0 0]
% 3 is the "highest value" and is what is sought.
% 3 occurs in two regions (places).
% Find those two regions of highest value
% and put locations into a logical array.
locations = ismember(m, max(m(:)))
% Get a new matrix withteh actual values.
highestValueRegions = m .* locations

Image Analyst
Image Analyst il 22 Ott 2016
If you have floating point values, I think what you're trying to say is that you want a matrix with only elements that are in the highest 10% of all values in the array. You can do this like:
% Define sample data consisting of floating point numbers
m = 100 * rand(6, 5)
% Sort the array
sortedm = sort(m(:), 'descend')
% Find the 10% index
index10 = ceil(0.1 * numel(m))
% Determine the value that 10% of the values lie above
value10 = sortedm(index10)
% Get binary "map" of where these highest 10% of values live:
binaryImage = m >= value10
% Extract a matrix with only the highest 10% of floating point values:
output = m .* binaryImage
When I ran it, this is what I got. Tell me if this is what you were thinking of:
m =
9.1113 64.762 23.623 77.029 25.644
57.621 67.902 11.94 35.022 61.346
68.336 63.579 60.73 66.201 58.225
54.659 94.517 45.014 41.616 54.074
42.573 20.893 45.873 84.193 86.994
64.444 70.928 66.194 83.292 26.478
sortedm =
94.517
86.994
84.193
83.292
77.029
70.928
68.336
67.902
66.201
66.194
64.762
64.444
63.579
61.346
60.73
58.225
57.621
54.659
54.074
45.873
45.014
42.573
41.616
35.022
26.478
25.644
23.623
20.893
11.94
9.1113
index10 =
3
value10 =
84.193
binaryImage =
6×5 logical array
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0
0 0 0 1 1
0 0 0 0 0
output =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 94.517 0 0 0
0 0 0 84.193 86.994
0 0 0 0 0
  13 Commenti
Chaya N
Chaya N il 22 Ott 2016
Modificato: Chaya N il 22 Ott 2016
To add to the above, I would suggest a square mask (or scrolling array, if you'd like) with odd number of elements so you would have something of a 'center' value. This is a common tactic used in filtering operations. Also, the mask size and shape would influence the data, so choose as small a square size as possible so you would not end up manipulating your data over the necessary amount. In my example, I have chosen a 3x3 mask because it is the smallest odd square that I could use that is greater than k.
Image Analyst
Image Analyst il 22 Ott 2016
To get the mean of the interactions (pixels) in a horizontal 1-by-2 sliding window, do this:
[rows, columns] = size(im)
for col = 1 : columns
windowWidth = col;
kernel = ones(1, windowWidth) / windowWidth;
meanImage = conv2(im, kernel, 'same');
% Now do something with meanImage.....
end
where m is your interaction matrix.
To do the same but in a vertical 2-by-1 sliding window, do this:
[rows, columns] = size(im)
for row = 1 : rows
windowHeight = row;
kernel = ones(windowHeight, 1) / windowHeight;
meanImage = conv2(im, kernel, 'same');
% Now do something with meanImage.....
end
If you want, you could use a double for loop over both rows and columns to create all possible kernel shapes:
[rows, columns] = size(im)
for col = 1 : columns
for row = 1 : rows
kernel = ones(row, col)/(row * col);
meanImage = conv2(im, kernel, 'same');
% Now do something with meanImage.....
end
end
Not sure what you want to do with the mean image once you have it though.

Accedi per commentare.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by