Mar*_*sin 8 c++ opencv hdr unreal-engine4 opencv3.0
我目前卡在图片上的视频节目中.
问题:
我正在从UE4中提取图片,由于存在错误,在渲染截图期间并未考虑所有灯光.输出是HDR图像.我希望得到更好的亮度,因为导出的图像非常暗,就像第一次曝光一样.
使用UE4中的"曝光偏差"参数,我能够真实地获得场景的亮度,但不能将此参数应用于屏幕截图渲染:

尝试:
使用Tonemapper算法(特定cv::TonemapDrago)我能够获得更好的图像结果:

对于我的情况,Tonemap算法的主要问题是因为全局亮度根据区域的亮度而改变:在第二个图像中,窗口增加了大量的光,因此算法降低了所有亮度以调整平均值.在渲染的视频中,光线变化非常残酷.
我试图改变亮度和饱和度而没有成功.我已经修改了TonemapDrago尝试使用常量的代码来执行算法的某些步骤.
题 :
我想从HDR图像中"选择曝光时间".Tonemap基于同一图像的几个曝光时间,在我的情况下并不有趣.
欢迎任何其他想法.
编辑:
CV :: Mat深度为5,类型为CV_32FC3
cout << mat.step 给我19200
以下是我用来尝试解决问题的2个示例:
编辑2:
无法用gimp打开.HDR图片,带有"explosure blend"插件的事件.我可以使用Photoshop获得足够的结果.那背后的算法有什么想法吗?OpenCV的6个Tonemap算法中的任何一个允许选择曝光校正.

编辑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;
}
Run Code Online (Sandbox Code Playgroud)
将此算法应用于我的.HDR图片,即使对于伽玛和曝光进行1和1的校正,我也得到了非常明亮的结果:

读取代码时,有一些错误,因为1和1作为参数不应该修改图片.修正了答案的问题.非常感谢@ user3896254(Ge在评论中也看到了它)
考虑使用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;
}
Run Code Online (Sandbox Code Playgroud)