Search code examples
matlabbounding-box

Odd bounding box coordinates in Matlab


I'm using regionprops(img,'BoundingBox'); to generate bounding boxes around some objects in an image. The coordinates of the bounding boxes (x, y, width, height) are always by 0.5 off from Integer-values. Why is that the case?

For me, it is causing two problems:

  • When using these coordinates for accessing an image array, I get the warning: Warning: Integer operands are required for colon operator when used as index. I can live with that, respectively remove it with floor or ceil, BUT ...
  • ... when these coordinates are close to image borders, they cause errors since the values 0.5 and 1024.5 don't match with the image borders 1 and 1024. I get Subscripted assignment dimension mismatch. or Index exceed matrix dimensions., which is plausible.

So can someone explain to me:

  1. Why is it doing this?
  2. How am I supposed to work with it when using the coordinates to crop and replace image regions. I want to replace exactly what was cropped by imcrop and rounding is a bit circumstancial (simply using floor or ceil won't work, I would have to check for the image borders which is not a problem but seems a bit tedious for a rather simple task and certainly questionable whether it is supposed to be used like this...).

Below are some code snippets with which I produced the errors for a 1024x1024 image.

bb_coords = [124.5  979.5   27  45];   % example for bounding box generated by regionprops
subregion = imcrop(img, bb_coords);    % works fine with imcrop

% but when I want to use these coordinates for accessing the img array, 
% I generally get a warning and in this case an error.
img( bb_coords(2):(bb_coords(2)+bb_coords(4)), ...
     bb_coords(1):(bb_coords(1)+bb_coords(3))) = subregion;

Solution

  • Functions in MATLAB that handle image display or processing treat the center of the pixel as lining up with the corresponding coordinate grid points. In other words, for a given dimension of an image, the first pixel center is at 1, the second pixel center is at 2, etc., and the area of each pixel will span +-0.5 on either side of the coordinate. You can see this when you plot an image, turn the axes display on, and zoom in around one of the corners:

    img = imread('cameraman.tif');  % Load a sample image
    imshow(img);                    % Display it
    set(gca, 'Visible', 'on');      % Make the axes visible
    axis([0 5 252 257]);            % Zoom in on the bottom left corner
    

    The documentation for regionprops illustrates that the 'BoundingBox' will enclose the entire pixel area, thus leading to a bounding box that appears a full pixel wider (0.5 pixels wider on each side) than the range of center coordinates:

    enter image description here

    For the 5-by-5 sample image above, the nonzero pixels cover an area that spans the top 4 rows (row coordinates of the pixel centers from 1 to 4) and right 4 columns (column coordinates of the pixel centers from 2 to 5). The bounding box (in green) therefore spans from 0.5 to 4.5 (height of 4) across the rows and 1.5 to 5.5 (width of 4) across the columns.

    In short, if you want to use the bounding box values in bb_coords to generate indices into the image, you need to add 0.5 to each corner coordinate and subtract 1 from each width:

    ind_coords = bb_coords + [0.5 0.5 -1 -1];
    img(ind_coords(2):(ind_coords(2)+ind_coords(4)), ...
        ind_coords(1):(ind_coords(1)+ind_coords(3))) = subregion;