Skip to content
Snippets Groups Projects
Commit 4b367be9 authored by mhz1g21's avatar mhz1g21
Browse files

added ClickableLabel for interactive point selection; enhanced SimpleTab with...

added ClickableLabel for interactive point selection; enhanced SimpleTab with image distance section; added scrollbar
parent 5fced666
Branches
No related tags found
1 merge request!8enhanced UI: improved styling for main window, tabs, and controls; updated...
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
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout,
QGroupBox, QCheckBox, QMessageBox, QPushButton,
QProgressBar,QComboBox,QLabel)
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
......@@ -150,13 +151,23 @@ class SimpleTab(QWidget):
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.setup_ui(self.scroll_content)
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")
......@@ -164,7 +175,7 @@ class SimpleTab(QWidget):
QGroupBox {
font-weight: bold;
border: 2px solid grey;
border-radius: 10px;
border-radius: 20px;
margin-top: 10px;
background-color: #3e3e3e;
padding: 15px;
......@@ -330,6 +341,67 @@ class SimpleTab(QWidget):
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", 300)
......@@ -337,7 +409,7 @@ class SimpleTab(QWidget):
QGroupBox {
font-weight: bold;
border: 2px solid grey;
border-radius: 10px;
border-radius: 20px;
margin-top: 10px;
background-color: #3e3e3e;
padding: 20px;
......@@ -369,7 +441,7 @@ class SimpleTab(QWidget):
QGroupBox {
font-weight: bold;
border: 2px solid grey;
border-radius: 10px;
border-radius: 20px;
margin-top: 10px;
background-color: #3e3e3e;
padding: 20px;
......@@ -446,9 +518,15 @@ 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
......@@ -471,6 +549,21 @@ class SimpleTab(QWidget):
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)
def run_full_pipeline(self):
if not self.input_path:
QMessageBox.warning(self, "Warning", "Please select an input file first")
......@@ -494,6 +587,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()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment