How to calculate the dynamic range of an RGB image

47 vues (au cours des 30 derniers jours)
Avi Patani
Avi Patani le 5 Mar 2020
Modifié(e) : DGM le 28 Nov 2022
This is the code I am using to cal. the DR of an RGB image, I divide the n*m*3 image into R,G,B components and go from there. I understand that the min value could be zero and I can set it take all the values >=2 (or 2 in case of a lower value).
But the code is doing something unexpected and I am not sure where I am going wrong.
Thank you
Avi
% Cal. the luminance value of the frame
I4 = 0.2126*R(:,:)+ 0.7152*G(:,:)+ 0.0722*B(:,:);
% Find the max and min value
Max = max(I4,[],'all');
Min = min(I4,[],'all');
% Cal the log2() values
LogMax = log2(Max);
LogMin = log2(Min);
DR = LogMax - LogMin;

Réponses (1)

DGM
DGM le 27 Nov 2022
The error occurs because you're trying to do everything with integer data.
% read an image
inpict = imread('peppers.png');
inpict = im2double(inpict); % cast to a non-integer class
% split channels
[R G B] = imsplit(inpict);
% Cal. the BT709 luma value of the frame
Y = 0.2126*R + 0.7152*G + 0.0722*B;
% Find the max and min value
ymax = max(Y,[],'all');
ymin = min(Y,[],'all');
% Cal the log2() values
LogMax = log2(ymax);
LogMin = log2(ymin);
% dynamic range of luma
DRy = LogMax - LogMin
DRy = 5.1004
  3 commentaires
Walter Roberson
Walter Roberson le 27 Nov 2022
Except when calculating with int64 or uint64, calculations with the integer classes and the same class, or integer classes and scalar doubles, are carried out "as if" the values were converted to double, then the calculation was performed, and then the result is converted to the integer class.
That does not mean that the calculations are carried out in double: the model is just "as-if" they were.
The main time you notice this in uint8 is division:
uint8(1)/uint8(2)
ans = uint8 1
How can 1/2 evaluate to 1 ? It is because it is as-if you calculated uint8( double(uint8(1)) / double(uint8(2))) which is uint8(1/2) which is uint8(0.5)... and casting a fraction to uint8 rounds.
You get the same rounding with uint8 times a fraction,
uint8(1) * (3/2)
ans = uint8 2
which is uint8(3/2) which rounds to 2. But that tends to surprise people less than the fact that you get rounding with uint8 division.
DGM
DGM le 28 Nov 2022
Modifié(e) : DGM le 28 Nov 2022
I should mention that I have no idea if the actual DR calculations are correct. I doubt it. I don't know why you'd calculate from luma. I just jumped at the obvious error.
EDIT: eh.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Images dans Help Center et File Exchange

Produits


Version

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by