How to change background color with imrotate function?

39 views (last 30 days)
I want to use imorotate function.
When this function let turn, a background color becomes the black.
Do you have the method to leave a background white?

Accepted Answer

mark palmer
mark palmer on 10 Jan 2023
A quick, if inelegant, fix is just to convert the image to it's negative
I = 255 - I
then rotate
I = imrotate(I,rotvalue)
then convert back to original colors
I = 255 - I
  2 Comments
DGM
DGM on 10 Jan 2023
As external workarounds go, I think this is pretty elegant. It does only really work for the particular case of white padding, but that is what was requested. Using imcomplement() as Walter suggests would make it independent of image class.

Sign in to comment.

More Answers (3)

DGM
DGM on 10 Jan 2023
Edited: DGM on 11 Jan 2023
Modifying or Replacing imrotate()
I don't think reimplementing or modifying imrotate() is the easier solution, especially for a novice user.
What would be the easiest approach to modifying imrotate()? To add flexible padding functionality on the typical path would involve reimplementing one of the builtin mex functions. If one forces a fallback to imwarp(), then you could specify a 'fillvalues' argument there without having to rewrite anything major. As a rough prototype:
% force fallback to avoid optimized path
if false %useIPP(A)
% ...
else
% ...
% fill color comes from where? should input parser be modified to support it?
% fill color must be scalar when image is single-channel
% fill color may be nonscalar when image is multi-channel
% fill color must be properly scaled to match A, regardless of class.
% if you try to simplify this with simple multiplication, bear in mind that int16 images exist
fillcolor = [1 0.7 0]; % a tuple that's properly-scaled for its own class
fillcolor = imcast(fillcolor,class(A)); % this is MIMT; IPT requires a pile of conditionals
B = imwarp(A,tform,method,'OutputView',Rout,'SmoothEdges',true,'fillvalues',fillcolor);
% ...
... and then use it as normal
% an image
inpict = imread('peppers.png');
% parameters
angle = 20;
interp = 'bilinear';
% rotate the image
outpict = imrotate(inpict,angle,interp);
If one only wanted to permanently make the padding white for all images, it would be a relatively simple modification. For anything practically flexible, it would not be a simple modification, and you may be giving up some speed to do it. Validating, collapsing/expanding, and rescaling the color parameter would be a fair volume of code using base/IPT tools. Still, this could potentially be the fastest of the three options, despite any challenges.
Basic image compositing
Basic image composition can be very easy if one isn't picky. The padding color can be anything you want.
% an image
inpict = imread('peppers.png');
% parameters
angle = 20;
interp = 'bilinear';
paddingcolor = [0.6 0.2 0.9];
% rotate both the image and a mask
outpict = imrotate(inpict,angle,interp);
mask = imrotate(ones(imsize(inpict,2)),angle,interp);
% replace the padding region
outpict = replacepixels(paddingcolor,outpict,iminv(mask),'linear');
Since this is approached as a composition task, it doesn't even have to be a solid color. It can be another image, and it's hardly any more complicated.
% replace the padding region
padpict = imresize(inpict,size(mask))/2; % pick something
outpict = replacepixels(outpict,padpict,mask,'linear');
It's not as nice as having a padding parameter available in imrotate(), but two extra lines is no mountain to climb.
The above examples use replacepixels() from MIMT, but the same can be done the hard way if you take care to accomodate potentially varied image class, scale, and depth. It's still not that much to deal with.
% replace the padding region
% this is sRGB instead of linear RGB (as prior example), requires R2016b+
% presumes input is uint8
outpict = im2double(outpict);
paddingcolor = reshape(im2double(paddingcolor),1,1,3);
outpict = outpict.*mask + paddingcolor.*(1-mask);
outpict = im2uint8(outpict);
Since nothing in this compositing approach is binarized, interpolated edges are somewhat accomodated. If using non-default interpolation, there will be some traces of black that still weight the transition, but they are difficult to notice unless both the padding and image are brightly colored. Default interpolation won't have this weighted transition.
Image blending
That's the basics, but what about that transition? The better way to do things is only slightly more complicated.
% replace the padding region
%paddingpict = colorpict(size(mask),paddingcolor); % a solid color image
paddingpict = imresize(inpict,size(mask))/2; % or any other image
paddingpict = replacepixels(0,paddingpict,mask); % fill the interior with black
outpict = imblend(paddingpict,outpict,1,'lineardodge'); % class/depth-agnostic addition
Here, instead of just compositing (alpha "blending") the image with a solid color, we're creating a colored overlay and doing purely additive blending. Now the black padding no longer weights the transition region. A white image will blend seamlessly with a white padding.
Again, this example uses MIMT tools. The same can be done with basic addition if you do all the necessary housekeeping. For the rudimentary case of white-only padding (post R2016b), this can simplify significantly.
% an image
inpict = imread('peppers.png');
% parameters
angle = 20;
interp = 'bilinear';
% rotate both the image and a mask
outpict = imrotate(inpict,angle,interp);
mask = imrotate(ones(imsize(inpict,2)),angle,interp);
% invert mask, cast/scale mask to match class of image
%mask = imcast(imcomplement(mask),class(outpict)); % while MIMT imcast() accepts a class parameter
mask = im2uint8(imcomplement(mask)); % IPT tools have to be matched manually or using some external conditional test
% replace the padding region
outpict = outpict + mask;
While using a full blending approach is flexible and still relatively concise and easy to use, it's fair to assume that this is more costly than a purpose-built rotation tool could be. Bear in mind that there's no upper limit on how costly a custom reimplementation of imrotate() could be.

Naveed Salman
Naveed Salman on 11 Nov 2023
Edited: Naveed Salman on 13 Nov 2023
I liked @mark palmer's anwer.
This is what I tried and it works well for me.
It doesn't require any m-file code. It can be written in Command line.
For white background this works
angle = 30; % Specify angle
A = imread('peppers.png'); % Specify your Image file
figure(1)
imshow(A)
B = imrotate(uint8(255*ones(size(A))),angle);
C = uint8(255*ones(size(B))) - B + imrotate(A,angle);
figure(2)
imshow(C)
If you want background of some other color you can modify it to this.
Background_color = [100 150 120]; % Specify background
angle = 30; % Specify angle
A = imread('peppers.png'); % Specify you Image file
figure(1)
imshow(A)
B = imrotate(uint8(ones(size(A))),angle);
C = uint8(ones(size(B))) - B;
C(:,:,1) = C(:,:,1)*Background_color(1);
C(:,:,2) = C(:,:,2)*Background_color(2);
C(:,:,3) = C(:,:,3)*Background_color(3);
C = C + imrotate(A,angle);
figure(2)
imshow(C)
I am sure people may have more efficient and better way of doing this, but this method is simple so I wanted to share with anyone who faces this issue.

Image Analyst
Image Analyst on 8 Jan 2020
Right now there is no option to set the color of the background that is exposed after rotation. You could make a copy of imrotate() and call it imrotateColor.m and then edit it to put in the color you want. Or you could rotate a uniform image and find the zero pixels and replace those in your actual image with the color you want. But making your own imrotate2 is easier.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!