2

This is a follow up to the question: Overlapping sliding window over an image using blockproc or im2col?

So by using the code :

B = blockproc(A, [1 1], @block_fun, 'BorderSize', [2 2], 'TrimBorder', false, 'PadPartialBlocks', true)

I was able to create an overlapping sliding window over my image and calculate the dct2 for each window. But the problem is that blockproc concatenates the output in a way that I cannot use. The output greatly depends on the block size and the size of the output matrix is different because of it every time.

My dct2 function creates a 1 x 200 vector for every block or window. So I assumed that if there are 64 blocks I should get something like 64 x 200 or 200 x 64 output, but I get something like 64 x 1600 or in case of larger blocks I get 15 x 400.

Looking into the blockproc function the problem is caused by

% write 4 corner blocks
b(1:ul_output_size(1),1:ul_output_size(2),:) = ul_output;
if ll_processed
    last_row_start = final_rows - size(ll_output,1) + 1;
    last_row_width = size(ll_output,2);
    b(last_row_start:end,1:last_row_width,:) = ll_output;
end
if ur_processed
    last_col_start = final_cols - size(ur_output,2) + 1;
    last_col_height = size(ur_output,1);
    b(1:last_col_height,last_col_start:end,:) = ur_output;
end
if lr_processed
    last_row_start = final_rows - size(ll_output,1) + 1;
    last_col_start = final_cols - size(ur_output,2) + 1;
    b(last_row_start:end,last_col_start:end,:) = lr_output;
end

Apparently, blockproc further divides the blocks into upper left, upper right, lower left and lower right and concatenates that result. And that is why I am getting all this mixed outputs.

I need the output of each block in its each row, for each window. Each window should just give me a 1x200 output, that I can feed into my classifier.

Can I force the output of blockproc in the way that I want it, just give the output of each block.

If not, I would really appreciate an alternative solution to have an overlapping sliding window over the image.

edit: would it be possible to save the blocks data using block_struct.data for every block into a cell array inside the function block_fun and then use that array to extract my features?

Thank you

edit:

B = blockproc(images_m{1}, [64 64], @(x)reshape(x.data(:),[1 1 numel(x.data)]), 'BorderSize', [10 10], 'TrimBorder', false, 'PadPartialBlocks', true, 'PadMethod', 'replicate');
imgs = {};
for i = 1:size(B,1)
    for j = 1:size(B,2)
        tempy = squeeze(B(i,j,:));
        tempy2 = reshape(tempy, [84 84]);
        feats{end+1} = block_dct2(tempy2); %calculates dct2 for the block and returns a 1*200 vector

    end
end
Community
  • 1
  • 1
StuckInPhDNoMore
  • 2,507
  • 4
  • 41
  • 73
  • The '4 corner blocks' is a red herring. If your callback function returned a 1x200 for each pixel in a 3x3 image - imagine each pixel being replaced by that 1x200 vector (resulting in a 200*3 wide image). You could 'reshape' the result if you know the output size of the callback function. Or, see if my answer helps you with an alternate approach. – Ashish Uthama Mar 18 '15 at 19:56
  • 1
    See if [this](http://stackoverflow.com/a/29132803/3293881) helps? – Divakar Mar 18 '15 at 23:06
  • 2
    Clarifying my first comment - This assumption: "Apparently, blockproc further divides the blocks into upper left, upper right, lower left and lower right and concatenates that result. And that is why I am getting all this mixed outputs." is incorrect. BLOCKPROC doesn't subdivide a given block size and the output is not mixed :) (I can explain in more detail, but I dont think that adds to this question) – Ashish Uthama Mar 19 '15 at 15:25
  • Thank you @Divakar for the alternative solution. I will definitely look into it if this one fails :) – StuckInPhDNoMore Mar 20 '15 at 18:30

2 Answers2

1

Maybe reshape you data in the third dimension?

>> A = magic(3)

A =

     8     1     6
     3     5     7
     4     9     2

>> B = blockproc(A, [1 1], @(x)reshape(x.data(:),[1 1 numel(x.data)]), 'BorderSize', [1 1], 'TrimBorder', false, 'PadPartialBlocks', true);

>> whos B
  Name      Size             Bytes  Class     Attributes

  B         3x3x9              648  double  
>> squeeze(B(1,1,:))

ans =

     0
     0
     0
     0
     8
     3
     0
     1
     5

>> 
Ashish Uthama
  • 1,331
  • 1
  • 9
  • 14
  • Thanks for looking at my question. And thank you for your answer. Can you please help me understand your code a little bit. When I applied your code to my image I got size ``2x17x24336``. I know that ``24336`` is because of my block size which is ``[156 156]`` but how do I interpret the other dimensions, does 17 mean I have 17 blocks? I need to get the rows back into matrix form to apply ``dct2`` to it, I tried ``reshape((squeeze(B(1,1,:))), [156 156])`` to get the first block, how do I get the other blocks? Thank you – StuckInPhDNoMore Mar 18 '15 at 19:59
  • Right I created a nested for loop and apparently the image is divided into ``17*2`` blocks and each can be obtained using the code above. I think this will work and I will give it a try. Many thanks for your help :) – StuckInPhDNoMore Mar 18 '15 at 20:02
  • @FarazKhan - Hard to follow what you are running into without some reproducible code. What is the next step? Why cant you fold that right into the blockproc callback itself (since in that context, you'll have the data as 156x156). – Ashish Uthama Mar 19 '15 at 00:44
  • I added the code based on your answer to my main question, I just wanted a controllable way to divide the image into overlapping windows. Your code made it possible to control that. I tried adding the ``dct2`` call function in ``blockproc`` but that would again concatenate the results in a way that could not be used in my classifer as explained in my question above. What do you mean by ``blockproc`` returning data as ``156 x 156``? Thank you – StuckInPhDNoMore Mar 19 '15 at 14:25
1

An alternate using MAT2CELL:

function extractFeatures
images_m{1} = rand(128);
B = blockproc(images_m{1}, [64 64], @processBlock,...
    'BorderSize', [10 10], 'TrimBorder', false,...
    'PadPartialBlocks', true, 'PadMethod', 'replicate');

%B is 2x400 i.e 2x2 blocks of each block being a 1x200 feature vector
m = ones(1,size(B,1));
n = 200*ones(1,size(B,2)/200);
% The MAT2CELL help does a good job, just read it carefully and run the
% examples
feats = mat2cell(B,m,n);
feats = feats(:);

end

function feature = processBlock(bstruct)    
    % I dont know what block_dct2 does:
    %feature = block_dct2(bstruct.data);
    % So I'll put in a place holder which returns a 1x200 'feature'
    % for each overlapping image block
    feature = repmat(mean(bstruct.data(:)), [1 200]);
end
Ashish Uthama
  • 1,331
  • 1
  • 9
  • 14
  • Many thanks @Ashish Uthama but I think I will go with the previous answer even though it appears more inefficient. It gives me more control over my results which I would like to have. This does not always work because based on my sliding window size I dont always get ``2*400`` ``B``. It varies with the block size. If I use a ``[16 16]`` window size the results returned by ``B`` are very different :( – StuckInPhDNoMore Mar 20 '15 at 18:29