Python进行高动态图像合成

数据准备

首先,我们准备三张不同曝光的图像,如下图所示。

曝光时间0.05
曝光时间0.0125
曝光时间0.003125

利用几个helper函数来从文件夹里读取图像和图像的曝光时间。

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)
    #根据曝光时间长短,对图像序列和曝光时间序列重新排序
    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图像对准。在配准的时候,首先需要找到一张曝光最好的照片作为基准照片,下面的一个函数计算照片中曝光不足和曝光过量的像素个数,把曝光不足和曝光过量像素最少的图像作为参考图像。

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进行配准,并且返回已经对其的图像序列。

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图像,首先要拟合相机响应函数(Camera Response Function,CRF),关于拟合CRF的算法,后续博客中将详细介绍,这里,我们先关注Opencv-Python的实现。

import numpy as np
import cv2
import Utility #Utility为前面函数所在的模块

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

exposTimes = np.array(exposTimes,dtype=np.float32) #需要转化为numpy浮点数组
calibrateDebevec = cv2.createCalibrateDebevec(samples=120,random=True)  
###采样点数120个,采样方式为随机,一般而言,采用点数越多,采样方式越随机,最后的CRF曲线会越加平滑
responseDebevec = calibrateDebevec.process(images, exposTimes)  #获得CRF
mergeDebevec = cv2.createMergeDebevec()
hdrDebevec = mergeDebevec.process(images, exposTimes, responseDebevec) #
# Save HDR image.
cv2.imwrite("hdrDebevec.hdr", hdrDebevec) 

你可能感兴趣的:(Python进行高动态图像合成)