Search code examples
matlabimage-processingblock

How to divide an M×N image into non-overlapping blocks of [3,3]?


I have an M×N image that should be divided into non-overlapping blocks of [3 3]. For each block I should make the gradient vector, have the mean of them and finally normalize.

I have resized the image to a dividable dimension by [3 3] and used blockproc but when I tested like

fun = @(block_struct) mean2(block_struct.data);
A   = blockproc(im,[3 3],fun);

I saw that the block isn't applied to the whole image, but to the top left side of image.

Note: The number of blocks is not known.

[x,y]=size(im)
r=floor(x/3)
c=floor(y/3)
ext_x = mod(x,3);
ext_y = mod(y,3);
a = im(1:(end-ext_x), 1:(end-ext_y));
f= @(block_struct) gradient(block_struct.blockSize);
b=blockproc(im,[3,3],f);
imshow(b)

Any ideas?


Solution

  • You do know that if you do imshow(A) the size of the image displayed will be 3 times less than that of im? That is because mean2 of course reduces each block of 3×3 to a single scalar...

    Apart from the obvious, I don't see that there's anything wrong with what you're doing. I also can't reproduce what you're saying.

    As a partial solution: remember that many of MATLAB's functions are just there to make life for the average user as easy as possible. They're often not terribly complex to implement, just a bit time consuming.

    It's fairly trivial to cook together your own basic blockproc:

    %// Some bogus data
    A = reshape(1:16, 4, 4);
    
    %// Desired blocksize
    blockSize = [2 2];
    
    %// The desired function 
    fcn = @(x) mean2(gradient(x));
    
    %// "blockproc"
    m = 1;
    blocks = size(A)./blockSize;
    out = cell(blocks);
    for jj = 1:blocks(2)
        for ii = 1:blocks(1)
    
            % The indices to the current block
            blockIndsX = (1:blockSize(1)) + (ii-1)*blocks(1);
            blockIndsY = (1:blockSize(2)) + (jj-1)*blocks(2);
    
            %// Apply the function to the current block and store the result
            out{m} = fcn( A(blockIndsX, blockIndsY, :) );
    
            %// the index to the next output value
            m = m + 1;
        end
    end
    
    %// Make outcomes more intuitive; if every entry is a scalar, make the result a matrix
    if all(cellfun(@isscalar, out(:)))
        out = reshape([out{:}], size(out)); end