python?使用OpenCV進行曝光融合
1 什么是曝光融合
曝光融合是一種將使用不同曝光設(shè)置拍攝的圖像合成為一張看起來像色調(diào)映射的高動態(tài)范圍(HDR)圖像的圖像的方法。當(dāng)我們使用相機拍攝照片時,每個顏色通道只有8位來表示場景的亮度。然而,我們周圍世界的亮度理論上可以從0(黑色)到幾乎無限(直視太陽)。因此,傻瓜相機或移動相機根據(jù)場景決定曝光設(shè)置,以便使用相機的動態(tài)范圍(0-255值)來表示圖像中最有趣的部分。例如,在許多相機中,使用面部檢測來查找面部并設(shè)置曝光,使得面部看起來很好。這引出了一個問題-我們可以在不同的曝光設(shè)置下拍攝多張照片并拍攝更大范圍的場景亮度嗎?答案是肯定的。傳統(tǒng)上使用HDR成像然后進行色調(diào)映射的方式。具體見上篇文章:python使用OpenCV獲取高動態(tài)范圍成像HDR
HDR成像要求我們知道精確的曝光時間。HDR圖像本身看起來很暗,看起來不太漂亮。DR圖像中的最小強度為0,但理論上沒有最大值。所以我們需要將其值映射到0到255之間,以便我們可以顯示它。將HDR圖像映射到常規(guī)的每通道8位彩色圖像的過程稱為色調(diào)映射。如您所見,組裝HDR圖像和色調(diào)映射有點麻煩。我們不能不使用HDR就使用多個圖像創(chuàng)建色調(diào)映射圖像。結(jié)果證明我們可以用曝光融合來實現(xiàn)。
2 曝光融合的原理
應(yīng)用曝光融合的步驟如下所述:
- 使用不同曝光拍攝多張圖像
首先,我們需要在不移動相機的情況下捕獲同一場景的一系列圖像。如上所示,序列中的圖像具有不同的曝光。這是通過改變相機的快門速度來實現(xiàn)的。通常,我們選擇一些曝光不足的圖像,一些曝光過度的圖像和一個正確曝光的圖像。
在“正確”曝光的圖像中,選擇快門速度(由相機或攝影師自動選擇),以便每通道8位動態(tài)范圍用于表示圖像中最有趣的部分。太暗的區(qū)域被剪切為0,而太亮的區(qū)域被飽和到255。
在曝光不足的圖像中,快門速度很快,圖像很暗。因此,圖像的8位用于捕獲亮區(qū)域,而暗區(qū)域被剪切為0。在曝光過度的圖像中,快門速度較慢,因此傳感器捕獲的光線更多,因此圖像更亮。傳感器的8位用于捕獲暗區(qū)域的強度,而亮區(qū)域飽和到255的值。大多數(shù)單反相機都有一個稱為自動曝光包圍(AEB)的功能,只需按一下按鈕,我們就可以在不同曝光下拍攝多張照片。當(dāng)我們在iPhone中使用HDR模式時,它需要三張照片(安卓可以下載超級相機這個軟件)。
圖像對齊:
即使使用三腳架獲取序列中的圖像也需要對齊,因為即使較小的相機抖動也會降低最終圖像的質(zhì)量。OpenCV提供了一種使用對齊這些圖像的簡便方法AlignMTB。該算法將所有圖像轉(zhuǎn)換為中值閾值位圖(MTB)。通過將值1分配給比中值亮度更亮的像素來計算圖像的MTB,否則為0。MTB 對曝光時間不變。因此,可以對準(zhǔn)MTB而無需我們指定曝光時間。
圖像融合:
具有不同曝光的圖像捕獲不同范圍的場景亮度。根據(jù)Tom Mertens
,Jan Kautz
和Frank Van Reeth
題為Exposure Fusion
的論文。論文見:曝光融合通過僅保留多重曝光圖像序列中的“最佳”部分來計算所需圖像。
作者提出了三個質(zhì)量指標(biāo):
1曝光良好:如果序列中的圖像中的像素接近零或接近255,則不應(yīng)使用該圖像來查找最終像素值。其值接近中間強度(128)的像素是比較合適的。
2對比度:高對比度通常意味著高品質(zhì)。因此,對于該像素,給予特定像素的對比度值高的圖像具有更高的權(quán)重。
3飽和度:類似地,更飽和的顏色更少被淘汰并且代表更高質(zhì)量的像素。因此,特定像素的飽和度高的圖像被賦予該像素的更高權(quán)重。
三種質(zhì)量度量用于創(chuàng)建權(quán)重圖 該權(quán)重圖表示
, 圖像在位置處的像素的最終強度中的貢獻
, 對權(quán)重圖
,進行歸一化,使得對于任何像素
所以所有圖像的貢獻總計為1。
結(jié)合權(quán)重圖使用以下等式組合圖像是很有效的:
其中,,是原始圖像,
, 是輸出圖像。問題在于,由于像素是從不同曝光的圖像中拍攝的,因此
使用上述等式獲得的輸出圖像將顯示許多裂縫。該論文的作者使用拉普拉斯金字塔來混合圖像。我們將在以后的文章中介紹這項技術(shù)的細節(jié)。
幸運的是使用OpenCV
,這種圖像曝光融合合并只是使用MergeMertens
該類的兩行代碼。請注意,這個名字取決于Exposure Fusion論文的第一作者Tom Mertens 。
3 代碼與結(jié)果
代碼地址:
C++:
#include "pch.h" #include <iostream> #include <opencv2/opencv.hpp> #include <vector> #include <fstream> using namespace cv; using namespace std; // Read Images void readImages(vector<Mat> &images) { int numImages = 16; static const char* filenames[] = { "image/memorial0061.jpg", "image/memorial0062.jpg", "image/memorial0063.jpg", "image/memorial0064.jpg", "image/memorial0065.jpg", "image/memorial0066.jpg", "image/memorial0067.jpg", "image/memorial0068.jpg", "image/memorial0069.jpg", "image/memorial0070.jpg", "image/memorial0071.jpg", "image/memorial0072.jpg", "image/memorial0073.jpg", "image/memorial0074.jpg", "image/memorial0075.jpg", "image/memorial0076.jpg" }; //讀圖 for (int i = 0; i < numImages; i++) { Mat im = imread(filenames[i]); images.push_back(im); } } int main() { // Read images 讀取圖像 cout << "Reading images ... " << endl; vector<Mat> images; //是否圖像映射 bool needsAlignment = true; // Read example images 讀取例子圖像 readImages(images); //needsAlignment = false; // Align input images if (needsAlignment) { cout << "Aligning images ... " << endl; Ptr<AlignMTB> alignMTB = createAlignMTB(); alignMTB->process(images, images); } else { cout << "Skipping alignment ... " << endl; } // Merge using Exposure Fusion 圖像融合 cout << "Merging using Exposure Fusion ... " << endl; Mat exposureFusion; Ptr<MergeMertens> mergeMertens = createMergeMertens(); mergeMertens->process(images, exposureFusion); // Save output image 圖像保存 cout << "Saving output ... exposure-fusion.jpg" << endl; imwrite("exposure-fusion.jpg", exposureFusion * 255); return 0; }
Python:
import cv2 import numpy as np import sys def readImagesAndTimes(): filenames = [ "image/memorial0061.jpg", "image/memorial0062.jpg", "image/memorial0063.jpg", "image/memorial0064.jpg", "image/memorial0065.jpg", "image/memorial0066.jpg", "image/memorial0067.jpg", "image/memorial0068.jpg", "image/memorial0069.jpg", "image/memorial0070.jpg", "image/memorial0071.jpg", "image/memorial0072.jpg", "image/memorial0073.jpg", "image/memorial0074.jpg", "image/memorial0075.jpg", "image/memorial0076.jpg" ] images = [] for filename in filenames: im = cv2.imread(filename) images.append(im) return images if __name__ == '__main__': # Read images print("Reading images ... ") if len(sys.argv) > 1: # Read images from the command line images = [] for filename in sys.argv[1:]: im = cv2.imread(filename) images.append(im) needsAlignment = False else : # Read example images images = readImagesAndTimes() needsAlignment = False # Align input images if needsAlignment: print("Aligning images ... ") alignMTB = cv2.createAlignMTB() alignMTB.process(images, images) else : print("Skipping alignment ... ") # Merge using Exposure Fusion print("Merging using Exposure Fusion ... "); mergeMertens = cv2.createMergeMertens() exposureFusion = mergeMertens.process(images) # Save output image print("Saving output ... exposure-fusion.jpg") cv2.imwrite("exposure-fusion.jpg", exposureFusion * 255)
本文第一張圖獲得的不同曝光的圖像,通過這種方法所得結(jié)果如下:
在輸入圖像中,我們可以獲得過度曝光圖像中光線昏暗區(qū)域和曝光不足圖像中明亮區(qū)域的細節(jié)。但是,在合并的輸出圖像中,像素在圖像的每個部分都具有明亮的細節(jié)。我們還可以在之前的帖子中看到我們用于HDR成像的圖像的這種效果。用于產(chǎn)生最終輸出的四個圖像顯示在左側(cè),輸出圖像顯示在右側(cè)。結(jié)果如下圖所示:
正如您在本文中所看到的,Exposure Fusion
允許我們在不明確計算HDR圖像的情況下實現(xiàn)類似于HDR + Tonemapping
的效果。因此,我們不需要知道每張圖像的曝光時間,但我們能夠獲得非常合理的結(jié)果。那么,為什么要費心去做HDR呢?好吧,在很多情況下,Exposure Fusion產(chǎn)生的輸出可能不符合您的喜好。沒有旋鈕可以調(diào)整以使其變得不同或更好。另一方面,HDR圖像捕獲場景的原始亮度。如果您不喜歡色調(diào)映射的HDR圖像,請嘗試使用不同的色調(diào)映射算法。總之,Exposure Fusion代表了一種權(quán)衡。在速度和不太嚴格的要求下使得算法更加靈活(例如,不需要暴露時間)
到此這篇關(guān)于python 使用OpenCV進行曝光融合的文章就介紹到這了,更多相關(guān)OpenCV曝光融合內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python?OpenCV超詳細講解調(diào)整大小與圖像操作的實現(xiàn)
- Python?OpenCV超詳細講解讀取圖像視頻和網(wǎng)絡(luò)攝像頭
- Python中使用Opencv開發(fā)停車位計數(shù)器功能
- 關(guān)于python3?opencv?圖像二值化的問題(cv2.adaptiveThreshold函數(shù))
- Python?OpenCV實現(xiàn)圖形檢測示例詳解
- Python?OpenCV實現(xiàn)3種濾鏡效果實例
- python?OpenCV?圖像通道數(shù)判斷
- 巧妙使用python?opencv庫玩轉(zhuǎn)視頻幀率
- python+opencv實現(xiàn)堆疊圖片
相關(guān)文章
淺談在django中使用redirect重定向數(shù)據(jù)傳輸?shù)膯栴}
這篇文章主要介紹了淺談在django中使用redirect重定向數(shù)據(jù)傳輸?shù)膯栴},具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03詳解Python使用apscheduler定時執(zhí)行任務(wù)
在平常的工作中幾乎有一半的功能模塊都需要定時任務(wù)來推動,例如項目中有一個定時統(tǒng)計程序,定時爬出網(wǎng)站的URL程序,定時檢測釣魚網(wǎng)站的程序等等,都涉及到了關(guān)于定時任務(wù)的問題,所以就找到了python的定時任務(wù)模塊2022-03-03Python如何統(tǒng)計大小寫字母個數(shù)和數(shù)字個數(shù)
這篇文章主要介紹了Python如何統(tǒng)計大小寫字母個數(shù)和數(shù)字個數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08使用Python和PySpark進行數(shù)據(jù)分析的實戰(zhàn)教程
數(shù)據(jù)分析是當(dāng)今信息時代中至關(guān)重要的技能之一,Python和PySpark作為強大的工具,提供了豐富的庫和功能,使得數(shù)據(jù)分析變得更加高效和靈活,在這篇文章中,我們將深入探討如何使用Python和PySpark進行數(shù)據(jù)分析,需要的朋友可以參考下2024-01-01