从HDR图像

时间:2015-12-14 23:18:19

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

我目前正停留在图片上的视频节目中。

问题:

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

enter image description here

使用"曝光偏差" UE4中的参数能够实现我场景的真实亮度,但不能将此参数应用于屏幕截图渲染: enter image description here

尝试:

使用Tonemapper算法(特别是cv::TonemapDrago)我能够获得更好的图像效果: enter image description here

对于我的情况,Tonemap算法的主要问题是因为全局亮度根据区域的亮度而改变:在第二个图像中,窗口增加了很多光,因此算法降低了所有亮度以调整意思。 在渲染的视频中,光线变化非常残酷。

我试图改变brightness并且饱和但没有成功。 我已经修改了TonemapDrago的代码,试图为算法的某些steps使用常量。

问题:

我想"选择曝光时间"来自HDR图像。 Tonemap基于同一图像的几个曝光时间,在我的情况下并不有趣。

欢迎任何其他想法。

修改

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

cout << mat.step给我19200

以下是我用来尝试解决问题的2个样本:

First Image

Image with light window

编辑2:

无法使用gimp打开.HDR图片,使用&#34; explosure混合&#34;插入。 我能够使用Photoshop获得足够的结果。那背后的算法有什么想法吗? OpenCV的6个Tonemap算法中的任何一个允许选择曝光校正。 enter image description here

编辑3:

我已经按照这个tuto中的算法解释了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: enter image description here

读取代码时,有一些错误,因为1和1作为参数不应该修改图片。 修正了答案的问题。非常感谢@ user3896254(Ge在评论中也看到了它)

3 个答案:

答案 0 :(得分:2)

考虑使用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): enter image description here enter image description here 注意地板颜色,窗口中的天空和用这种方法保留的淡黄色光。

以下是完整代码:

#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;
}

答案 1 :(得分:0)

您目前使用什么样的场景照明?看起来你正在使用灯泡所在的点光源,但它们不够亮。在你未渲染的场景中,场景将达到全亮度。在你渲染的场景中,你会变黑。

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

答案 2 :(得分:0)

(string)$productCollection->getSelect(); 

此算法是Tonemapper,试图模拟HDR中的曝光偏差 如果你想在openCv 3.0中使用它,不要忘记打开-1作为imread的最后一个参数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; }

enter image description here