├── README.md ├── convert2hdf5.py ├── file_io.py ├── requirements.txt ├── util.py └── visualize_scenes.py /README.md: -------------------------------------------------------------------------------- 1 | 2 | Collection of support scripts to read/write/process light field data. 3 | 4 | Please don't hesitate to contact us for any kind of questions, feedback, wishes, or bug reports. 5 | 6 | # Importing the light field data 7 | 8 | You may use the provided Python scripts to read light fields, parameter files, disparity maps and depth maps as follows: 9 | 10 | ```python 11 | import file_io.py 12 | data_folder = "some_path/training/dino" 13 | 14 | LF = file_io.read_lightfield(data_folder) 15 | param_dict = file_io.read_parameters(data_folder) 16 | depth_map = file_io.read_depth(data_folder, highres=True) 17 | disparity_map = file_io.read_disparity(data_folder, highres=False) 18 | ``` 19 | 20 | Note that there are no public depth or disparity maps for the test scenes. 21 | 22 | 23 | # General file io for PFM files 24 | 25 | You may use the general IO methods `read_pfm()` and `write_pfm()` to process single channel PFM files such as the provided disparity maps. Call `write_pfm(disp_map, file_path)` to save your algorithm results. 26 | 27 | 28 | # Creating visualizations and converting to hdf5 29 | 30 | You may use our scripts to create figures or convert the data to hdf5. 31 | We assume that the data and the scripts are placed in the same directory: 32 | ```javascript 33 | |-- visualize_scenes.py 34 | |-- convert2hdf5.py 35 | |-- training 36 | |-- dino 37 | |-- boxes 38 | |-- additional 39 | |-- stratified 40 | |-- test 41 | ``` 42 | 43 | To convert/visualize all downloaded scenes, run: 44 | ```bash 45 | $ python convert2hdf5.py 46 | $ python visualize_scenes.py 47 | ``` 48 | 49 | To convert/visualize specific scenes, run e.g. 50 | ```bash 51 | $ python convert2hdf5.py -d "training/boxes,training/dino" 52 | $ python visualize_scenes.py -d "training/boxes,training/dino" 53 | ``` 54 | 55 | 56 | # Dependencies 57 | 58 | The scripts are tested with Python 2.7 and the dependencies as listed in the requirements.txt The modules h5py and matplotlib are optional. They are only required for the conversion/visualization. 59 | 60 | 61 | # License 62 | This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. 63 | To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/. 64 | 65 | Authors: Katrin Honauer & Ole Johannsen 66 | 67 | Website: www.lightfield-analysis.net 68 | 69 | 70 | The 4D Light Field Benchmark was jointly created by the University of Konstanz and the HCI at Heidelberg University. If you use any part of the benchmark, please cite our paper "A dataset and evaluation methodology for depth estimation on 4D light fields". Thanks! 71 | 72 | @inproceedings{honauer2016benchmark, 73 | title={A dataset and evaluation methodology for depth estimation on 74 | 4D light fields}, 75 | author={Honauer, Katrin and Johannsen, Ole and Kondermann, Daniel 76 | and Goldluecke, Bastian}, 77 | booktitle={Asian Conference on Computer Vision}, 78 | year={2016}, 79 | organization={Springer} 80 | } 81 | -------------------------------------------------------------------------------- /convert2hdf5.py: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # This file is part of the 4D Light Field Benchmark. # 3 | # # 4 | # This work is licensed under the Creative Commons # 5 | # Attribution-NonCommercial-ShareAlike 4.0 International License. # 6 | # To view a copy of this license, # 7 | # visit http://creativecommons.org/licenses/by-nc-sa/4.0/. # 8 | ##################################################################### 9 | 10 | import os 11 | import file_io 12 | 13 | import util 14 | 15 | 16 | def convert_to_hdf5(data_folder, tgt=None): 17 | if tgt is None: 18 | tgt = os.path.join(data_folder, "scene.h5") 19 | 20 | scene = dict() 21 | scene["LF"] = file_io.read_lightfield(data_folder) 22 | params = file_io.read_parameters(data_folder) 23 | 24 | if params["category"] != "test": 25 | scene["disp_highres"] = file_io.read_disparity(data_folder, highres=True) 26 | scene["disp_lowres"] = file_io.read_disparity(data_folder, highres=False) 27 | scene["depth_highres"] = file_io.read_depth(data_folder, highres=True) 28 | scene["depth_lowres"] = file_io.read_depth(data_folder, highres=False) 29 | 30 | file_io.write_hdf5(scene, tgt) 31 | 32 | 33 | if __name__ == '__main__': 34 | data_folders = util.parse_options() 35 | 36 | for data_folder in data_folders: 37 | print "converting: %s" % data_folder 38 | convert_to_hdf5(data_folder) 39 | -------------------------------------------------------------------------------- /file_io.py: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # This file is part of the 4D Light Field Benchmark. # 3 | # # 4 | # This work is licensed under the Creative Commons # 5 | # Attribution-NonCommercial-ShareAlike 4.0 International License. # 6 | # To view a copy of this license, # 7 | # visit http://creativecommons.org/licenses/by-nc-sa/4.0/. # 8 | ##################################################################### 9 | 10 | import ConfigParser 11 | import os 12 | import sys 13 | 14 | import numpy as np 15 | 16 | 17 | def read_lightfield(data_folder): 18 | params = read_parameters(data_folder) 19 | light_field = np.zeros((params["num_cams_x"], params["num_cams_y"], params["height"], params["width"], 3), dtype=np.uint8) 20 | 21 | views = sorted([f for f in os.listdir(data_folder) if f.startswith("input_") and f.endswith(".png")]) 22 | 23 | for idx, view in enumerate(views): 24 | fpath = os.path.join(data_folder, view) 25 | try: 26 | img = read_img(fpath) 27 | light_field[idx / params["num_cams_x"], idx % params["num_cams_y"], :, :, :] = img 28 | except IOError: 29 | print "Could not read input file: %s" % fpath 30 | sys.exit() 31 | 32 | return light_field 33 | 34 | 35 | def read_parameters(data_folder): 36 | params = dict() 37 | 38 | with open(os.path.join(data_folder, "parameters.cfg"), "r") as f: 39 | parser = ConfigParser.ConfigParser() 40 | parser.readfp(f) 41 | 42 | section = "intrinsics" 43 | params["width"] = int(parser.get(section, 'image_resolution_x_px')) 44 | params["height"] = int(parser.get(section, 'image_resolution_y_px')) 45 | params["focal_length_mm"] = float(parser.get(section, 'focal_length_mm')) 46 | params["sensor_size_mm"] = float(parser.get(section, 'sensor_size_mm')) 47 | params["fstop"] = float(parser.get(section, 'fstop')) 48 | 49 | section = "extrinsics" 50 | params["num_cams_x"] = int(parser.get(section, 'num_cams_x')) 51 | params["num_cams_y"] = int(parser.get(section, 'num_cams_y')) 52 | params["baseline_mm"] = float(parser.get(section, 'baseline_mm')) 53 | params["focus_distance_m"] = float(parser.get(section, 'focus_distance_m')) 54 | params["center_cam_x_m"] = float(parser.get(section, 'center_cam_x_m')) 55 | params["center_cam_y_m"] = float(parser.get(section, 'center_cam_y_m')) 56 | params["center_cam_z_m"] = float(parser.get(section, 'center_cam_z_m')) 57 | params["center_cam_rx_rad"] = float(parser.get(section, 'center_cam_rx_rad')) 58 | params["center_cam_ry_rad"] = float(parser.get(section, 'center_cam_ry_rad')) 59 | params["center_cam_rz_rad"] = float(parser.get(section, 'center_cam_rz_rad')) 60 | 61 | section = "meta" 62 | params["disp_min"] = float(parser.get(section, 'disp_min')) 63 | params["disp_max"] = float(parser.get(section, 'disp_max')) 64 | params["frustum_disp_min"] = float(parser.get(section, 'frustum_disp_min')) 65 | params["frustum_disp_max"] = float(parser.get(section, 'frustum_disp_max')) 66 | params["depth_map_scale"] = float(parser.get(section, 'depth_map_scale')) 67 | 68 | params["scene"] = parser.get(section, 'scene') 69 | params["category"] = parser.get(section, 'category') 70 | params["date"] = parser.get(section, 'date') 71 | params["version"] = parser.get(section, 'version') 72 | params["authors"] = parser.get(section, 'authors').split(", ") 73 | params["contact"] = parser.get(section, 'contact') 74 | 75 | return params 76 | 77 | 78 | def read_depth(data_folder, highres=False): 79 | fpath = os.path.join(data_folder, "gt_depth_%s.pfm" % ("highres" if highres else "lowres")) 80 | try: 81 | data = read_pfm(fpath) 82 | except IOError: 83 | print "Could not read depth file: %s" % fpath 84 | sys.exit() 85 | return data 86 | 87 | 88 | def read_disparity(data_folder, highres=False): 89 | fpath = os.path.join(data_folder, "gt_disp_%s.pfm" % ("highres" if highres else "lowres")) 90 | try: 91 | data = read_pfm(fpath) 92 | except IOError: 93 | print "Could not read disparity file: %s" % fpath 94 | sys.exit() 95 | return data 96 | 97 | 98 | def read_img(fpath): 99 | from scipy import misc 100 | data = misc.imread(fpath) 101 | return data 102 | 103 | 104 | def write_hdf5(data, fpath): 105 | import h5py 106 | h = h5py.File(fpath, 'w') 107 | for key, value in data.iteritems(): 108 | h.create_dataset(key, data=value) 109 | h.close() 110 | 111 | 112 | def write_pfm(data, fpath, scale=1, file_identifier="Pf", dtype="float32"): 113 | # PFM format definition: http://netpbm.sourceforge.net/doc/pfm.html 114 | 115 | data = np.flipud(data) 116 | height, width = np.shape(data)[:2] 117 | values = np.ndarray.flatten(np.asarray(data, dtype=dtype)) 118 | endianess = data.dtype.byteorder 119 | print endianess 120 | 121 | if endianess == '<' or (endianess == '=' and sys.byteorder == 'little'): 122 | scale *= -1 123 | 124 | with open(fpath, 'wb') as file: 125 | file.write(file_identifier + '\n') 126 | file.write('%d %d\n' % (width, height)) 127 | file.write('%d\n' % scale) 128 | file.write(values) 129 | 130 | 131 | def read_pfm(fpath, expected_identifier="Pf"): 132 | # PFM format definition: http://netpbm.sourceforge.net/doc/pfm.html 133 | 134 | with open(fpath, 'rb') as f: 135 | # header 136 | identifier = _get_next_line(f) 137 | if identifier != expected_identifier: 138 | raise Exception('Unknown identifier. Expected: "%s", got: "%s".' % (expected_identifier, identifier)) 139 | 140 | try: 141 | line_dimensions = _get_next_line(f) 142 | dimensions = line_dimensions.split(' ') 143 | width = int(dimensions[0].strip()) 144 | height = int(dimensions[1].strip()) 145 | except: 146 | raise Exception('Could not parse dimensions: "%s". ' 147 | 'Expected "width height", e.g. "512 512".' % line_dimensions) 148 | 149 | try: 150 | line_scale = _get_next_line(f) 151 | scale = float(line_scale) 152 | assert scale != 0 153 | if scale < 0: 154 | endianness = "<" 155 | else: 156 | endianness = ">" 157 | except: 158 | raise Exception('Could not parse max value / endianess information: "%s". ' 159 | 'Should be a non-zero number.' % line_scale) 160 | 161 | try: 162 | data = np.fromfile(f, "%sf" % endianness) 163 | data = np.reshape(data, (height, width)) 164 | data = np.flipud(data) 165 | with np.errstate(invalid="ignore"): 166 | data *= abs(scale) 167 | except: 168 | raise Exception('Invalid binary values. Could not create %dx%d array from input.' % (height, width)) 169 | 170 | return data 171 | 172 | 173 | def _get_next_line(f): 174 | next_line = f.readline().rstrip() 175 | # ignore comments 176 | while next_line.startswith('#'): 177 | next_line = f.readline().rstrip() 178 | return next_line -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | cycler==0.10.0 2 | h5py==2.5.0 3 | matplotlib==1.5.1 4 | numpy==1.11.2 5 | pyparsing==2.1.9 6 | python-dateutil==2.5.3 7 | pytz==2016.7 8 | scipy==0.17.0 9 | six==1.10.0 10 | -------------------------------------------------------------------------------- /util.py: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # This file is part of the 4D Light Field Benchmark. # 3 | # # 4 | # This work is licensed under the Creative Commons # 5 | # Attribution-NonCommercial-ShareAlike 4.0 International License. # 6 | # To view a copy of this license, # 7 | # visit http://creativecommons.org/licenses/by-nc-sa/4.0/. # 8 | ##################################################################### 9 | 10 | import optparse 11 | import os 12 | 13 | 14 | def get_all_data_folders(base_dir=None): 15 | if base_dir is None: 16 | base_dir = os.getcwd() 17 | 18 | data_folders = [] 19 | categories = [d for d in os.listdir(base_dir) if os.path.isdir(os.path.join(base_dir, d))] 20 | for category in categories: 21 | for scene in os.listdir(os.path.join(base_dir, category)): 22 | data_folder = os.path.join(*[base_dir, category, scene]) 23 | if os.path.isdir(data_folder): 24 | data_folders.append(data_folder) 25 | 26 | return data_folders 27 | 28 | 29 | def get_comma_separated_args(option, opt, value, parser): 30 | values = [v.strip() for v in value.split(',')] 31 | setattr(parser.values, option.dest, values) 32 | 33 | 34 | def parse_options(): 35 | parser = optparse.OptionParser() 36 | parser.add_option('-d', '--date_folder', type="string", action="callback", callback=get_comma_separated_args, 37 | dest="data_folders", help="e.g. stratified/dots,test/bedroom") 38 | options, remainder = parser.parse_args() 39 | 40 | if options.data_folders is None: 41 | options.data_folders = get_all_data_folders(os.getcwd()) 42 | else: 43 | options.data_folders = [os.path.abspath("%s") % d for d in options.data_folders] 44 | for f in options.data_folders: 45 | print f 46 | 47 | return options.data_folders -------------------------------------------------------------------------------- /visualize_scenes.py: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # This file is part of the 4D Light Field Benchmark. # 3 | # # 4 | # This work is licensed under the Creative Commons # 5 | # Attribution-NonCommercial-ShareAlike 4.0 International License. # 6 | # To view a copy of this license, # 7 | # visit http://creativecommons.org/licenses/by-nc-sa/4.0/. # 8 | ##################################################################### 9 | 10 | import os 11 | 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | import matplotlib.cm as cm 15 | 16 | import util 17 | import file_io 18 | 19 | 20 | def visualize_scene(data_folder): 21 | params = file_io.read_parameters(data_folder) 22 | 23 | if params["category"] == "test": 24 | print "Test scenes with hidden ground truth are not visualized." 25 | return 26 | 27 | light_field = file_io.read_lightfield(data_folder) 28 | disp_map_highres = file_io.read_disparity(data_folder, highres=True) 29 | disp_map_lowres = file_io.read_disparity(data_folder, highres=False) 30 | depth_map_lowres = file_io.read_depth(data_folder, highres=False) 31 | 32 | rows, cols = 1, 4 33 | cb_shrink = 0.7 34 | fig = plt.figure(figsize=(20, 4)) 35 | plt.suptitle("%s:%s (%s)" % (params["category"].title(), 36 | params["scene"].title(), 37 | "x".join(str(i) for i in list(np.shape(light_field))))) 38 | 39 | plt.subplot(rows, cols, 1) 40 | plt.title("Center View") 41 | plt.imshow(light_field[4, 4, :, :, :]) 42 | 43 | plt.subplot(rows, cols, 2) 44 | plt.title("Depth Map (%dx%d)" % np.shape(depth_map_lowres)) 45 | cc = plt.imshow(depth_map_lowres, cmap=cm.viridis, interpolation="none") 46 | plt.colorbar(cc, shrink=cb_shrink) 47 | 48 | plt.subplot(rows, cols, 3) 49 | plt.title("Disparity Map (%dx%d)" % np.shape(disp_map_lowres)) 50 | cc = plt.imshow(disp_map_lowres, cmap=cm.viridis, interpolation="none") 51 | plt.colorbar(cc, shrink=cb_shrink) 52 | 53 | plt.subplot(rows, cols, 4) 54 | plt.title("Disparity Map (%dx%d)" % np.shape(disp_map_highres)) 55 | cc = plt.imshow(disp_map_highres, cmap=cm.viridis, interpolation="none") 56 | plt.colorbar(cc, shrink=cb_shrink) 57 | 58 | fig_name = os.path.join(data_folder, "scene.png") 59 | plt.savefig(fig_name, dpi=200, bbox_inches='tight') 60 | fig.clf() 61 | plt.close(fig) 62 | 63 | 64 | if __name__ == '__main__': 65 | data_folders = util.parse_options() 66 | 67 | for data_folder in data_folders: 68 | print "visualizing: %s" % data_folder 69 | visualize_scene(data_folder) --------------------------------------------------------------------------------