diff --git a/mona-ssc b/mona-ssc new file mode 160000 index 0000000000000000000000000000000000000000..a0816610da9fa1ed52674240d8343b5643f0e25c --- /dev/null +++ b/mona-ssc @@ -0,0 +1 @@ +Subproject commit a0816610da9fa1ed52674240d8343b5643f0e25c diff --git a/scripts/GUI.py b/scripts/GUI.py index 5a574f7f9cd0334e1727a63b9787264045aac9b6..fbb15da747c8378fe8f2b4e823c08bf66d241950 100644 --- a/scripts/GUI.py +++ b/scripts/GUI.py @@ -34,17 +34,46 @@ class VRSceneCreatorGUI(QMainWindow): def setup_ui(self): # Create main widget and layout main_widget = QWidget() + main_widget.setStyleSheet("background-color: #1e1e1e;") self.setCentralWidget(main_widget) layout = QVBoxLayout(main_widget) # Add title/header header_label = QLabel("Immersive VR Scene Creator") header_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - header_label.setStyleSheet("font-size: 24px; font-weight: bold; margin: 10px;") + header_label.setStyleSheet(""" + font-size: 24px; + font-weight: bold; + margin: 10px; + color: white; + """) layout.addWidget(header_label) # Create tab widget self.tabs = QTabWidget() + self.tabs.setStyleSheet(""" + QTabWidget::pane { /* The tab widget frame */ + border-top: 2px solid #C2C7CB; + } + QTabBar::tab { + background: #3e3e3e; + color: white; + padding: 10px; + border: 1px solid #C2C7CB; + border-bottom: none; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } + QTabBar::tab:selected { + background: #5e5e5e; + color: white; + border-color: #9B9B9B; + } + QTabBar::tab:hover { + background: #4e4e4e; + color: white; + } + """) layout.addWidget(self.tabs) # Initialize tabs diff --git a/scripts/advanced_tab.py b/scripts/advanced_tab.py index 85617ddda6d7d7060fbcb257791487574458d39f..52860a43e145eef22a62e0a2b923a80ce0c21d61 100644 --- a/scripts/advanced_tab.py +++ b/scripts/advanced_tab.py @@ -44,44 +44,202 @@ class AdvancedTab(QWidget): def add_module_controls(self, layout): # Status section for overall progress status_group, self.status_text = create_group_with_text("Pipeline Status", 100) + status_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) + self.status_text.setStyleSheet(""" + QTextEdit { + background-color: #1e1e1e; + color: white; + border: 2px solid grey; + border-radius: 10px; + padding: 10px; + font-size: 14px; + } + QTextEdit:focus { + border: 2px solid #05B8CC; + } + """) layout.addWidget(status_group) # Image Shifter Controls shifter_group = QGroupBox("Image Shifter") shifter_layout = QVBoxLayout(shifter_group) + shifter_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) # Add shifter specific controls layout.addWidget(shifter_group) # Depth Estimation Controls depth_group = QGroupBox("Depth Estimation") depth_layout = QVBoxLayout(depth_group) + depth_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) # Add depth estimation specific controls layout.addWidget(depth_group) # Material Recognition Controls material_group = QGroupBox("Material Recognition") material_layout = QVBoxLayout(material_group) + material_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) # Add material recognition specific controls layout.addWidget(material_group) # EdgeNet Controls edgenet_group = QGroupBox("EdgeNet") edgenet_layout = QVBoxLayout(edgenet_group) + edgenet_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) # Add EdgeNet specific controls layout.addWidget(edgenet_group) # Mesh Processing Controls mesh_group = QGroupBox("Mesh Processing") mesh_layout = QVBoxLayout(mesh_group) + mesh_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) # Add mesh processing specific controls layout.addWidget(mesh_group) # Preview section preview_group = QGroupBox("Preview") preview_layout = QHBoxLayout(preview_group) + preview_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) input_group, self.input_preview = create_preview_group("Input") output_group, self.output_preview = create_preview_group("Output") + input_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #1e1e1e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + QLabel { + margin: 5px; + background-color: #1e1e1e; + color: white; + } + """) + output_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #1e1e1e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + QLabel { + margin: 5px; + background-color: #1e1e1e; + color: white; + } + """) preview_layout.addWidget(input_group) preview_layout.addWidget(output_group) diff --git a/scripts/debug_tool/utils/clickable_label.py b/scripts/debug_tool/utils/clickable_label.py new file mode 100644 index 0000000000000000000000000000000000000000..26516da6b37752dba65fb50602874da2310a683a --- /dev/null +++ b/scripts/debug_tool/utils/clickable_label.py @@ -0,0 +1,49 @@ +from PyQt6.QtWidgets import QInputDialog, QLabel +from PyQt6.QtCore import Qt, pyqtSignal +from PyQt6.QtGui import QPainter, QPen, QColor +from collections import deque + +class ClickableLabel(QLabel): + point_added = pyqtSignal() + def __init__(self, parent=None): + super().__init__(parent) + self.points = deque(maxlen=2) # Initialize a deque with a maximum length of 2 + + def mousePressEvent(self, event): + if event.button() == Qt.MouseButton.LeftButton: + x = event.position().x() + y = event.position().y() + number, ok = QInputDialog.getDouble(self, "Input Distance", "Enter a number (meters):", min=0) + if ok: + self.points.append((x, y, number)) + print(f"Stored: x={x}, y={y}, number={number}") + self.point_added.emit() + + def paintEvent(self, event): + super().paintEvent(event) + painter = QPainter(self) + pen = QPen(QColor("red")) + pen.setWidth(2) + painter.setPen(pen) + for i, point in enumerate(self.points): + x, y, _ = point + painter.drawEllipse(int(x) - 5, int(y) - 5, 10, 10) # Draw a hollow circle + painter.drawText(int(x) + 10, int(y), str(i + 1)) # Draw the number next to the circle + + + def get_points(self): + """ + Returns the stored points from the image. + + Returns: + list: List of tuples (x, y, number) + """ + return list(self.points) # Convert deque to list before returning + + def clear_points(self): + """ + Clears the stored points from the image. + """ + self.points.clear() + self.update() + self.point_added.emit() \ No newline at end of file diff --git a/scripts/scene_completion.py b/scripts/scene_completion.py new file mode 100644 index 0000000000000000000000000000000000000000..fdb3fcc0b99b87e3d7cf5ca9f6ef062b89e1c075 --- /dev/null +++ b/scripts/scene_completion.py @@ -0,0 +1,138 @@ +import paramiko +from dotenv import load_dotenv +from scp import SCPClient +import os +import subprocess +import time + +load_dotenv() +hostname = os.getenv("HOSTNAME") +username = os.getenv("USERNAME") +password = os.getenv("PASSWORD") + +def send_files(shifted_disparity_path, shifted_t_path): + # sends two files needed to iridis + # files keep their names. NAMES MUST BE shifted_disparity.png AND shifted_t.png + + command = [ + "scp", + shifted_disparity_path, + f"{username}@{hostname}:{os.getenv("REMOTE_INPUT_PATH")}" + ] + try: + subprocess.run(command, check=True) + + except subprocess.CalledProcessError as e: + print(f"Error during SCP: {e}") + return False, False + + + command = [ + "scp", + shifted_t_path, + f"{username}@{hostname}:{os.getenv("REMOTE_INPUT_PATH")}" + ] + try: + subprocess.run(command, check=True) + + except subprocess.CalledProcessError as e: + print(f"Error during SCP: {e}") + return False, False + return True + +def get_completed_scene(shifted_disparity_path, shifted_t_path): + if send_files(shifted_disparity_path, shifted_t_path): + + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + # Connect to the server + try: + client.connect(hostname, username=username, password=password) + print("SSH connection established.") + + # Check if the connection is active + if client.get_transport().is_active(): + print("Connection is active.") + else: + print("Connection is not active.") + return False, False + except Exception as e: + print(f"Failed to connect to {hostname}: {e}") + return False, False + + stdin, stdout, stderr = client.exec_command( + "cd mona/MDBNet360_GDP/" + + " && module load conda" + + " && source activate" + + " && conda activate ssc_env" + + " && sbatch --partition=ecsstudents --account=ecsstudents run_enhance360_job.sh" + ) + output = stdout.read().decode() + print(output) + + stdin, stdout, stderr = client.exec_command("squeue -lu kproject") + output = stdout.read().decode() + print(output) + + time.sleep(30) + + while "RUNNING" in output: + print("Sleeping for 30") + time.sleep(30) + stdin, stdout, stderr = client.exec_command("squeue -lu kproject") + output = stdout.read().decode() + print(output) + + print("Finish Enhancing") + + stdin, stdout, stderr = client.exec_command( + "cd mona/MDBNet360_GDP/" + + " && module load conda" + + " && source activate" + + " && conda activate ssc_env" + + " && sbatch --partition=ecsstudents --account=ecsstudents run_obj_job.sh" + ) + + output = stdout.read().decode() + print(output) + + stdin, stdout, stderr = client.exec_command("squeue -lu kproject") + output = stdout.read().decode() + print(output) + time.sleep(30) + + while "RUNNING" in output: + print("Sleeping for 30") + time.sleep(30) + stdin, stdout, stderr = client.exec_command("squeue -lu kproject") + output = stdout.read().decode() + print(output) + + remote_file_path = "/mainfs/ECShome/kproject/mona/MDBNet360_GDP/output/scene_completed_prediction.obj" + local_file_path = "edgenet-360/Data/Input/scene_completed_prediction.obj" + with SCPClient(client.get_transport()) as scp: + scp.get(remote_file_path, local_file_path) # Download file + + print("OUTPUT DOWNLOADED") + # Close the SSH connection + client.close() + return True, local_file_path + + else: + return False, False + + +# out = get_completed_scene("C:\\Project\\AVVR-Pipeline-GDP4\\edgenet-360\\Data\\Courtyard\\shifted-disparity.png", "C:\\Project\\AVVR-Pipeline-GDP4\\edgenet-360\\Data\\Courtyard\\shifted_t.png") +# print(out) + +if __name__ == "__main__": + if len(sys.argv) != 3: + print("Usage: python shifter.py <shifted_disparity_path> <shifted_t_path>") + sys.exit(1) + + shifted_disparity_path = sys.argv[1] + shifted_t_path = sys.argv[2] + + saved_path = get_completed_scene(shifted_disparity_path, shifted_t_path) + print(f"Shifted image saved as {saved_path}") \ No newline at end of file diff --git a/scripts/simple_tab.py b/scripts/simple_tab.py index a80dae8cb91a799c6aa706b9f5ad3b4a02fc18da..0f383dfc7c88657a2a4ecfda208c382c1a3c1a98 100644 --- a/scripts/simple_tab.py +++ b/scripts/simple_tab.py @@ -1,7 +1,7 @@ from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QCheckBox, QMessageBox, QPushButton, - QProgressBar) -from PyQt6.QtCore import Qt, QThread, pyqtSignal + QProgressBar, QComboBox, QLabel, QSizePolicy, QScrollArea) +from PyQt6.QtCore import Qt, QThread, pyqtSignal, QTimer import os import sys @@ -9,7 +9,8 @@ import sys from debug_tool.utils.qt_widgets import (create_group_with_text, create_button_layout, create_info_group, create_preview_group) from debug_tool.utils.file_handlers import select_file, clean_directory, copy_file, run_command -from debug_tool.utils.image_handlers import update_preview +from debug_tool.utils.image_handlers import update_preview, load_and_resize_image, convert_cv_to_pixmap +from debug_tool.utils.clickable_label import ClickableLabel # Import existing module implementations from debug_tool.tabs.shifter_tab import ShifterTab @@ -149,33 +150,139 @@ class SimpleTab(QWidget): self.depth.hide() self.material.hide() self.edge_net.hide() + + # Scroll Area + self.scroll_area = QScrollArea(self) + self.scroll_area.setWidgetResizable(True) + + self.scroll_content = QWidget() + + self.file_selected = False + self.flash_timer = QTimer(self) + self.flash_timer.timeout.connect(self.toggle_flash) + self.setup_ui(self.scroll_content) - self.setup_ui() + self.scroll_area.setWidget(self.scroll_content) + layout=QVBoxLayout(self) + layout.addWidget(self.scroll_area) - def setup_ui(self): - layout = QVBoxLayout(self) + def setup_ui(self,parent_widget): + layout = QVBoxLayout(parent_widget) # Controls section controls_group = QGroupBox("Pipeline Controls") + controls_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 20px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 15px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) controls_layout = QVBoxLayout(controls_group) # Info display info_rows = [ ("Input Image:", "No file selected"), - ("Status:", "Ready") + ("Status:", "Ready - Waiting for input"), ] self.info_group, self.info_labels = create_info_group("Information", info_rows) + self.info_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + QLabel{ + margin: 5px; + background-color: #3e3e3e; + color: white; + } + """) + for label in self.info_labels.values(): + label.setStyleSheet(""" + QLabel{ + margin: 5px; + background-color: #3e3e3e; + color: white; + } + """) controls_layout.addWidget(self.info_group) # Options options_layout = QHBoxLayout() self.include_top_check = QCheckBox("Include Top in Mesh") + self.include_top_check.setStyleSheet(""" + QCheckBox { + margin: 5px; + padding: 5px; + background-color: #3e3e3e; + color: white; + border: none; + border-radius: 5px; + } + """) options_layout.addWidget(self.include_top_check) self.shift_image_check = QCheckBox("Shift Input Image") + self.shift_image_check.setStyleSheet("QCheckBox { margin: 5px; background-color: #3e3e3e;}") options_layout.addWidget(self.shift_image_check) - + + # SSC Model selection + ssc_model_layout = QHBoxLayout() + ssc_model_label = QLabel("SSC Model:") + #ssc_model_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter) + ssc_model_label.setStyleSheet(""" + QLabel { + margin: 5px; + background-color: transparent; + color: white; + font-weight: bold; + } + """) + ssc_model_label.setFixedWidth(ssc_model_label.sizeHint().width()) + ssc_model_layout.addWidget(ssc_model_label) + + self.ssc_model_combo = QComboBox() + self.ssc_model_combo.addItems(["EdgeNet360", "MDBNet"]) + self.ssc_model_combo.setStyleSheet(""" + QComboBox { + margin: 5px; + padding: 5px; + background-color: #1e1e1e; + color: white; + border: none; + border-radius: 5px; + } + QComboBox QAbstractItemView { + background-color: #1e1e1e; + color: white; + selection-background-color: #5e5e5e; + border-radius: 5px; + } + """) + self.ssc_model_combo.setFixedWidth(150) + ssc_model_layout.addWidget(self.ssc_model_combo) + ssc_model_layout.setAlignment(Qt.AlignmentFlag.AlignLeft) + # Add the horizontal layout to the options layout + options_layout.addLayout(ssc_model_layout) + controls_layout.addLayout(options_layout) # Progress Bar @@ -183,38 +290,219 @@ class SimpleTab(QWidget): self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(0) # Makes it an indefinite progress bar self.progress_bar.hide() # Hidden by default + self.progress_bar.setStyleSheet(""" + QProgressBar { + border: 2px solid grey; + border-radius: 5px; + text-align: center; + } + QProgressBar::chunk { + background-color: #05B8CC; + width: 20px; + } + """) controls_layout.addWidget(self.progress_bar) # Buttons self.run_pipeline_btn = QPushButton("Run Pipeline") self.run_pipeline_btn.clicked.connect(self.run_full_pipeline) self.run_pipeline_btn.setEnabled(False) # Disabled by default + self.run_pipeline_btn.setStyleSheet(""" + QPushButton { + margin: 5px; + padding: 5px; + border-radius: 10px; + } + QPushButton:enabled { + background-color: green; + color: white; + } + QPushButton:disabled { + background-color: red; + color: white; + } + """) + self.run_pipeline_btn.setFixedSize(600, 40) # Explicit size buttons_layout = QHBoxLayout() - select_btn = QPushButton("Select Input Image") - select_btn.clicked.connect(self.handle_file_select) - - buttons_layout.addWidget(select_btn) + self.select_btn = QPushButton("Select Input Image") + self.select_btn.clicked.connect(self.handle_file_select) + self.select_btn.setStyleSheet(""" + QPushButton { + margin: 5px; + padding: 5px; + border-radius: 10px; + } + """) + self.select_btn.setFixedSize(600, 40) # Explicit size + + buttons_layout.addWidget(self.select_btn) buttons_layout.addWidget(self.run_pipeline_btn) controls_layout.addLayout(buttons_layout) layout.addWidget(controls_group) + + # Image Distance section + self.image_distance_group = QGroupBox("Image Distance") + distance_layout = QVBoxLayout(self.image_distance_group) + info_label = QLabel("Please select two point on the image and input the distance from the camera to that point.") + self.counter_label = QLabel("(0/2)") + self.distance_preview = ClickableLabel() + self.distance_preview.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.counter_label.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignCenter) + self.points_info_label = QLabel() # Label to display points and distances + self.points_info_label.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignCenter) + self.image_distance_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 20px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + QLabel { + margin: 5px; + background-color: #3e3e3e; + color: white; + } + """) + # Center the ClickableLabel within its parent layout + distance_preview_layout = QHBoxLayout() + distance_preview_layout.addStretch() + distance_preview_layout.addWidget(self.distance_preview) + distance_preview_layout.addStretch() + + self.distance_reset_btn = QPushButton("Reset Points") + self.distance_reset_btn.clicked.connect(self.distance_preview.clear_points) + self.distance_reset_btn.setFixedSize(150, 40) + self.distance_reset_btn.setStyleSheet(""" + QPushButton { + margin: 5px; + padding: 5px; + border-radius: 10px; + } + """) + distance_btn_layout = QHBoxLayout() + distance_btn_layout.addStretch() + distance_btn_layout.addWidget(self.distance_reset_btn) + distance_btn_layout.addStretch() + + distance_layout.addWidget(info_label) + distance_layout.addLayout(distance_preview_layout) + distance_layout.addWidget(self.points_info_label) + distance_layout.addWidget(self.counter_label) + distance_layout.addWidget(self.distance_reset_btn) + self.image_distance_group.hide() + layout.addWidget(self.image_distance_group) + + self.distance_preview.point_added.connect(self.update_counter_Label) # Status section - status_group, self.status_text = create_group_with_text("Pipeline Status", 150) + status_group, self.status_text = create_group_with_text("Pipeline Status", 300) + status_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 20px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) + self.status_text.setStyleSheet(""" + QTextEdit { + background-color: #1e1e1e; + color: white; + border: 2px solid grey; + border-radius: 10px; + padding: 10px; + font-size: 14px; + } + QTextEdit:focus { + border: 2px solid #05B8CC; + } + """) layout.addWidget(status_group) # Preview section preview_group = QGroupBox("Preview") + preview_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 20px; + margin-top: 10px; + background-color: #3e3e3e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + """) preview_layout = QHBoxLayout(preview_group) input_group, self.input_preview = create_preview_group("Input Image") output_group, self.output_preview = create_preview_group("Current Output") - + input_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #1e1e1e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + QLabel { + margin: 5px; + background-color: #1e1e1e; + color: white; + } + """) + output_group.setStyleSheet(""" + QGroupBox { + font-weight: bold; + border: 2px solid grey; + border-radius: 10px; + margin-top: 10px; + background-color: #1e1e1e; + padding: 20px; + } + QGroupBox::title { + margin: 10px; + background-color: transparent; + color: white; + } + QLabel { + margin: 5px; + background-color: #1e1e1e; + color: white; + } + """) preview_layout.addWidget(input_group) preview_layout.addWidget(output_group) layout.addWidget(preview_group) + # Start flashing if no file is selected + self.start_flashing() + def handle_file_select(self): file_path = select_file( @@ -230,15 +518,53 @@ class SimpleTab(QWidget): self.update_status(f"Selected input file: {file_path}") update_preview(self.input_preview, file_path, error_callback=self.update_status) - + update_preview(self.distance_preview,file_path,max_size=1500) + pixmap = load_and_resize_image(file_path, 1500) + pixmap = convert_cv_to_pixmap(pixmap) + self.distance_preview.setFixedSize(pixmap.size()) + self.image_distance_group.show() + self.update_status("Waiting for distance points...") + self.info_labels["Status:"].setText("Waiting for distance points...") # Enable the run pipeline button - self.run_pipeline_btn.setEnabled(True) + #self.run_pipeline_btn.setEnabled(True) # Provide input path to all modules self.shifter.input_file_path = file_path self.depth.depth_input_path = file_path self.material.input_file_path = file_path # self.edge_net.input_path = file_path # edgenet have default input path + + self.file_selected = True + self.flash_timer.stop() + self.select_btn.setStyleSheet("QPushButton { margin: 5px; padding: 5px; border-radius: 10px;}") + + def start_flashing(self): + if not self.file_selected: + self.flash_timer.start(1000) # Flash every 1000 milliseconds + + def toggle_flash(self): + current_style = self.select_btn.styleSheet() + if "background-color: DarkOrange;" in current_style: + self.select_btn.setStyleSheet("QPushButton { margin: 5px; padding: 5px; border-radius: 10px;}") + else: + self.select_btn.setStyleSheet("QPushButton { margin: 5px; padding: 5px; background-color: DarkOrange; border-radius: 10px;}") + + def update_counter_Label(self): + count = len(self.distance_preview.get_points()) + self.counter_label.setText(f"({count}/2)") + points_info = "\n".join([f"Point {i+1}: (x={x:.2f}, y={y:.2f}), Distance: {distance:.2f} meters)" + for i, (x, y, distance) in enumerate(self.distance_preview.get_points())]) + self.points_info_label.setText(points_info) + + #enable run pipeline button if 2 points are selected + if count == 2: + self.run_pipeline_btn.setEnabled(True) + self.update_status("Distance points selected. Ready to run pipeline.") + else: + #pass + self.run_pipeline_btn.setEnabled(False) + self.update_status("Waiting for distance points...") + self.info_labels["Status:"].setText("Waiting for distance points...") def run_full_pipeline(self): if not self.input_path: @@ -263,6 +589,14 @@ class SimpleTab(QWidget): self.setEnabled(False) self.progress_bar.setEnabled(True) # Keep progress bar enabled + #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()