How to calculate the dynamic range of an RGB image

34 ビュー (過去 30 日間)
Avi Patani
Avi Patani 2020 年 3 月 5 日
編集済み: DGM 2022 年 11 月 28 日
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;

回答 (1 件)

DGM
DGM 2022 年 11 月 27 日
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 件のコメント
Walter Roberson
Walter Roberson 2022 年 11 月 27 日
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 2022 年 11 月 28 日
編集済み: DGM 2022 年 11 月 28 日
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.

サインインしてコメントする。

製品


リリース

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by