美文网首页
Python进行高动态图像合成

Python进行高动态图像合成

作者: 学而时习之_不亦说乎 | 来源:发表于2018-01-19 04:29 被阅读223次

    数据准备

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

    曝光时间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进行高动态图像合成

          本文链接:https://www.haomeiwen.com/subject/rkvnoxtx.html