PFM格式图像和读取middlebury 数据集

PFM格式图像和读取middlebury 数据集

  • PFM格式图像
    • 图像格式
  • Middlebury 2014数据集
    • 数据集介绍
    • 读取Middlebury数据集中视差图生成depth map

PFM格式图像

http://www.pauldebevec.com/Research/HDR/PFM/
https://linux.die.net/man/5/pfm
PFM (Portable Float Map),是一种浮点像素的图像格式,包含文件信息和文件二进制数据两部分内容。

图像格式

PFM中的文件信息称为header,二进制图像数据称为raster。

header 文件信息:
共有三行信息,并且以Unix风格的换行符“\n”的十六进制“0x0a”结尾。

  • Identifier Line
    值为“PF”或者“Pf”。
    • “PF”,说明是RGB三通道图像
    • “Pf”,说明是单通道图像
  • Dimensions Line
    此行是图像的行列信息(不包含通道),中间以空格隔开
  • Scale Factor / Endianness
    缩放因子/字节顺序,该行写入的信息是全局浮点数缩放因子值,有正负之分。
    如果是正值,说明图像的二进制数据是以大端序列存储,负值则为小端序列存储(不存在0值)。
    只有获取depth map时才用到这个scale factor,需要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()

结果:

你可能感兴趣的:(3D视觉)