Python进行高动态图像合成

数据准备

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

利用几个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) 

猜你喜欢

转载自blog.csdn.net/weixin_34151004/article/details/87233449
今日推荐