calvin tiger
calvin tiger

Reputation: 391

Center crop or pad an image within a frame

My question is about a problem that is very easy to solve, but I am interested in learning the best practice for this. (nominally for Matlab, but not really language-specific ).

I am loading an image of an arbitrary size, and I need to make it fit (without any scaling nor change of aspect ratio) within a black image of a predefined size (let's call it the frame). The loaded image can be smaller, equal or bigger than the predefined frame, in either or both dimension(s).

If the image is smaller than the frame, I want it to be padded with zeros (there will be a black border around it), up to the frame size, and centered. If it is bigger, I want to crop it in a centered fashion.

Ideally, I do not want to make any assumptions on the parity of the pixel numbers in either dimension - that is, both the loaded image and the frame can have odd or even pixel numbers for both dimensions. Surely there will be some rounding to do.

I'm sure that this problem has been researched, solved and exhausted, so it shouldn't be a very hard question for knowledgeable programmers with some experience in image processing :)

Upvotes: 4

Views: 1961

Answers (1)

Junuxx
Junuxx

Reputation: 14251

This should work for both greyscale and color images of smaller, equal and larger size than the frame. Tried to keep it sort of readable.

frameWidth = 800;
frameHeight = 600;
imagepath = 'smaller.jpg'; % 'equal.jpg', 'larger.jpg'

img = im2double(imread(imagepath));
[imgHeight, imgWidth, channels] = size(img);
frame = zeros(frameHeight, frameWidth, channels);

dImageWidth = round((frameWidth - imgWidth)/2);
dImageHeight = round((frameHeight - imgHeight)/2);

unEqualHeight = (imgHeight ~= frameHeight);
unEqualWidth = (imgWidth ~= frameWidth);

if imgHeight <= frameHeight
    frameVStart = max(1, dImageHeight);
    frameVEnd = min(frameHeight, frameHeight-dImageHeight-unEqualHeight);
    imgVStart = 1;
    imgVEnd = imgHeight;
else
    frameVStart = 1;
    frameVEnd = frameHeight; 
    imgVStart = max(1, -dImageHeight);
    imgVEnd = min(imgHeight, imgHeight+dImageHeight);
end

if imgWidth <= frameWidth
    frameHStart = max(1, dImageWidth);
    frameHEnd = min(frameWidth, frameWidth-dImageWidth-unEqualWidth);
    imgHStart = 1;
    imgHEnd = imgWidth;
else
    frameHStart = 1;
    frameHEnd = frameWidth; 
    imgHStart = max(1, -dImageWidth);
    imgHEnd = min(imgWidth, imgWidth+dImageWidth);
end

frame(frameVStart:frameVEnd, frameHStart:frameHEnd, :) = ...
    img(imgVStart:imgVEnd, imgHStart:imgHEnd, :);

imshow(frame);

Upvotes: 1

Related Questions