Cournet, M., Sarrazin, E., Dumas, L., Michel, J., Guinet, J., Youssefi, D., Defonte, V., Fardet, Q., 2020. Ground-truth generation and disparity estimation for optical satellite imagery. ISPRS - International Archives of the Photogrammetry, Remote Sensing and Spatial Information Sciences.
import io
from IPython.display import Image, display
import io
import matplotlib.pyplot as plt
import numpy as np
import os
from pathlib import Path
import rasterio
from snippets.utils import *
def plot_image(img, title=None, output_dir=None, cmap="viridis"):
fig = plt.figure()
plt.title(title)
plt.imshow(img, cmap=cmap, vmin=np.min(img), vmax=np.max(img))
plt.colorbar()
if output_dir is not None:
fig.savefig(os.path.join(output_dir,title + '.pdf'))
def plot_state_machine(machine):
stream = io.BytesIO()
try:
pandora_machine.get_graph().draw(stream, prog='dot', format='png')
display(Image(stream.getvalue()))
except:
print("It is not possible to show the graphic of the state machine. To solve it, please install graphviz on your system (apt-get install graphviz if operating in Linux) and install python package with pip install graphviz")
[Scharstein 2002] A Taxonomy and Evaluation of Dense Two-Frame Stereo Correspondence Algorithms, D. Scharstein and R. Szeliski, vol. 47, International Journal of Computer Vision}, 2002
Pandora provides the following steps:
Step | Algorithms implemented |
---|---|
Matching cost computation | Census / SAD / SSD / ZNNC / MC-CNN |
Cost aggregation | Cross Based Cost Aggregation |
Cost optimization | SGM |
Disparity computation | Winner-Take-All |
Subpixel disparity refinement | Vfit / Quadratic |
Disparity filtering | Median / Bilateral |
Validation | Cross checking |
Multiscale | Fixed zoom pyramid |
# Load pandora imports
import pandora
from pandora.img_tools import read_img
from pandora.check_json import check_pipeline_section, concat_conf, memory_consumption_estimation
from pandora.state_machine import PandoraMachine
from pandora import import_plugin, check_conf
Available Pandora Plugins include :
# Load plugins
import_plugin()
Provide image path
# Paths to left and right images
img_left_path = "data/Cones_LEFT.tif"
img_right_path = "data/Cones_RIGHT.tif"
# Paths to masks (None if not provided)
left_mask_path = None
right_mask_path = None
Provide image configuration
image_cfg = {'image': {'no_data_left': np.nan, 'no_data_right': np.nan}}
Provide output directory to write results
output_dir = os.path.join(os.getcwd(),"output")
# If necessary, create output dir
Path(output_dir).mkdir(exist_ok=True,parents=True)
Convert input data to dataset
img_left = read_img(img_left_path, no_data=image_cfg['image']['no_data_left'],
mask=left_mask_path)
img_right = read_img(img_right_path, no_data=image_cfg['image']['no_data_right'],
mask=right_mask_path)
Visualize input data
plot_image(img_left.im, "Left input image", output_dir, cmap="gray")
pandora_machine = PandoraMachine()
user_pipeline_cfg = {
'pipeline':{
"right_disp_map": {
"method": "accurate"
},
"matching_cost" : {
"matching_cost_method": "zncc",
"window_size": 5,
"subpix": 4
},
"disparity": {
"disparity_method": "wta",
"invalid_disparity": "NaN"
},
"refinement": {
"refinement_method": "quadratic"
},
"filter": {
"filter_method": "median"
},
"validation": {
"validation_method": "cross_checking"
},
"filter.this_time_after_validation" : {
"filter_method": "median",
"filter_size": 3
}
}
}
Disparity interval used
disp_min = -60
disp_max = 0
checked_cfg = check_pipeline_section(user_pipeline_cfg, pandora_machine)
pipeline_cfg = checked_cfg['pipeline']
print(pipeline_cfg)
min_mem_consump, max_mem_consump = memory_consumption_estimation(user_pipeline_cfg, [img_left_path, disp_min, disp_max], pandora_machine)
print("Estimated maximum memory consumption between {:.2f} GiB and {:.2f} GiB".format(min_mem_consump, max_mem_consump))
pandora_machine.run_prepare(pipeline_cfg, img_left, img_right, disp_min, disp_max)
left_disparity, right_disparity = pandora.run(pandora_machine, img_left, img_right, disp_min, disp_max, pipeline_cfg)
Visualize output disparity map
plot_image(left_disparity.disparity_map, "Left disparity map", output_dir, cmap=pandora_cmap())
The implementation of Pandora with a state machine makes it possible to set up a more flexible pipeline, which makes it possible to choose via a configuration file the steps as well as the order of the steps that one wishes to follow in Pandora.
Moreover, the state machine allows to run each step of the pipeline independently, giving the possibility to save and visualize the results after each step.
The state machine has three states :
Being the connections between them the different steps of the pipeline.
pandora_machine = PandoraMachine()
user_pipeline_cfg = {
'pipeline':{
"right_disp_map": {
"method": "accurate"
},
"matching_cost" : {
"matching_cost_method": "zncc",
"window_size": 5,
"subpix": 4
},
"aggregation": {
"aggregation_method": "cbca"
},
"disparity": {
"disparity_method": "wta",
"invalid_disparity": "NaN"
},
"refinement": {
"refinement_method": "quadratic"
},
"filter": {
"filter_method": "median"
},
"validation": {
"validation_method": "cross_checking"
}
}
}
Disparity interval used
disp_min = -60
disp_max = 0
checked_cfg = check_pipeline_section(user_pipeline_cfg, pandora_machine)
print(checked_cfg)
pipeline_cfg = checked_cfg['pipeline']
min_mem_consump, max_mem_consump = memory_consumption_estimation(user_pipeline_cfg, [img_left_path, disp_min, disp_max], pandora_machine)
print("Estimated maximum memory consumption between {:.2f} GiB and {:.2f} GiB".format(min_mem_consump, max_mem_consump))
pandora_machine.run_prepare(pipeline_cfg, img_left, img_right, disp_min, disp_max)
plot_state_machine(pandora_machine)
Run matching cost
pandora_machine.run('matching_cost', pipeline_cfg)
plot_state_machine(pandora_machine)
pandora_machine.run('aggregation', pipeline_cfg)
plot_state_machine(pandora_machine)
Run disparity
pandora_machine.run('disparity', pipeline_cfg)
plot_state_machine(pandora_machine)
Run refinement
pandora_machine.run('refinement', pipeline_cfg)
plot_state_machine(pandora_machine)
Run filter
pandora_machine.run('filter', pipeline_cfg)
plot_state_machine(pandora_machine)
Run validation
pandora_machine.run('validation', pipeline_cfg)
plot_state_machine(pandora_machine)
Visualize output disparity map
plot_image(pandora_machine.left_disparity.disparity_map, "Left disparity map", output_dir, cmap=pandora_cmap())