def HDR(_imgs_nx1, _times_nx1, method=Debevec): assert _imgs_nx1.dtype == np.uint8 and _times_nx1.dtype == np.float32, "Type Error" assert len(_imgs_nx1) == len( _times_nx1) and len(_times_nx1) > 0, "Len Error" if method == Debevec: CalibrateDebevec = cv2.createCalibrateDebevec(samples=70, random=True) crf = CalibrateDebevec.process(src=_imgs_nx1, times=_times_nx1) merge_debvec = cv2.createMergeDebevec() hdr_img = merge_debvec.process(src=_imgs_nx1, times=_times_nx1, response=crf) tonemap = cv2.createTonemapDurand(gamma=1.4) res_img = tonemap.process(hdr_img.copy()) return crf, hdr_img, res_img if method == Robertson: CalibrateRobertson = cv2.createCalibrateRobertson() crf = CalibrateRobertson.process(src=_imgs_nx1, times=_times_nx1) merge_robertson = cv2.createMergeRobertson() hdr_img = merge_robertson.process(src=_imgs_nx1, times=_times_nx1, response=crf) #local tonermap tonemap = cv2.createTonemapDurand(gamma=1.4) res_img = tonemap.process(hdr_img.copy()) return crf, hdr_img, res_img if method == Mertens: merge_mertens = cv2.createMergeMertens() res_img = merge_mertens.process(_imgs_nx1) # cv2.imshow("ss", res_img) # cv2.waitKey(0) # cv2.destroyAllWindows() # res_mertens_8bit = np.clip(res_img*255, 0, 255).astype('uint8') # cv2.imwrite("PyFusion.png", res_mertens_8bit) return res_img
def process_roberston(images, exposures): calibrate_robertson = cv2.createCalibrateRobertson() response_robertson = calibrateRobertson.process(images, times=exposures) merge_robertson = cv2.createMergeRoberston() return merge_robertson.process( images, times=exposures, response=response_robertson )
hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy()) # Tonemap HDR image tonemap1 = cv.createTonemap(gamma=2.2) res_debevec = tonemap1.process(hdr_debevec.copy()) tonemap2 = cv.createTonemap(gamma=1.3) res_robertson = tonemap2.process(hdr_robertson) # Exposure fusion using Mertens merge_mertens = cv.createMergeMertens() res_mertens = merge_mertens.process(img_list) # Convert datatype to 8-bit and save res_debevec_8bit = np.clip(res_debevec * 255, 0, 255).astype('uint8') res_robertson_8bit = np.clip(res_robertson * 255, 0, 255).astype('uint8') res_mertens_8bit = np.clip(res_mertens * 255, 0, 255).astype('uint8') cv.imwrite("hdr_debevec.jpg", res_debevec_8bit) cv.imwrite("hdr_robertson.jpg", res_robertson_8bit) cv.imwrite("fusion_mertens.jpg", res_mertens_8bit) # Estimate camera response function (CRF) cal_debevec = cv.createCalibrateDebevec() crf_debevec = cal_debevec.process(img_list, times=exposure_times) hdr_debevec = merge_debevec.process(img_list, times=exposure_times.copy(), response=crf_debevec.copy()) cal_robertson = cv.createCalibrateRobertson() crf_robertson = cal_robertson.process(img_list, times=exposure_times) hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy(), response=crf_robertson.copy())
def recover_camera_response(inputFolder = '.', exposureListFile = None, outputResponseCurve = "camera_response.spi1d", outputResponseFormat = "spi1d", calibrationApproach = "berkeley", mergeExposures = False, mergedExposuresOutput = None, verbose = False, robertsonMaxIter = 30.0, robertsonThreshold = 0.01, berkeleyLambda = 20.0, berkeleySamples = 1024, berkeleySamplePlacementRandom = False): extensions = generalExtensions if exposureListFile: with open(exposureListFile, 'r') as f: exposuresList = f.readlines() exposuresList = [x.strip() for x in exposuresList if len(x) > 1] imageUris = [x.split(' ')[0] for x in exposuresList] exposure_times = [1.0/float(x.split(' ')[1]) for x in exposuresList] else: imageUris = sorted( os.listdir( inputFolder ) ) imageUris = [x for x in imageUris if (os.path.splitext(x)[-1].lower()[1:] in extensions) and (x[0] != '.')] if verbose: print( imageUris ) cwd = os.getcwd() os.chdir( inputFolder ) exposure_times = [0]*len(imageUris) for i in range(len(imageUris)): exposure_times[i] = getShutterSpeed( imageUris[i], verbose=verbose ) # List has to be sorted from longest shutter speed to shortest for opencv functions to work exposure_times, imageUris = (list(x) for x in zip(*sorted(zip(exposure_times, imageUris)))) imageUris.reverse() exposure_times.reverse() exposure_times = np.array(exposure_times, dtype=np.float32) if verbose: for exposure in zip(exposure_times, imageUris): print( "Image : %s, Shutter speed : %2.6f" % (exposure[1], exposure[0]) ) img_list = [cv2.imread(fn) for fn in imageUris ] if not exposureListFile: os.chdir( cwd ) if calibrationApproach == "robertson": merge = cv2.createMergeRobertson() calibrate = cv2.createCalibrateRobertson() calibrate.setMaxIter(robertsonMaxIter) calibrate.setThreshold(robertsonThreshold) if verbose: print( calibrationApproach ) print( "\tmax iter : %d" % robertsonMaxIter ) print( "\tthreshold : %f" % robertsonThreshold ) else: merge = cv2.createMergeDebevec() calibrate = cv2.createCalibrateDebevec() calibrate.setLambda(berkeleyLambda) calibrate.setSamples(berkeleySamples) calibrate.setRandom(berkeleySamplePlacementRandom) if verbose: print( calibrationApproach ) print( "\tlambda : %3.2f" % berkeleyLambda ) print( "\tsamples : %d" % berkeleySamples ) print( "\trandom : %s" % berkeleySamplePlacementRandom ) if verbose: print( "recovering camera response" ) curve = calibrate.process(img_list, times=exposure_times) if verbose: print( "writing camera response - %s, %s" % (outputResponseFormat, outputResponseCurve) ) if outputResponseFormat == "spi1d": with open(outputResponseCurve, "w") as f: f.write( "Version 1\n" ) f.write( "From 0.000000 1.000000\n" ) f.write( "Length 256\n" ) f.write( "Components 3\n" ) f.write( "{\n" ) for i in range(len(curve)): f.write( "%3.6f %3.6f %3.6f\n" % (curve[i][0][0]*0.18, curve[i][0][1]*0.18, curve[i][0][2]*0.18) ) f.write( "}\n" ) else: with open(outputResponseCurve, "w") as f: for i in range(len(curve)): f.write( "%3.6f %3.6f %3.6f\n" % (curve[i][0][0], curve[i][0][1], curve[i][0][2]) ) if mergedExposuresOutput: if verbose: print( "merging exposures" ) hdr = merge.process(img_list, times=exposure_times.copy(), response=curve.copy()) cv2.imwrite(mergedExposuresOutput, hdr)
tonemap1 = cv2.createTonemapDurand(gamma=2.2) res_debvec = tonemap1.process(hdr_debvec.copy()) tonemap2 = cv2.createTonemapDurand(gamma=1.3) res_robertson = tonemap2.process(hdr_robertson.copy()) # Exposure fusion using Mertens # 这里我们展示了一种可以合并曝光图像的替代算法,我们不需要曝光时间。我们也不需要使用任何tonemap算法,因为Mertens算法已经给出了[0..1]范围内的结果。 merge_mertens = cv2.createMergeMertens() res_mertens = merge_mertens.process(img_list) # Convert datatype to 8-bit and save # 为了保存或显示结果,我们需要将数据转换为[0..255]范围内的8位整数。 res_debvec_8bit = np.clip(res_debvec * 255, 0, 255).astype('uint8') res_robertson_8bit = np.clip(res_robertson * 255, 0, 255).astype('uint8') res_mertens_8bit = np.clip(res_mertens * 255, 0, 255).astype('uint8') cv2.imwrite("ldr_debvec.jpg", res_debvec_8bit) cv2.imwrite("ldr_robertson.jpg", res_robertson_8bit) cv2.imwrite("fusion_mertens.jpg", res_mertens_8bit) exit(0) # Estimate camera response function (CRF) # 相机响应功能(CRF)给出了场景辐射度与测量强度值之间的连接。如果在一些计算机视觉算法中非常重要,包括HDR算法,CRF。这里我们估计反相机响应函数并将其用于HDR合并。 cal_debvec = cv2.createCalibrateDebevec() crf_debvec = cal_debvec.process(img_list, times=exposure_times) hdr_debvec = merge_debvec.process(img_list, times=exposure_times.copy(), response=crf_debvec.copy()) cal_robertson = cv2.createCalibrateRobertson() crf_robertson = cal_robertson.process(img_list, times=exposure_times) hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy(), response=crf_robertson.copy())