In Matlab I've got a 3D matrix (over 100 frames 512x512). My goal is to find some representative points through the whole hyper-matrix. To do so I've implemented the traditional (and not very efficient) method: I subdivide the large matrix into smaller sub-matrices and then I look for the pixel with the highest value. After doing that I change those relative coordinates of that very pixel in the sub-matrix to global coordinates referenced to the large matrix.
Now, I'm redesigning the algorithm. I've seen that in order to analyze a large matrix block-by-block (that's actually what I'm doing with my old algorithm) the BLOCKPROC function is very efficient. I've read the documentation but I don't know how the "fun" function should be implemented to extract that the pixel with the highest value of each block. Thank you in advance.
*I'm trying to get the coordinates of those maximum pixels referenced to the global matrix, I really don't care about their value.
First define a function to find the location of the maximum of a (sub)matrix:
function loc = max_location(M);
[~, ii] = max(M(:));
[r c] = ind2sub(size(M),ii);
loc = [r c];
Then use
blockproc(im, blocksize, @(x) x.location+max_location(x.data)-1)
where im
is your image (2D array) and blocksize
is a 1x2 vector specifying block size. Within blockproc
, the data
field is the submatrix (which you pass to max_location
), and the location
field contains the coordinates of the top-left corner of the submatrix (which you add to the result of max_location
, minus 1).
Example:
>> blocksize = [3 3];
>> im = [ 0.3724 0.0527 0.4177 0.6981 0.0326 0.4607
0.1981 0.7379 0.9831 0.6665 0.5612 0.9816
0.4897 0.2691 0.3015 0.1781 0.8819 0.1564
0.3395 0.4228 0.7011 0.1280 0.6692 0.8555
0.9516 0.5479 0.6663 0.9991 0.1904 0.6448
0.9203 0.9427 0.5391 0.1711 0.3689 0.3763 ];
>> blockproc(im, blocksize, @(x) x.location+max_location(x.data)-1)
ans =
2 3 2 6
5 1 5 4
meaning your block maxima are located at coordinates (2,3), (5,1), (2,6) and (5,4)
Another possiblity is to use im2col
for each frame. If I
is your frame (512,512):
% rearranges 512 x 512 image into 4096 x 64
% each column of I2 represents a 64 x 64 block
n = 64;
I2 = im2col(I,[n,n],'distinct');
% find max in each block
% ~ to ignore that output
[~,y] = max(I2);
% convert those values to overall indices
ind = sub2ind(size(I2),y, 1:n);
% create new matrix
I3 = zeros(size(I2));
I3(ind)=1;
I3 = col2im(I3,[n,n],size(I),'distinct');
I3
should now be an image the same size of input I
but with all zeros except for the locations of the maximum points in each sub-matrix.
the tricky part with the function handle "fun" is that it refers to the subblocks which are a struct, this is an object with one or more fields and one or more values assigend to each of the fields.
The values of your subblocks are stored in a field called "data" so the function call
@(x)max(x)
is not enough, in this case the correct version of that is
@(x)max(x.data)
A 2D example of what you are looking for would look like this:
a=magic(4);
b=blockproc(a,[2,2],@(x) find(x.data==max(max(x.data)))); %linear indexes
outputs
a =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
b =
1 3
4 2
b
are the linear indexes of each subblock, so that's the values 16, 13, 14, 15 in a
.
Hope that helps!