Python進行高動態(tài)圖像合成

數(shù)據(jù)準備

首先,我們準備三張不同曝光的圖像,如下圖所示。

曝光時間0.05
曝光時間0.0125
曝光時間0.003125

利用幾個helper函數(shù)來從文件夾里讀取圖像和圖像的曝光時間。

import PIL.ExifTags
from PIL import Image
import cv2
import numpy as np
from libtiff import TIFF
from os import listdir
from os.path import isfile, isdir, join

#讀取文件夾下文件
def ListFiles(FilePath):
    onlyfiles = [f for f in listdir(FilePath) if isfile(join(FilePath, f))]
    return onlyfiles

#獲得圖像文件屬性
def get_exif(fn):
    img = Image.open(fn)
    exif = {PIL.ExifTags.TAGS[k]: v
            for k, v in img._getexif().items()
            if k in PIL.ExifTags.TAGS
            }
    return exif

#獲得圖像曝光時間
def get_exposure_time(fn):
    exif = get_exif(fn)
    exposure_time = exif.get('ExposureTime')
    return exposure_time[0]/exposure_time[1]

#獲取圖像曝光時間序列和圖像
def getImageStackAndExpos(folderPath):
    files = ListFiles(folderPath)
    exposTimes = []
    imageStack = []
    for file in files:
        filePath = join(folderPath,file)
        exposTime = get_exposure_time(filePath)
        currImage = cv2.imread(filePath)
        exposTimes.append(exposTime)
        imageStack.append(currImage)
    #根據(jù)曝光時間長短,對圖像序列和曝光時間序列重新排序
    index = sorted(range(len(exposTimes)), key=lambda k: exposTimes[k])
    exposTimes = [exposTimes[i] for i in index]
    imageStack = [imageStack[i] for i in index]
    return exposTimes,imageStack

預處理

由于上面的三張圖像在拍攝的時候存在一定的抖動和位移情況,可以用SIFT算法對其配準Python進行SIFT圖像對準。在配準的時候,首先需要找到一張曝光最好的照片作為基準照片,下面的一個函數(shù)計算照片中曝光不足和曝光過量的像素個數(shù),把曝光不足和曝光過量像素最少的圖像作為參考圖像。

def getSaturNum(img):
    gray_image = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    underExpos=np.count_nonzero(gray_image==0)
    overExpos = np.count_nonzero(gray_image==255)
    return underExpos + overExpos


def getRefImage(imgStack):
    saturNum = imgStack[0].shape[0]*imgStack[0].shape[1]
    for imgIndex in np.arange(len(imgStack)):
        curImg = imgStack[imgIndex]
        curSaturNum = getSaturNum(curImg)
        print(curSaturNum)
        if curSaturNum <= saturNum:
            saturNum = curSaturNum
            refIndex = imgIndex

    return  refIndex

在獲得參考圖像以后,使用Python進行SIFT圖像對準中提供的siftImageAlignment進行配準,并且返回已經(jīng)對其的圖像序列。

def siftAlignment(imgStack,refIndex):
    refImg = imgStack[refIndex]
    outStack = []
    for index in np.arange(len(imgStack)):
        if index == refIndex:
            outStack.append(refImg)
        else:
            currImg = imgStack[index]
            outImg,_,_ = siftImageAlignment(refImg,currImg)
            outStack.append(outImg)
    return outStack

HDR合成

為了合成HDR圖像,首先要擬合相機響應函數(shù)(Camera Response Function,CRF),關于擬合CRF的算法,后續(xù)博客中將詳細介紹,這里,我們先關注Opencv-Python的實現(xiàn)。

import numpy as np
import cv2
import Utility #Utility為前面函數(shù)所在的模塊

exposTimes,images = Utility.getImageStackAndExpos('stack_alignment')
refImgIndex= Utility.getRefImage(images)
images = Utility.siftAlignment(images,refImgIndex) 

exposTimes = np.array(exposTimes,dtype=np.float32) #需要轉(zhuǎn)化為numpy浮點數(shù)組
calibrateDebevec = cv2.createCalibrateDebevec(samples=120,random=True)  
###采樣點數(shù)120個,采樣方式為隨機,一般而言,采用點數(shù)越多,采樣方式越隨機,最后的CRF曲線會越加平滑
responseDebevec = calibrateDebevec.process(images, exposTimes)  #獲得CRF
mergeDebevec = cv2.createMergeDebevec()
hdrDebevec = mergeDebevec.process(images, exposTimes, responseDebevec) #
# Save HDR image.
cv2.imwrite("hdrDebevec.hdr", hdrDebevec) 
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容