高動態(tài)范圍成像

2018-10-24 10:13 更新

今天,大多數(shù)數(shù)字圖像和成像設(shè)備每通道使用8位,從而將設(shè)備的動態(tài)范圍限制在兩個數(shù)量級(實(shí)際上為256級),而人眼可以適應(yīng)10個數(shù)量級的照明條件。當(dāng)我們拍攝現(xiàn)實(shí)世界的場景時,明亮的地區(qū)可能曝光過度,而黑暗的區(qū)域可能曝光不足,所以我們無法使用單次曝光拍攝所有細(xì)節(jié)。HDR圖像與每個通道使用更多8位(通常為32位浮點(diǎn)值)的圖像一起使用,允許更寬的動態(tài)范圍。

有不同的獲取HDR圖像的方法,但最常見的方法是使用不同曝光值拍攝的場景照片。要結(jié)合這種曝光,了解您的相機(jī)的響應(yīng)功能是有用的,并且有算法來估計它。HDR圖像混合后,必須將其轉(zhuǎn)換回8位才能在通常的顯示屏上進(jìn)行查看。這個過程叫做tonemapping。當(dāng)場景或相機(jī)的對象在拍攝之間移動時,會出現(xiàn)額外的復(fù)雜性,因?yàn)榫哂胁煌毓獾膱D像應(yīng)該被注冊和對準(zhǔn)。

在本教程中,我們將介紹如何從曝光序列生成和顯示HDR圖像。在我們的情況下,圖像已經(jīng)對齊,沒有移動的對象。我們還展示了一種稱為曝光融合的替代方法,產(chǎn)生低動態(tài)范圍圖像。HDR管道的每一步都可以使用不同的算法來實(shí)現(xiàn),所以看看參考手冊來看看。

曝光順序

高動態(tài)范圍成像

源代碼

#include <opencv2/photo.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace std;
void loadExposureSeq(String, vector<Mat>&, vector<float>&);
int main(int, char**argv)
{
    vector<Mat> images;
    vector<float> times;
    loadExposureSeq(argv[1], images, times);
    Mat response;
    Ptr<CalibrateDebevec> calibrate = createCalibrateDebevec();
    calibrate->process(images, response, times);
    Mat hdr;
    Ptr<MergeDebevec> merge_debevec = createMergeDebevec();
    merge_debevec->process(images, hdr, times, response);
    Mat ldr;
    Ptr<TonemapDurand> tonemap = createTonemapDurand(2.2f);
    tonemap->process(hdr, ldr);
    Mat fusion;
    Ptr<MergeMertens> merge_mertens = createMergeMertens();
    merge_mertens->process(images, fusion);
    imwrite("fusion.png", fusion * 255);
    imwrite("ldr.png", ldr * 255);
    imwrite("hdr.hdr", hdr);
    return 0;
}
void loadExposureSeq(String path, vector<Mat>& images, vector<float>& times)
{
    path = path + std::string("/");
    ifstream list_file((path + "list.txt").c_str());
    string name;
    float val;
    while(list_file >> name >> val) {
        Mat img = imread(path + name);
        images.push_back(img);
        times.push_back(1 / val);
    }
    list_file.close();
}

說明

  • 加載圖像和曝光時間
vector<Mat> images;
vector<float> times;
loadExposureSeq(argv[1], images, times);

首先,我們從用戶定義的文件夾加載輸入圖像和曝光時間。該文件夾應(yīng)包含包含文件名和反曝光時間的圖像和list.txt文件。

對于我們的圖像序列,列表如下:

memorial00.png 0.03125
memorial01.png 0.0625
...
memorial15.png 1024

  • 估計相機(jī)響應(yīng)

Mat response;
Ptr<CalibrateDebevec> calibrate = createCalibrateDebevec();
calibrate->process(images, response, times);

需要了解大量HDR構(gòu)建算法的相機(jī)響應(yīng)函數(shù)(CRF)。我們使用一種校準(zhǔn)算法來估計所有256個像素值的反CRF。

  • 制作HDR圖像
Mat hdr;
Ptr<MergeDebevec> merge_debevec = createMergeDebevec();
merge_debevec->process(images, hdr, times, response);

我們使用Debevec的加權(quán)方案來構(gòu)建使用上一項(xiàng)計算的響應(yīng)的HDR圖像。

  • Tonemap HDR圖像

Mat ldr;
Ptr<TonemapDurand> tonemap = createTonemapDurand(2.2f);
tonemap->process(hdr, ldr);

由于我們希望通過LDR顯示我們的結(jié)果,我們必須將我們的HDR圖像映射到保留大部分細(xì)節(jié)的8位范圍。這是噸位法的主要目標(biāo)。我們使用tonemapper進(jìn)行雙邊濾波,并將2.2設(shè)置為伽馬校正值。

  • 進(jìn)行曝光融合

Mat fusion;
Ptr<MergeMertens> merge_mertens = createMergeMertens();
merge_mertens->process(images, fusion);

如果我們不需要HDR圖像,可以選擇合并我們的曝光。該過程稱為曝光融合,并產(chǎn)生不需要伽馬校正的LDR圖像。它也不使用照片的曝光值。

  • 寫結(jié)果

imwrite("fusion.png", fusion * 255);
imwrite("ldr.png", ldr * 255);
imwrite("hdr.hdr", hdr);

現(xiàn)在是時候看結(jié)果了。請注意,HDR圖像不能以常見圖像格式存儲,因此我們將其保存到Radiance圖像(.hdr)。此外,所有HDR成像功能都會將結(jié)果返回[0,1]范圍,因此我們應(yīng)該將結(jié)果乘以255。

結(jié)果

回收圖像

高動態(tài)范圍成像

曝光融合

高動態(tài)范圍成像

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號