PFM形式の画像とmiddleburyデータセットの読み取り

16669 ワード

PFM形式の画像とmiddleburyデータセットの読み取り
  • PFM形式画像
  • 画像フォーマット
  • Middlebury 2014データセット
  • データセット紹介
  • Middleburyデータ集中視差マップを読み取るdepth map
  • を生成する.
    PFM形式画像
    http://www.pauldebevec.com/Research/HDR/PFM/https://linux.die.net/man/5/pfmPFM(Portable Float Map)は、ファイル情報とファイルバイナリデータの2つの部分を含む浮動小数点画素の画像フォーマットである.
    画像フォーマット
    PFMにおけるファイル情報をヘッダと呼び,バイナリ画像データをrasterと呼ぶ.
    ヘッダーファイル情報:3行の情報が共有され、Unixスタイルの改行記号「」の16進数「0 sa」で終わる.
  • Identifier Line値は「PF」または「Pf」です.
  • 「PF」は、RGB 3チャネル画像
  • であることを示す.
  • "Pf"は、単一チャネル画像
  • であることを示す.
  • Dimensions Lineこの行は画像の行列情報(チャネルを含まない)であり、中間は
  • をスペースで隔てている.
  • Scale Factor/Endiannessスケーリングファクタ/バイト順で、この行に書き込まれた情報はグローバル浮動小数点数スケーリングファクタ値であり、正負の区別がある.正の値であれば、画像のバイナリデータは大端シーケンスで格納され、負の値は小端シーケンスで格納される(0値は存在しない).このscale factorはdepth mapを取得する場合にのみ使用され、disparity mapの値をこのscale factorで除算する必要があります.

  • raster画像データ領域:画像中の各画素値は4バイト、RGBチャネルは12バイト順に記憶され、画像の画素点読取順は下から上へ左から右の順に読み取られる.
    Middlebury 2014データセット
    http://vision.middlebury.edu/stereo/data/scenes2014/#description
    データセットの紹介
    PFM格式图像和读取middlebury 数据集_第1张图片 PFM格式图像和读取middlebury 数据集_第2张图片 PFM格式图像和读取middlebury 数据集_第3张图片
    Middleburyデータ集中視差マップを読み出してdepth mapを生成
    from pathlib import Path
    import numpy as np
    import csv
    import re
    import cv2
    
    def read_calib(calib_file_path):
        with open(calib_file_path, 'r') as calib_file:
            calib = {}
            csv_reader = csv.reader(calib_file, delimiter='=')
            for attr, value in csv_reader:
                calib.setdefault(attr, value)
    
        return calib
    
    def read_pfm(pfm_file_path):
        with open(pfm_file_path, 'rb') as pfm_file:
            header = pfm_file.readline().decode().rstrip()
            channels = 3 if header == 'PF' else 1
    
            dim_match = re.match(r'^(\d+)\s(\d+)\s$', pfm_file.readline().decode('utf-8'))
            if dim_match:
                width, height = map(int, dim_match.groups())
            else:
                raise Exception("Malformed PFM header.")
    
            scale = float(pfm_file.readline().decode().rstrip())
            if scale < 0:
                endian = ' # littel endian
                scale = -scale
            else:
                endian = '>' # big endian
    
            dispariy = np.fromfile(pfm_file, endian + 'f')
        #
        img = np.reshape(dispariy, newshape=(height, width, channels))
        img = np.flipud(img).astype('uint8')
        #
        show(img, "disparity")
    
        return dispariy, [(height, width, channels), scale]
    
    
    def create_depth_map(pfm_file_path, calib=None):
    
        dispariy, [shape,scale] = read_pfm(pfm_file_path)
    
        if calib is None:
            raise Exception("Loss calibration information.")
        else:
            fx = float(calib['cam0'].split(' ')[0].lstrip('['))
            base_line = float(calib['baseline'])
            doffs = float(calib['doffs'])
    
    		# scale factor is used here
            depth_map = fx*base_line / (dispariy / scale + doffs)
            depth_map = np.reshape(depth_map, newshape=shape)
            depth_map = np.flipud(depth_map).astype('uint8')
    
            return depth_map
    
    def show(img, win_name='image'):
        if img is None:
            raise Exception("Can't display an empty image.")
        else:
            cv2.namedWindow(win_name, cv2.WINDOW_NORMAL)
            cv2.imshow(win_name, img)
            cv2.waitKey()
            cv2.destroyWindow(win_name)
    
    
    def main():
        pfm_file_dir = Path(r'middlebury\2014\Adirondack-imperfect')
        calib_file_path = pfm_file_dir.joinpath('calib.txt')
    	disp_left = pfm_file_dir.joinpath('disp0.pfm')
    	
        # calibration information
        calib = read_calib(calib_file_path)
    	# create depth map
        depth_map_left = create_depth_map(disp_left, calib)
    
        show(depth_map_left, "depth_map")
    
    if __name__ == '__main__':
        main()
    

    結果: