【问题标题】:Choose luminosity (exposure) from HDR image从 HDR 图像中选择亮度(曝光)
【发布时间】:2016-03-20 14:29:57
【问题描述】:

我目前被困在图片视频项目上。

问题:

我正在从 UE4 中提取图片,由于一个错误,在屏幕截图的渲染过程中并未考虑所有灯光。 输出是 HDR 图像。我想得到更好的亮度,因为导出的图片很暗,就像第一次曝光一样。

使用 UE4 中的“曝光偏差”参数,我可以使我的场景具有良好的亮度,但不能将此参数应用于屏幕截图渲染:

尝试:

使用 Tonemapper 算法(特别是 cv::TonemapDrago)我可以获得更好的图像效果:

就我而言,色调映射算法的主要问题是因为全局亮度会根据区域的亮度而改变:在第二张图像中,窗口添加了大量光线,因此算法会降低所有亮度以调整意思是。 在渲染的视频中,光线变化非常残酷。

我尝试更改 brightness 和饱和度但没有成功。 我已经修改了TonemapDrago 的代码,试图对算法的一些steps 使用常量。

问题:

我想从 HDR 图像中“选择曝光时间”。 Tonemap 基于同一图像的多个曝光时间,在我的情况下并不有趣。

欢迎任何其他想法。

编辑

CV::Mat 深度为 5,类型为 CV_32FC3

cout << mat.step给我19200

这是我用来解决问题的 2 个示例:

First Image

Image with light window

编辑 2:

无法使用 gimp 打开 .HDR 图片,使用“explosure blend”插件打开事件。 我能够使用 Photoshop 获得足够好的结果。知道背后的算法吗? OpenCV 的 6 个 Tonemap 算法中的任何一个都允许选择曝光校正。

编辑 3:

我已经按照tuto for openGL 中的算法解释,将这个 C+ 代码提供给我:

cv::Mat exposureTonemap (cv::Mat m, float gamma = 2.2, float exposure = 1)
{
  // Exposure tone mapping
  cv::Mat exp;
  cv::exp( (-m) * exposure, exp );

  cv::Mat mapped = cv::Vec3f(1.0) - exp;
  // Gamma correction 
  cv::pow(exp, 1.0f / gamma, exp);

  cv::imshow("exposure tonemap", exp );
  cv::waitKey();

  return exp;
}

在我的 .HDR 图片上应用这个算法,即使对伽马和曝光进行了 1 和 1 的校正,我也得到了非常明亮的结果:

阅读代码,有问题,因为 1 和 1 作为参数不应该修改图片。 解决了这个问题,答案已发布。非常感谢@user3896254(Ge 在评论中也看到了)

【问题讨论】:

  • 输出图像是什么格式的?如果它没有足够的位深度,您可能无法恢复丢失的数据。
  • @MarkRansom opencv打开的.hdr图片像素格式为CV_32FC3
  • 如果您在某处上传此图片的示例 - 我们会更容易为您提供帮助。您可以将原始图像缓冲区转储为二进制文件并说出图像分辨率以允许其他人使用它。
  • @user3896254 :完成,我添加了链接,我想比写下二进制文件更容易。我正在阅读并尝试您的答案
  • 关于你添加的色调映射代码 - 你应该做 v::pow(mapped, 1.0f / gamma, exp);而不是 cv::pow(exp, 1.0f / gamma, exp);

标签: c++ opencv opencv3.0 unreal-engine4 hdr


【解决方案1】:

考虑使用Retinex。它使用单个图像作为输入,并且包含在 GIMP 中,因此很容易玩弄,除了你可以获得它的源代码(或者你自己的,这很简单)。由于您有渲染而不是照片 - 没有噪点,理论上您可以根据需要调整颜色。

但正如@mark-ransom 所说,您可能无法从渲染输出中恢复信息。你说你有 HDR 图像作为渲染输出,但我不确定你的意思。它是单个 RGB 图像吗?每个通道的颜色深度是多少?我曾尝试将 retinex 应用于您的样本,但显然它看起来不太好,因为压缩和保存前应用的范围有限。如果您的输出具有高范围且未压缩 - 您将获得更好的结果。

编辑:我在您的输入上尝试了 retinex,结果不是很好 - 图像的明亮部分(灯/窗户)在它们周围引入了丑陋的暗光晕。

在这种情况下,简单的色调映射和伽马校正看起来要好得多。您的代码几乎没问题,只是有一点错字: 而不是cv::pow(exp, 1.0f / gamma, exp); 你应该有v::pow(mapped, 1.0f / gamma, exp);

我弄乱了您的代码,并注意到这种色调映射似乎会降低色彩饱和度。为了克服这个问题,我只在 HSV 图像的 V 通道上执行它。自己比较结果(左 - 全空间色调映射,右 - 仅 V): 注意用这种方法保存的地板颜色、窗外的天空和淡黄色的浅色。

为了完整起见,这里是完整的代码:

#include <opencv2/opencv.hpp>

using namespace cv;

Mat1f exposureTonemap (Mat1f m, float gamma = 2.2, float exposure = 1) {
  // Exposure tone mapping
  Mat1f exp;
  cv::exp( (-m) * exposure, exp );
  Mat1f mapped = 1.0f - exp;

  // Gamma correction
  cv::pow(mapped, 1.0f / gamma, mapped);

  return mapped;
}

Mat3f hsvExposureTonemap(Mat &a) {
  Mat3f hsvComb;
  cvtColor(a, hsvComb, COLOR_RGB2HSV);

  Mat1f hsv[3];
  split(hsvComb, hsv);

  hsv[2] = exposureTonemap(hsv[2], 2.2, 10);

  merge(hsv, 3, hsvComb);

  Mat rgb;
  cvtColor(hsvComb, rgb, COLOR_HSV2RGB);

  return rgb;
}

int main() {
  Mat a = imread("first.HDR", -1);
  Mat b = imread("withwindow.HDR", -1);

  imshow("a", hsvExposureTonemap(a));
  imshow("b", hsvExposureTonemap(b));
  waitKey();

  return 0;
}

【讨论】:

  • 太好了,HSV 图片中“值”上的色调映射提供了更好的结果。感谢您的修复!
【解决方案2】:

您目前使用哪种场景照明?看起来您在灯泡所在的位置使用点光源,但它们不够亮。在您未渲染的场景中,场景将是全亮度的。在您渲染的场景中,您将获得黑暗。

我可能会推荐至少一个最小的天光,这样你的场景中总是有一些光线(除非你有真正的黑暗区域)

【讨论】:

  • 这个bug的问题是在UE的360度渲染中没有采用一些氛围灯和点光源。添加更亮的天空盒将增加来自窗口的光线,并且色调映射器算法将随着相机的移动而变得更加残酷。即使这样,提取的图片也会太暗而无法“按原样”使用
【解决方案3】:
cv::Mat exposureTonemap (cv::Mat m, float gamma = 2.2, float exposure = 1)
{
  // Exposure tone mapping
  cv::Mat exp;
  cv::exp( (-m) * exposure, exp );
  cv::Mat mapped = cv::Scalar(1.0f, 1.0f, 1.0f) - exp;

  // Gamma correction 
  cv::pow(mapped, 1.0f / gamma, mapped);

  /*
  cv::imshow("exposure tonemap", mapped );
  cv::waitKey();
  */

  return mapped;
}

这个算法是一个色调映射器,试图在 HDR 中模拟曝光偏差 如果你想在 openCv 3.0 中使用它,别忘了用 -1 作为 imread cv::Mat img = cv::imread("mypicture.HDR", -1);的最后一个参数打开

【讨论】:

    猜你喜欢
    • 2020-08-29
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多