高动态范围(High-Dynamic Range,简称HDR),相应的,LDR(Low-Dynamic Range),也就是我们常见的8bit存储方式的图片.之前都是在介绍视频方面.但是在高动态图片(HDRI)方面也有一些少量应用, 目前常用的存储格式有三种:OpenEXR、RadianceRGBE、FloatTIFF.

OpenEXR

可以通过此文章来了解其格式介绍. 其官网可以了解更多信息.

总之, Exr格式的储存方式是使用4*16Bit RGBA来储存数据的,即是说,它使用四个通道分别为红绿蓝和alpha,每个通道占16位储存空间,每个像素占48位储存空间来储存数据。而这16位信息exr图片是这样分配的,拿出一位来表示这个数值的正负;拿出10位来储存RGBA的基本信息;拿出5位来表示曝光度。跟下面要说的.hdr图片的记录方式有些类似。只不过,我们基本的RGBA值的精度更高,有2的10次方,1024个色阶;而能表达的亮度范围却比较小一些,只有2的5次方,32个档。

RadianceRGBE与FloatTIFF

RGBE文件的扩展名为.hdr,具体信息同样参考这里。

类型                                  输出格式char programtype[16];         //#?Radiance/n#Generated by still/nfloat gamma;                      //1.0float exposure;                   //1.0字符串常量                          //FORMAT=32-bit_rle_rgbe/n/nint nWidth, int nHeight         //-Y nHeight +X nWidth/nRGBE数据与HDR FP32(RGB)相互转换公式如下:1、rgbe->FP32(RGB)如果e为0, R = G = B = 0.0,否则:R = r * 2^(e – 128 - 8);G = g * 2^(e – 128 - 8);B = b * 2^(e – 128 - 8);2、FP32(RGB) -> rgbev = max(R, G, B); 如果v < 1e-32, r = g = b = e = 0, 否则:将v用科学计算法表示成 v = m * 2 ^ n ( 0 < m < 1):r = R * m *  256.0/v; g = G * m *  256.0/v;b = B * m *  256.0/v;e = n + 128;

我们一般说HDR采用FP32,指的是HDR图象运算时候的内存数据类型,而Radiance RGBE文件采用8bit BYTE类型存储HDR数据。也就是说打开Radiance RGBE文件,要使用上面的公式1将Radiance RGBE文件的8bit BYTE文件数据转换为FP 32的HDR内存数据进行运算;保存为Radiance RGBE文件时,要使用上面的公式2将HDR的FP32内存数据转换为Radiance RGBE的8bit BYTE文件数据进行保存。同理,OpenEXR文件的读写也存在将其FP16的文件数据到HDR的 FP32图象数据的转换;而下面将要讲的Float Tiff是不需要进行数据转换,直接将HDR的FP32图象数据保存到TIFF文件中即可.Tiff文件的扩展名为.tif(.tiff),FloatTiff每个通道为FP32(32bit Float Point)类型,一共3个通道96bpp。用Tiff文件存储HDR数据,直接将HDR的FP32保存到TIFF文件中.引用自

用文字表达的可能不大明确,可以用该公式表示:

上面所述的e就是曝光通道,你可以把前面的RGB理解成某个像素的颜色,而这个E通道,可以理解成这个像素的亮度.因为E有8位,所以取值范围也是0到255;当E为128时,2的0次方为1,RGB值保持初始。当E大于128时,没大个1,RGB的亮度就会比之前亮一倍,指数上升

所以这两种图片格式的区别就很明确了。openEXR图片的精度要高于HDR图片(RGBA有1024色阶);而HDR图片的亮度范围要高于openEXR图片;但是最关键的点在这里,HDR图片不能带alpha非常不方便合成,所以摄影里用的相对多一些;而openEXR格式除了能带alpha通道以外,还可以人工置入一些我们三维软件里渲染出来的别的通道,非常适合CG工作者,来自

色调映射

HDRI文件是一种文件,扩展名是hdr或tif格式,有足够的能力保存光照信息,但不一定是全景图。Dynamic Range(动态范围)是指一个场景的最亮和最暗部分之间的相对比值。一张HDR图片,它记录了远远超出256个级别的实际场景的亮度值,超出的部分在屏幕上是显示不出来的。它比其它格式的图像有着更大亮度的数据贮存,而且它记录亮度的方式与传统的图片不同,不是用非线性的方式将亮度信息压缩到8bit或16bit的颜色空间内,而是用直接对应的方式记录亮度信息,它可以说记录了图片环境中的照明信息,因此我们可以使用这种图象来“照亮”场景.

由于大部分显示设备仍然使用最高100nit的显示亮度,由此上面提到的将超出256个亮度级别的实际场景使用普通显示设备进行显示前,需要进行了一些亮度色度等方面信息的转换,将高动态图片映射成地动态图片.这个过程就是色调映射.但需要明确的是, 并不一定是HDR-LDR转换.由于当前HDR定义太过广泛,比如说现在大部分能够显示HDR的设备大部分最高支持1000nit,但是拍摄时的光的信息有可能超过1000, 比如说是2000,但这仍属于HDR标准范围. 因此, 不同所谓的HDR标准之间的映射也是色调映射.

现在的色调映射算法通常都遵循着一种算法设计流水线。现在的大多数算法的不同,也只是体现在流水线中不同步骤的实现方式存在差异,或者额外添加了一些新的限制,但是算法的主要部分,依然遵循着这样一种流水线.

这个流水线接收 HDR 图像,输出 LDR 图像。首先,先对输入的 HDR 图像进行预处理,主要包括测算图像的亮度信息,并将亮度信息转换到对数域。接着,处理后的图像通过边缘保留滤波器(例如双边,三边,金字塔型滤波器),提取出图像的亮度信息,也就是图中的 base layer。然后从处理后的图像中减去 base layer,就可以得到 detail layer,也就是图像的边缘信息,或者称之为图像细节。也就是说,第二步操作,将图像的亮度信息与图像细节分开,以供后续步骤进行不同的操作。再之后,第三步,提取出的亮度信息通过不同的 tone curve(色调曲线)进行压缩,或称之为映射,进而映射到 LDR 图像的亮度域之中。最后,将新的,映射后的亮度与之前提取出的 detail layer 叠加,并通过前一节提到的方式,将图像的颜色还原添加,就得到了最终的 LDR 图像.

有一种称为快速双边滤波算法的色调映射,其过程大致为:

第一步是将 HDR 图像分解为亮度分量和色度分量,此时用双边滤波器对对数域内的亮度进行滤波,并通过亮度与滤波后的商来计算细节层,滤波后的亮度随后使用一个全局算法进行色调映射。最后,将色调映射的基本层、细节层和色度分量重组,形成色调映射的最终结果.通过这个步骤发现其色度分量没有进行色调映射,主要是在亮度分量上运用了色调映射公式.

               基于快速双边滤波的色调映射算法

HDR-SDR这种向下的映射一般可以分为全局映射和局部映射.全局映射的结果就是在同一幅内相同像素点的值肯定都是相同的,而局部映射不一定.一般全局映射过程比较简单,有根据某个公式,然后将像素点带入即可,其余的还有直方图理论的映射或根据某种视觉适应模型的映射.局部色调映射相对比较麻烦一些,有的为保持局部的对比度的方法,这是空间不均匀缩放方法的一种.其他的局部色调映射还可能用到写摄影学色调重现的原理来调整局部色调因子.除了上述两种方法外,还可以从频域的方法进行入手来进行色调映射

动态范围

一直再说高动态范围,那么到底是什么动态范围.平时生活中,我们使用手机相机进行照相,当手指点击某个部分意味着在这里聚焦.如果这里比较亮,那么点击这里进行对焦后,其他部分或者图像整体部分就会变暗. 相应的,如果点击比较暗的地方,那么明亮的地方就会显得过曝,这种现象在背景里面有太阳这种比较亮的发光体特别容易出现. 这就是由于相机的动态范围有限造成的.

动态范围,简单理解就是从最亮到最暗所能识别的范围,为什么人眼能清楚识别出背景和人脸,而相机要么看清楚背景,要么看清楚人脸,就是因为人眼的动态范围比相机更加广。这样说好像有点抽象,那我们就把它量化,我们假设,人眼的动态范围为20级,而相机的动态范围为10级,以这张图为例

人的眼睛,从最亮的白到最暗的黑,全部都能识别出来共20级,而相机的识别范围只有10级,这样会导致什么后果。是的,假如相机想要识别到最亮的地方(数值1),由于相机的动态范围只有10级,从亮到暗只能识别10格,所以他最暗的地方只能识别到数值10。低于10的地方,拥有更多高动态范围的人眼让能分辨出亮和黑的层次,但是相机只能统一处理为黑色. 同理,假如相机要识别到最暗的地方(数值20),由于相机的动态范围只有10级,所以他最亮的地方只能识别到数值11.小于11的地方为全白.假如一块石头的亮度都是大于10的,那么照出来的效果这里就是全白.过曝的情况下无法分辨物体.

由此,我们想出,如何拍出更高动态范围的照片的,目前常使用的两种办法就是,第一,使用能够拍摄HDR相机的设备,他拥有足够的高动态范围能力. 第二就是多张照片合成,多次曝光不同范围的聚焦,最终用某些方法进行合成.

如何打开

由于HDR屏幕占有量确实很少,很多软件主要功能并不是查看的功能,而是一种色调映射的功能,然后保存成普通的png图片.更确切的应当称他们为工具. 所以当前市面上能够打开这一类图片的除了主流的ps以外,搜集了一些其他能够打开.hdr文件的软件.

LuminanceHDR,也可以进入官网下载AppImage的形式, .AppImage的后缀文件不需要在进行相应的依赖配置.   双击即可运行软件. 如果双击无反应,点击该文件的属性,权限位置的"执行"位置点对号.  如果需要将该程序添加到程序列表.可以制作一个.desktop文件.

这个软件就应当是一个色调映射的软件,提供了不同的映射曲线

XnView MP, 是一个图像查看软件,可以打开多种图像格式.外国的软件以商业性质使用是收费的,但是个人的是免费.并且提供了主流的windows, Mac以及Linux三个版本

HDR Shop只提供了window版本.不过据了解,现在支持HDR硬件配置的也只有window ,而且必须是win10,

OpenHDR Viewer 提供了一个在线观看HDR文件,并且快速调整色调映射.可以看到曝光度不同的效果.

各个平台能够打开.hdr图片的列表.可谓是想当广泛

HDR File Format: How to Open .HDR Files |File Opener

上面提到的几个平台软件,对各种hdr图片格式的支持存在不一样,有的只支持exr后者.hdr,这个看选择的那款软件.

格式转换

这里主要是记录一下YUV<->RGB之间的互转.首先来说一下经常看到的YUV与YCbCr的关系, 在某种程度上他们表达的意思是一样,但是另一方面YCbCr主要是YUV经过缩放和偏移的翻版(或者成为量化后版本),如何区分呢?一般, 在完全黑画面的时候打印出图像的Y数据, 如果Y=16左右    说明Y经过量化 ,如果Y=0左右   说明Y未经过量化.他是在BT.601色域标准上YUV建议使用的表达方式.引用这里的一句话为:YCbCr is a scaled and offset version of the YUV color space. Y has an 8-bit range from 16 to 235. Cb and Cr have a range of 16-240. YCbCr is used for JPEG compression.

If the RGB data has a range of 0-255 (black-white), as is commonly found in PCs, the following equations should be used to maintain the correct black and white levels,BT.601下的YCbCr与RGB相互转换。

换一个说法,可以把YUV称为full range,而YCbCr称为legal range。其他几种叫法是等价的:legal range=video range=limited range=safe range,full range=data range=computer range。那么为什么会产生这种状况,可以参考这里,传送门一,以及对full range的详解.另外,对于常用的yuv420格式,I420表示着Y是analog(YCbCr),J420表示着Y是digital(YUV)。

在不同色域空间上YUV<->RGB的空间转换也存在系数的不同,可以总结为如下,注意这里用的是YUV,是full range:

Y  = a * R + b * G + c * B
Cb = (B - Y) / d
Cr = (R - Y) / e
BT.601 BT.709 BT.2020
a 0.299 0.2126 0.2627
b 0.587 0.7152 0.6780
c 0.114 0.0722 0.0593
d 1.772 1.8556 1.8814
e 1.402 1.5748 1.4747
R = Y + e * Cr
G = Y - (a * e / b) * Cr - (c * d / b) * Cb
B = Y + d * Cb

如果这种方程式看的不太舒服也可以有矩阵形式(参考文献不同,系数有所不同):

BT.601标准:

BT.709

需要注意的是,一般在使用YUV(full range)中,其范围为Y:[0-1],U:[-0.5,0.5],V:[-0.5,0.5].那么使用上面的RGB-YUV转换时需要注意值的取值范围(rgb的输出0-1)。而YCbCr则是Y:[16,235],CbCr:[16-240],RGB的输出为[16-235].

而上面的集中标准下给出的都是YUV。如果只是知道YCbCr则是不适用上表给的公式的。但是如果有YUV-YCbCr之间的转换公式,则通过其中一种就可以推出另外一种。通过ITU-R BT.2020-2,可以看出:

上图中的公式在BT.709依然适用的,只是n的取值换成8即可。INT取整内的R'G'B'可以看成full range内的取值。,, 看成是YUV即可。

假如我有一个YCbCr下的值,在BT.709的标准下,实现YUV-RGB的Python代码:

def YUV2RGB_bt709(Y,U,V):Cb = UCr = VY = (Y - 16)/219Cb = (Cb - 128)/224Cr = (Cr - 128)/224R = Y + e_709 * CrG = Y - (a_709 * e_709 / b_709) * Cr - (c_709 * d_709 / b_709) * CbB = Y + d_709 * CbR = R * 255G = G * 255B = B * 255return R,G,B

里面的参数在上述表中的abcde对应,只是加了_709.

在其他参考的代码中,特别是C语言,会经常看到stride和plane。这两个的意思分别为:

stride:指在内存中每行像素所占的空间。如下图所示,为了实现内存对齐(或者其它的什么原因),每行像素在内存中所占的空间并不是图像的宽度。

plane:一般是以luma plane、chroma plane的形式出现,其实就是luma层和chroma层,就像RGB,要用三个plane来存

HDR视频的色调映射

这里主要是记录一下ffmpeg的几种转换方法来实现HDR-SDR的向下转换.

ffmpeg中提供的例子:

ffmpeg -i INPUT -vf zscale=transfer=linear,tonemap=clip,zscale=transfer=bt709,format=yuv420p OUTPUT

这里用到了四个参数.并且多次用到了zscale.在早期版本的ffmpeg中,默认是没有zscale的.如果需要将其编译进去需要下载ffmpeg的源码,自己进行编译.

常用的或者说比较全的命令可以参考这个:

zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=2,zscale=t=bt709:m=bt709:r=tv,format=yuv420p

一般在进行编译的时候继续如下步骤:

./configure; make; makeinstall

这种是默认configure文件的编译选项.编出来的ffmpeg缺少很多功能. 但是在linux中,我们可以使用apt-get install ffmpeg方式来安装.通过这种安装方法是对configure进行配置的.通过命令ffmpeg -version查看版本信息时可以看到:

configuration: --extra-libs=-ldl --prefix=/opt/ffmpeg --disable-debug --enable-nonfree --enable-gpl --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb --disable-decoder=amrnb --disable-decoder=amrwb --enable-libpulse --enable-libfreetype --enable-gnutls --enable-libdav1d --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-libvorbis --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libspeex --enable-libass --enable-avisynth --enable-libsoxr --enable-libxvid --enable-libvidstab --enable-libtheora --enable-libwavpack --enable-libopenjpeg --enable-libgsm --enable-nvenc --enable-libzimg --enable-libaom

--enable-libzimg   该选项即使zscale的配置开关.

一般最新的apt install 的安装方式已经等到目的.但是也可以自定义configure的方式安装.比如 你只需要打开--enable-libzimg,即可按照一下步骤:./configure  --enable-libzimg ; make; makeinstall. 这种编出来的ffmpeg连x264这样的编码器都没有的.因为这配置文件里面该编码器是关闭的.

通过ffmpeg的介绍,我们都能够大致了解这四个参数的意义.这里需要提醒的就是这四个参数表示这四个步骤:

首先,

zscale=transfer=linear

这个是将颜色空间通过线性空间进行转换.其实就是一个电光转换(EOTF).将电信号转换成光信号,这里的光信号可以看成是自然界中光线信息.因此称之为线性的.在进行接下来的tonemapping中,必须转换到线性空间.

zscale=p=bt709

该部分是色域映射,对于HDR2SDR,一般都是bt2020->bt709的过程。应当注意的是,这里经过上面的transfer:电光转换函数后是线性光了。可以从这里得到色域映射的矩阵参数。

tonemap=clip

这个即是色调映射的过程.这里是列举clip的方式,还有linear,gamma,hable等几种方式,都可以通过里面的信息找到.

tonemap参数除了有几种方法选择,也还有结果参数可以进行设置。例如,tonemap=hable:desat=3.0

其他的参数还有param,peak。这里param对个别tonemap方法有效,比如说gamma,即tonemap=gamma时配置param的数值才有效。并且不同的色调映射方法,其默认值也不同。

desat的参数是对超过某一亮度的高光进行去饱和度。由于是超过的部分才做,同一张图,desat的值越大,意味着做去饱和度的部分越少,因此,值越大,转出来的图像的饱和度越大。此参数的设置导致超出SDR颜色范围的图像信息减少,但是,也使得图像显得更加自然。

peak参数,直接翻译ffmpeg的说明:用该值覆盖信号/标称/参考峰值。当显示元数据中嵌入的峰值信息不可靠或色调从较低范围映射到较高范围时非常有用。一般的转换,其值为10.0,该值是使用hable时,不设置peak参数和设置peak=10.0时的结果一样得出。

zscale=transfer=bt709

这里是一个光电转换函数的运用.即OETF. 由于SDR下的标准比较统一,因此在bt.709标准下可以找到.

format=yuv420p

这个是制定输出文件的格式,如果不对其进行添加的话,转出来的会使源一样的格式.比如说,hdr是10bit编码,但是在709空间下,用8bit完全够用.但是这里不对其进行format指明,转出来的会使10bit.

hable

经过测试,发现hable的色调映射算法还是最好的。通过源码也可以发现其函数是:

static float hable(float in)
{float a = 0.15f, b = 0.50f, c = 0.10f, d = 0.20f, e = 0.02f, f = 0.30f;return (in * (in * a + b * c) + d * e) / (in * (in * a + b) + d * f) - e / f;
}

在ffmpeg里面,都是按照线性光rgb中最亮的那个通道进行habel映射。然后进行归一话,使值都在0-1的范围。归一话的方式就是除以hable(peak)。peak是最高亮度。

这里主要想介绍的是,hable的曲线有点类似与脚的形状(S曲线),有脚趾ton(s曲线的左下角),脚背等,hable中的参数控制着脚趾脚背的形状。在博客中引出了其意义,并且peak换成了white point的概念。

A = Shoulder Strength
B = Linear Strength
C = Linear Angle
D = Toe Strength
E = Toe Numerator
F = Toe Denominator
Note: E/F = Toe Angle
LinearWhite = Linear White Point Value
F(x) = ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F)) - E/F;
FinalColor = F(LinearColor)/F(LinearWhite)‏  

看其实例发现,这里是float3类型,意味着分别对rgb三通道进行hable映射,而不是ffmpeg内部的rgb最大值进行hable映射,然后进行原始rgb的缩放。

HDR图片以及色调映射(ToneMapping)相关推荐

  1. 色调映射 (Tonemapping)

    色调映射 (Tonemapping) 色调映射 (Tonemapping) 通常可理解为将颜色值从 HDR(高动态范围)映射到 LDR(低动态范围)的过程.在 Unity 中,这对于大多数平台意味着, ...

  2. HDR视频中的色调映射算法对比(论文摘要)

    A comparative review of tone-mapping algorithms for high dynamic range video. EUROGRAPHICS 2017 G. E ...

  3. HDR 色调映射线性压缩(matlab)

    HDR 色调映射线性压缩(matlab) 目录 HDR 色调映射学习(matlab) 1.介绍 2.matlab在HDR上的应用 参考文章: 1.介绍 即使在引入数码相机之后,多年来,专业摄影师还是更 ...

  4. HDR技术之带参数估计的经典Reinhard色调映射算法的改进(嵌入了亮度均衡/暗光增强算法)

    上一篇博客已经贴出了带参数估计的经典Reinhard色调映射算法的代码.不过需注意的是,论文中是根据反映HDR图像动态范围的Zone数自动选择是采用全局映射还是局部映射.局部色调映射可以显著提升图像对 ...

  5. Chapter4、色调映射的一般方法

    因为这本书对具体方案的原理并不细说,只提了有哪些方法和有哪些效果,类似于综述.因此,我以后也按照综述的方法来写,不细说原理了. 4.1.色调映射的一种一般方法 4.1.1.建模一种通用的色调映射算子 ...

  6. 一种基于视神经网络的高动态范围(HDR)图像自适应局部色调映射的实现【OpenCV】【CUDA】

    原理是基于这篇论文--<Adaptive Local Tone Mapping Based on Retinex for High Dynamic Range Images> 论文提出的背 ...

  7. OpenGL HDR色调映射的实例

    OpenGL HDR色调映射 先上图,再解答. 正常显示 按下M键 完整主要的源代码 源代码剖析 先上图,再解答. 正常显示 按下M键 完整主要的源代码 #

  8. HDR视频色调映射算法(之三:Block matching TMO)

    本文是HDR视频色调映射算法系列之三,Block matching TMO算法介绍. 关注公众号,获取更多信息!

  9. HDR视频色调映射算法(之六:Real-time automatic TMO)

    本文是HDR视频色调映射算法系列之六,Real-time automatic TMO算法介绍. 关注公众号,获取更多信息!

最新文章

  1. LeetCode-334. Increasing Triplet Subsequence
  2. 软件测试中排错的基本方法
  3. c++矩阵转置_C语言:数据结构-稀疏矩阵的压缩存储
  4. mysql数据库常用字段类型_快速了解MySQL数据库常用字段类型
  5. Android.mk用法详解
  6. CSV大文件的处理(以ngsim数据为例):分割、导入与合并
  7. r导出html怎么保存,做植物谱系图,用Phylomatic软件将网页中的输出结果拷贝到文本文件中, 并另存为phylo...
  8. ubuntu16.04使用sudo apt-get autoremove导致系统崩溃的解决办法
  9. 20175126《Java程序设计》第四周学习总结
  10. 18.7 修改IP地址
  11. Visual C++ 冒险游戏程序设计
  12. 使用Flash地图控件AnyMap创建Dashboard Drilldown Maps
  13. 基于netty框架的JTT808/JTT905/JTT1078协议客户端
  14. JS事件 内容选中事件(onselect)选中事件,当文本框或者文本域中的文字被选中时,触发onselect事件,同时调用的程序就会被执行。...
  15. 正则表达式 re sys os random time 模块
  16. 已解决vue-router4路由报“[Vue Router warn]: No match found for location with path“
  17. Taro下拉刷新,上拉加载更多
  18. Unable to load class named
  19. Java8中Optional的基础使用和实践
  20. Casbin之ABAC

热门文章

  1. Java读取更新.ini文件(三)
  2. 在代码的cmake时遇到Could NOT find Qt5Svg (missing: Qt5Svg_DIR)
  3. Bost asio库与线程池的使用
  4. 拯救者 linux 显卡驱动,[Deepin v20]拯救者Y7000 2019 PG0 安装NVIDIA驱动
  5. 计算机开机慢的原因及解决方法,为什么电脑开机很慢?电脑开机很慢原因以及处理方法...
  6. Java通过file的API实现命令行dir文件夹的功能
  7. openwrt-智能路由器hack技术(网路信息监控和窃取)
  8. 22-CMS前端页面查询开发-Api调用-跨域解决
  9. 福禄克测试中的电阻参数:LOOP、PAIR UBL、P2P UBL代表什么?
  10. android 手机不能发短信