Advertisement

OpenGL-----Tone Mapping

阅读量:

Problem Description:
设计一个程序以对HDR图像进行色调映射,并采用点处理和区域处理滤波器
第一种简单的色调映射方法
您将首先实现一个色调映射操作员,在其亮度的对数空间中进行伽马校正。这是点处理技术的一个典型示例。具体来说,这包括三个步骤:

  1. 首先构建图像的亮度数据。您可以使用任意合适的运算(例如YUV、xyY等)。最简单的做法是使用Lw = 1/61.0 * (20.0R + 40.0G + B)来计算每个像素的亮度值。
  2. 计算每个像素的目标亮度Ld值。为了提高效率,在对数空间中可以使用乘法代替powf()函数来完成这一过程:首先对每个像素计算log(Lw),然后计算log(Ld) = r * log(Lw),最后通过指数运算得到Ld = exp(log(Ld))。
  3. 最后,针对每个颜色通道(R、G、B)计算目标颜色Cd值:Cd = Ld/lw * C。
    原始图像:
这里写图片描述

After:
gama=0.1

这里写图片描述

Second Tone Mapping with Convolution
Section 10.2 of Szeliski describes a very simple tone mapping operator which separately processes the low-pass (B) and high-pass (S) data of the log(Lw) channel. We will build these two channels using convolution.
First, you will need to implement a convolution operator, g, that performs low-pass smoothing by doing log(Lw) ⌦ g. g can be anything you like, but I suggest using a box filter of varying sizes (even 5 * 5 will improve the tone map, but up to 2020 may do better). Later you may want to experiment with tent or Gaussian filters. The basic process you will perform, for each pixel, is the following:
1. B=log(Lw)⌦g
2. S=log(Lw)-B
3. log(Ld)=r
B+S.
4. Ld = exp(log(Ld)).
5.Cd=Ld/Lw*C
Note that Szeliski, incorrectly, multiplies S by in step 3.
Setting is this situation can be tricky to understand. In general, the idea is that you want
to preserve some contrast threshold c. On Durand’s website (near the bottom) he suggests using a , called “compression factor” set relative to the minimum and maximum of B. Specifically, = log(c)/(max(B)-min(B)). I found that c 2 [5, 100] worked well. He also suggests subtracting an absolute scale from the formulation I found that both of these changes improved my results.

复制代码
    void ContoneMap(rgba_pixel **image)//- c mode
    {
    convolve(conFilter,Lw);
    float **Ld;
     Ld = new float*[HEIGHT];
       Ld[0] = new float[WIDTH*HEIGHT];
       for (int i=1; i<HEIGHT; i++) {
     Ld[i] = Ld[i-1] + WIDTH;
       }
       S = new float*[HEIGHT];
       S[0] = new float[WIDTH*HEIGHT];
       for (int i=1; i<HEIGHT; i++) {
     S[i] = S[i-1] + WIDTH;
       }
    
       float min=10000,max=0;
       for (int row=0; row<HEIGHT; row++) {
      for (int col=0; col<WIDTH; col++) {
       if(temp_buffer[row][col]<min)min=temp_buffer[row][col];
      if(temp_buffer[row][col]>max)max=temp_buffer[row][col];
      }
    }
    cout<<max<<endl;
    cout<<min<<endl;
    
    gam=log(c)/(max-min);
    cout<<"gam= "<<gam<<endl;
    
    for (int row=0; row<HEIGHT; row++) {
      for (int col=0; col<WIDTH; col++) {
      S[row][col]=Lw[row][col]-temp_buffer[row][col];
    
      Ld[row][col]=exp(gam*(temp_buffer[row][col])+S[row][col]);
    
      image[row][col].r=image[row][col].r*Ld[row][col]/lw[row][col];
      image[row][col].g=image[row][col].g*Ld[row][col]/lw[row][col];
      image[row][col].b=image[row][col].b*Ld[row][col]/lw[row][col];
      image[row][col].a=1.0;
      //cout<<image[row][col].r<<image[row][col].g<<endl;
      }
      }  
    
    }

Using boxfilter
size 7

size 7

Using Gaussian filters

size 7

Advanced Extension
将您的基于卷积的色调映射器的行为模仿为双边滤波器的行为。其核心理念在于,在卷积过程中应用色调映射会导致边缘模糊现象(halos),这取决于你所使用的卷积窗口大小。
为了实现这一目标,请您调整您的卷积操作以生成非线性运算符。
Durand提供了多种解决方案供您参考与尝试。
该模式采用双边滤波器对色调图进行处理。每个滤波器权重的计算基于图像对数空间中像素亮度值的变化。

boxfilter

全部评论 (0)

还没有任何评论哟~