Using imrotate without losing quality

17 visualizzazioni (ultimi 30 giorni)
Milad
Milad il 12 Mar 2018
Commentato: DGM il 5 Lug 2024
I'm in a situation that I need to be able to randomly rotate (0-359 angle degrees) different images. I'm currently using imrotate() but considering that the images are small and the quality is important, I noticed that the images lose their qualities, specially in curve lines. I can still rotate my images 0, 90, 180 and 270 degrees without losing any qualities but I wanted to know if there is any way to rotate an image with more degrees without losing the quality.
  11 Commenti
Image Analyst
Image Analyst il 5 Lug 2024
Not sure what all that means. An image IS a matrix. And what do you mean by invariant? Invariant to what?
Why don't you start a new discussion thread and explain it?
If you have any more questions, then attach your data and code to read it in with the paperclip icon after you read this:

Accedi per commentare.

Risposta accettata

Milad
Milad il 13 Mar 2018
(Thanks to guys for answering and helping me with this question. To sum things up I've decided to write an answer myself.)
It seems that rotation always reduces image quality unless we allow the rotated image to be larger than the original or only use multiples of 90 degrees.
The best option in imrotate() seem to be 'bicubic'. Even without resizing the image it gives a pretty good result.
  1 Commento
DGM
DGM il 5 Lug 2024
Modificato: DGM il 5 Lug 2024
This is appropriate, but there are conceivable reasons why someone might overlook this fact or otherwise be confused to hear that it's true.
Consider the following rotation of a small test pattern
% a tiny 12x9 checkerboard
A = imread('tinycb.png'); % uint8
% rotate by 90 using two interpolation options
theta = 90;
B = imrotate(A,theta); % output is 9x12
C = imrotate(A,theta,'bilinear');
% upscale to prevent the forum display from
% doing interpolation on the tiny images
B = imresize(B,20,'nearest');
C = imresize(C,20,'nearest');
% display them side by side
montage({B,C},'border',[10 10],'backgroundcolor','m');
What if the angle were off by a small amount?
% the same tiny image
A = imread('tinycb.png');
% angle is off by the tiniest amount
theta = 90 + eps(90) % looks like 90, right?
theta = 90.0000
% rotate as before
B = imrotate(A,theta); % now the output is 10x13
C = imrotate(A,theta,'bilinear');
% upscale as before
B = imresize(B,20,'nearest');
C = imresize(C,20,'nearest');
% display them side by side
montage({B,C},'border',[10 10],'backgroundcolor','m');
% how far off was that?
format long
theta
theta =
90.000000000000014
Depending on how the angles are being obtained, it's possible to run into cases where one only assumes they're hitting 90, but aren't actually. The cause might be rounding error, or it might be as gross as an off-by-one error -- for example:
th = linspace(0,360,1001); % this will hit [0 90 180 270 360]
nnz(mod(th,90) == 0)
ans =
5
versus
th = linspace(0,360,1000); % this only hits 0 and 360
nnz(mod(th,90) == 0)
ans =
2
FWIW, in the case of 90d multiples, imrotate() internally just calls rot90(), so the interpolation options are actually circumvented.

Accedi per commentare.

Più risposte (2)

Image Analyst
Image Analyst il 12 Mar 2018
See if using the ‘nearest’ option of imresize gives you something you like better.
  2 Commenti
Milad
Milad il 13 Mar 2018
Of course I've seen your solution! Your answers are the most respected. But as I said, I don't want to use imresize(). And if you meant imrotate(), I've tried its methods too. Which still didn't give good results. I'll try the 'nearest' option of imrotate() once again to see if anything changes.
Image Analyst
Image Analyst il 13 Mar 2018
Sorry - meant imrotate(). Let me know if that's any better. Otherwise (if not) your only option is to upsample your image like they already suggested.

Accedi per commentare.


Guillaume
Guillaume il 12 Mar 2018
As per Walter's comments, the only way you can perform arbitrary rotations without loss of quality if by increasing the number of pixels in the image, so:
supersampled = imresize(yourimage, 4); %use whatever scale you which > 1. imresize uses bicubic by default which is the best.
rotatedimage = imrotate(supersampled, someangle, 'bicubic');
  6 Commenti
Image Analyst
Image Analyst il 13 Mar 2018
Did you even TRY or even see my solution (below)? If you just want the image rotated but want sharp edges, not blurry edges, then it might work. Of course you will get jaggies for certain angles, but the edges will be sharper.
Guillaume
Guillaume il 13 Mar 2018
imresize is used to upsample the image. A feature that was occupying a single pixel now occupy more. Since we use 'bicubic interpolation' you also get antialising. You now have more resolution for your feature, so you loose less quality when you rotate it.

Accedi per commentare.

Categorie

Scopri di più su Read, Write, and Modify Image in Help Center e File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by