diff --git a/scripts/Depth2Disparity/depth2disparity.py b/scripts/Depth2Disparity/depth2disparity.py deleted file mode 100644 index 08c6bb232fc2aa7c70b4564cb33b96cd495e9606..0000000000000000000000000000000000000000 --- a/scripts/Depth2Disparity/depth2disparity.py +++ /dev/null @@ -1,105 +0,0 @@ -# takes 2 pixel coordinates and corresponding distance values - and a relative depth map -# caculates relative to absolute function - if linear -# applies function to relative depth map to get absolute depth map -# then convert to disparity map using depth disparity formula - - -import argparse -import numpy as np -import cv2 - -def relative2abs(rel_depth_map, coord1, dist1, coord2, dist2): - # Get the relative depth values at the two points - rel_value1 = rel_depth_map[coord1[1], coord1[0]] # (y, x) - rel_value2 = rel_depth_map[coord2[1], coord2[0]] - - # Calculate the linear transformation: depth = a * rel_depth + b - a = (dist2 - dist1) / (rel_value2 - rel_value1) - b = dist1 - a * rel_value1 - - # Apply the transformation to the entire relative depth map - abs_depth_map = a * rel_depth_map + b - - # this should not be normalised, the values in the array should equate to literal distances - return abs_depth_map - -def depth2disparity(abs_depth_map, baseline=0.176, disp_scale=2.0, disp_offset=-120): - - # Get image dimensions - height, width = abs_depth_map.shape - - # Calculate angular coordinates for each pixel - unit_w = 2.0 / width # Longitude step size - unit_h = 1.0 / height # Latitude step size - - # Initialize disparity map - disparity_map = np.zeros_like(abs_depth_map, dtype=np.float32) - - for i in range(height): - theta_t = i * unit_h * np.pi # Latitude angle for the row - - for j in range(width): - # Longitude angle (not strictly needed for disparity calculation) - phi = j * unit_w * np.pi - - # Retrieve the absolute depth (r_t) for this pixel - r_t = abs_depth_map[i, j] - - # Avoid invalid or infinite depth values - if r_t <= 0: - disparity_map[i, j] = 0 - continue - - try: - # Compute denominator with stability checks - epsilon = 1e-8 # Small value to prevent division instability - tan_theta_t = np.tan(theta_t) if np.abs(np.cos(theta_t)) > epsilon else np.sign(np.sin(theta_t)) * np.inf - - denominator = r_t * np.sin(theta_t) + r_t * np.cos(theta_t) * tan_theta_t - if denominator <= 0: - disparity_map[i, j] = 0 - continue - - # Calculate angular disparity (d) - angle_disp = np.arctan(baseline / denominator) - theta_t - - # Convert angular disparity to pixel disparity - disparity_map[i, j] = (angle_disp / (unit_h * np.pi) - disp_offset) * disp_scale - - except ZeroDivisionError: - disparity_map[i, j] = 0 - - return disparity_map - -if __name__ == "__main__": - # Set up argument parser - parser = argparse.ArgumentParser(description="Convert relative depth map to absolute depth map.") - parser.add_argument("rel_depth_map", type=str, help="Path to the relative depth map (image file).") - parser.add_argument("coord1", type=int, nargs=2, help="Pixel coordinates of the first point (x y).") - parser.add_argument("dist1", type=float, help="Absolute depth value at the first point.") - parser.add_argument("coord2", type=int, nargs=2, help="Pixel coordinates of the second point (x y).") - parser.add_argument("dist2", type=float, help="Absolute depth value at the second point.") - - # Parse arguments - args = parser.parse_args() - - # Load the relative depth map (dummy placeholder for now) - print(f"Loading relative depth map from: {args.rel_depth_map}") - rel_depth_map = cv2.imread(args.rel_depth_map, cv2.IMREAD_GRAYSCALE) # Load as grayscale - if rel_depth_map is None: - raise FileNotFoundError(f"Unable to load file: {args.rel_depth_map}") - - # Normalise depth map - rel_depth_map = rel_depth_map / 255.0 - - # Convert relative to absolute depth - abs_depth_map = relative2abs( - rel_depth_map, tuple(args.coord1), args.dist1, tuple(args.coord2), args.dist2 - ) - - # Convert depth map to disparity map - disparity_map = depth2disparity(abs_depth_map) - - # save disparity map - #cv2.imwrite(f"{args.rel_depth_map}-disparity.png", disparity_map) - \ No newline at end of file diff --git a/scripts/Depth2Disparity/depth_to_disparity.py b/scripts/Depth2Disparity/depth_to_disparity.py new file mode 100644 index 0000000000000000000000000000000000000000..f2ca50be08c25357901ac5b115a627696a966148 --- /dev/null +++ b/scripts/Depth2Disparity/depth_to_disparity.py @@ -0,0 +1,137 @@ +# takes 2 pixel coordinates and corresponding distance values - and a relative depth map +# caculates relative to absolute function - if linear +# applies function to relative depth map to get absolute depth map +# then convert to disparity map using depth disparity formula + + +import argparse +import numpy as np +import cv2 +import os + + +class Depth2Disparity: + + def __init__(self, baseline=0.176, disp_scale=2.0, disp_offset=-120): + """ + Initialize the Depth2Disparity class with correct parameters. + + Parameters: + baseline (float): Baseline distance between the stereo cameras (in meters). + disp_scale (float): Scaling factor for disparity values. + disp_offset (float): Offset added to the disparity values. + """ + self.baseline = baseline + self.disp_scale = disp_scale + self.disp_offset = disp_offset + + + def execute(self, rel_depth_path, coord1, dist1, coord2, dist2): + + # Load the relative depth map + print(f"Loading relative depth map from: {rel_depth_path}") + rel_depth_map = cv2.imread(rel_depth_path, cv2.IMREAD_GRAYSCALE) # Load as grayscale + if rel_depth_map is None: + raise FileNotFoundError(f"Unable to load file: {rel_depth_path}") + + # Normalize depth map + print("Normalizing depth map...") + rel_depth_map = rel_depth_map / 255.0 + + # Convert relative to absolute depth + print("Converting relative to absolute ...") + abs_depth_map = self._relative2abs(rel_depth_map, coord1, dist1, coord2, dist2) + + # Convert depth map to disparity map + print("Converting abs depth to disparity ...") + disparity_map = self._depth2disparity(abs_depth_map) + + # Determine the output path for the disparity map + disparity_dir = os.path.dirname(rel_depth_path) + disparity_base = "depth_e.png" + disparity_path = os.path.join(disparity_dir, disparity_base) + + # Check if an existing disparity map needs to be renamed + print(f"Checking for old depth map: {disparity_path}") + if os.path.exists(disparity_path): + old_depth_path = os.path.join(disparity_dir, "depth_e_old.png") + print(f"Renaming monodepth map to: {old_depth_path}") + os.rename(disparity_path, old_depth_path) + + # Save the new disparity map + print(f"Saving new disparity map to: {disparity_path}") + cv2.imwrite(disparity_path, (disparity_map * 255).astype(np.uint8)) + + # Debug message for GUI or logs + print("Complete") + + # add typing to this method defintion + def _relative2abs(self, rel_depth_map, coord1: tuple, dist1: float, coord2: tuple, dist2: float): + + print("\tStoring relative depth value at coordinates") + # Get the relative depth values at the two points + rel_value1 = rel_depth_map[coord1[1], coord1[0]] # (y, x) + rel_value2 = rel_depth_map[coord2[1], coord2[0]] + + print("\tPerforming linear transformation") + # Calculate the linear transformation: depth = a * rel_depth + b + a = (dist2 - dist1) / (rel_value2 - rel_value1) + b = dist1 - a * rel_value1 + + print("\tApplying transformation to entire depth map") + # Apply the transformation to the entire relative depth map + abs_depth_map = a * rel_depth_map + b + + # this should not be normalised, the values in the array should equate to literal distances + return abs_depth_map + + def _depth2disparity(self, abs_depth_map): + + # Get image dimensions + height, width = abs_depth_map.shape + + # Calculate angular coordinates for each pixel + unit_w = 2.0 / width # Longitude step size + unit_h = 1.0 / height # Latitude step size + + # Initialize disparity map + disparity_map = np.zeros_like(abs_depth_map, dtype=np.float32) + + for i in range(height): + theta_t = i * unit_h * np.pi # Latitude angle for the row + + for j in range(width): + # Longitude angle (not strictly needed for disparity calculation) + phi = j * unit_w * np.pi + + # Retrieve the absolute depth (r_t) for this pixel + r_t = abs_depth_map[i, j] + + # Avoid invalid or infinite depth values + if r_t <= 0: + disparity_map[i, j] = 0 + continue + + try: + # Compute denominator with stability checks + epsilon = 1e-8 # Small value to prevent division instability + tan_theta_t = np.tan(theta_t) if np.abs(np.cos(theta_t)) > epsilon else np.sign(np.sin(theta_t)) * np.inf + + denominator = r_t * np.sin(theta_t) + r_t * np.cos(theta_t) * tan_theta_t + if denominator <= 0: + disparity_map[i, j] = 0 + continue + + # Calculate angular disparity (d) + angle_disp = np.arctan(self.baseline / denominator) - theta_t + + # Convert angular disparity to pixel disparity + disparity_map[i, j] = (angle_disp / (unit_h * np.pi) - self.disp_offset) * self.disp_scale + + except ZeroDivisionError: + disparity_map[i, j] = 0 + + return disparity_map + + + \ No newline at end of file diff --git a/scripts/simple_tab.py b/scripts/simple_tab.py index 867c06ab3385c05cd959f7f19be0288d913229b2..ff0c9123eb027ec0dbe0a7454e8c356e8652c846 100644 --- a/scripts/simple_tab.py +++ b/scripts/simple_tab.py @@ -18,14 +18,17 @@ from debug_tool.tabs.depth_tab import DepthTab from debug_tool.tabs.material_tab import MaterialTab from debug_tool.tabs.edge_net_tab import EdgeNetTab +from Depth2Disparity.depth_to_disparity import Depth2Disparity + class PipelineWorker(QThread): progress = pyqtSignal(str) finished = pyqtSignal(bool, str) def __init__(self, tab_instance): super().__init__() - self.tab = tab_instance - + self.tab = tab_instance + self.distance_points = self.tab.distance_points # added distance points to class for disparity calculation + def run(self): try: self.run_pipeline() @@ -86,6 +89,26 @@ class PipelineWorker(QThread): self.progress.emit("Running depth estimation...") self.tab.depth.run_depth_estimation(False) print("Completed depth_estimation") # Debug print + + def run_depth_to_disparity(self): + print("\nStarting depth2disparity") + self.progress.emit("Converting mono-depthmap to disparity map...") + + # execute function to convert depth to disparity + real_depth_path = self.tab.depth.depth_output_path # depthmap path + coord1 = int(self.distance_points[0][0]), int(self.distance_points[0][1]) # x,y coordinates of point 1 + dist1 = float(self.distance_points[0][2]) # distance from camera to point 1 + coord2 = int(self.distance_points[1][0]), int(self.distance_points[1][1]) # x,y coordinates of point 2 + dist2 = float(self.distance_points[1][2]) # distance from camera to point 2 + print(f"{coord1}, {dist1}, {coord2}, {dist2}") + + convert_d2d = Depth2Disparity() + print("Executing...") + convert_d2d.execute(real_depth_path, coord1, dist1, coord2, dist2) + + print("Saved disparity map to output directory: " + real_depth_path) + self.progress.emit("Completed Disparity Map Conversion") + def run_material_recognition(self): print("Starting material_recognition") @@ -148,13 +171,15 @@ class PipelineWorker(QThread): self.progress.emit("File saved in edgenet-360\Output") def run_pipeline(self): - self.clean_temp_files() - self.shift_image() - self.copy_file() - self.run_depth_estimation() - self.run_material_recognition() - self.run_edge_net() - self.run_post_processing() + #self.clean_temp_files() + #self.shift_image() + #self.copy_file() + #self.run_depth_estimation() + self.run_depth_to_disparity() + + #self.run_material_recognition() + #self.run_edge_net() + #self.run_post_processing() self.progress.emit("Pipeline completed!") class SimpleTab(QWidget): @@ -612,6 +637,10 @@ class SimpleTab(QWidget): self.progress_bar.show() self.run_pipeline_btn.setEnabled(False) + #TODO: Add distance points to the pipeline for depth estimation + # Get the distance points + self.distance_points = self.distance_preview.get_points() + self.pipeline_thread = PipelineWorker(self) # Connect signals @@ -626,10 +655,6 @@ class SimpleTab(QWidget): #TODO: Add model selection for EdgeNet or MDBNet # Set the SSC model self.selected_model = self.ssc_model_combo.currentText() - - #TODO: Add distance points to the pipeline for depth estimation - # Get the distance points - self.distance_points = self.distance_preview.get_points() # Start the pipeline self.pipeline_thread.start()