Skip to content
Snippets Groups Projects
Commit 34d72aaf authored by mhby1g21's avatar mhby1g21
Browse files

refactored material tab (much more managable file size/lines now)

parent 2248f5aa
No related branches found
No related tags found
1 merge request!4GDP 4.2.10 - Adding Debug mode to GUI.py to run individual modules
This commit is part of merge request !4. Comments created here will be created in the context of that merge request.
......@@ -5,6 +5,7 @@ import os
from tabs.config_tab import ConfigTab
from tabs.shifter_tab import ShifterTab
from tabs.depth_tab import DepthTab
from tabs.material_tab import MaterialTab
from utils.config_reader import ConfigReader
class ModuleDebugGUI(QMainWindow):
......@@ -38,6 +39,7 @@ class ModuleDebugGUI(QMainWindow):
self.tabs.addTab(ConfigTab(self.config_reader), "Configuration")
self.tabs.addTab(ShifterTab(self.config_reader), "Image Shifter")
self.tabs.addTab(DepthTab(self.config_reader), "MonoDepth Estimation")
self.tabs.addTab(MaterialTab(self.config_reader), "Material Recognition")
def main():
app = QApplication(sys.argv)
......
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
# tabs/material_tab.py
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGroupBox,
QMessageBox, QTabWidget)
from PyQt6.QtCore import Qt
import os
from PIL import Image, ImageTk
import subprocess
import shutil
class MaterialTab:
def __init__(self, notebook, config_reader):
self.tab = ttk.Frame(notebook)
notebook.add(self.tab, text='Material Recognition')
from utils.qt_widgets import (create_group_with_text, create_button_layout,
create_info_group, create_preview_group,
create_status_label, create_preview_grid,
update_status_indicator, get_status_text)
from utils.file_handlers import select_file, clean_directory, run_command
from utils.image_handlers import (update_preview, update_face_previews,
clear_previews)
class MaterialTab(QWidget):
def __init__(self, config_reader):
super().__init__()
self.config_reader = config_reader
self.input_file_path = None
......@@ -17,346 +22,169 @@ class MaterialTab:
self.material_recog_dir = self.config_reader.directories['materialRecogDir']
self.checkpoint_file = self.config_reader.file_paths['checkpointFile']
self.cubemap_dir = os.path.join(self.material_recog_dir, "cubemap_faces")
self.material_output_dir = os.path.join(self.material_recog_dir, "output", "cubemap_faces")
self.setup_ui()
self.verify_checkpoint()
def setup_ui(self):
# Split into left and right frames
left_frame = ttk.Frame(self.tab)
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
right_frame = ttk.Frame(self.tab)
right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)
self.setup_control_panel(left_frame)
self.setup_preview_panel(right_frame)
def setup_control_panel(self, parent):
# Control section
control_frame = ttk.LabelFrame(parent, text="Controls", padding="5")
control_frame.pack(fill=tk.X, pady=5)
# Input file selection
input_frame = ttk.Frame(control_frame)
input_frame.pack(fill=tk.X, pady=5)
ttk.Label(input_frame, text="Input file:").pack(side=tk.LEFT, padx=5)
self.input_label = ttk.Label(input_frame, text="No file selected")
self.input_label.pack(side=tk.LEFT, padx=5)
# Checkpoint file verification
checkpoint_frame = ttk.Frame(control_frame)
checkpoint_frame.pack(fill=tk.X, pady=5)
ttk.Label(checkpoint_frame, text="Checkpoint file:").pack(side=tk.LEFT, padx=5)
self.checkpoint_label = ttk.Label(
checkpoint_frame,
text="✓ Found" if os.path.exists(self.checkpoint_file) else "✗ Missing",
foreground="green" if os.path.exists(self.checkpoint_file) else "red"
)
self.checkpoint_label.pack(side=tk.LEFT, padx=5)
main_layout = QHBoxLayout(self)
main_layout.setContentsMargins(10, 10, 10, 10)
# Left panel (controls)
left_layout = QVBoxLayout()
self.setup_control_panel(left_layout)
main_layout.addLayout(left_layout)
# Right panel (preview)
right_layout = QVBoxLayout()
self.setup_preview_panel(right_layout)
main_layout.addLayout(right_layout)
def setup_control_panel(self, layout):
# Info display
info_rows = [
("Input file:", "No file selected"),
("Checkpoint:", "✓ Found" if os.path.exists(self.checkpoint_file) else "✗ Missing")
]
info_group, self.info_labels = create_info_group("Controls", info_rows)
layout.addWidget(info_group)
# Progress indicators
self.progress_frame = ttk.LabelFrame(control_frame, text="Progress", padding="5")
self.progress_frame.pack(fill=tk.X, pady=5)
# Split progress
split_frame = ttk.Frame(self.progress_frame)
split_frame.pack(fill=tk.X, pady=2)
ttk.Label(split_frame, text="Split 360:").pack(side=tk.LEFT, padx=5)
self.split_status = ttk.Label(split_frame, text="Not started")
self.split_status.pack(side=tk.LEFT, padx=5)
# Material recognition progress
recog_frame = ttk.Frame(self.progress_frame)
recog_frame.pack(fill=tk.X, pady=2)
ttk.Label(recog_frame, text="Material Recognition:").pack(side=tk.LEFT, padx=5)
self.recog_status = ttk.Label(recog_frame, text="Not started")
self.recog_status.pack(side=tk.LEFT, padx=5)
# Combine progress
combine_frame = ttk.Frame(self.progress_frame)
combine_frame.pack(fill=tk.X, pady=2)
ttk.Label(combine_frame, text="Combine Output:").pack(side=tk.LEFT, padx=5)
self.combine_status = ttk.Label(combine_frame, text="Not started")
self.combine_status.pack(side=tk.LEFT, padx=5)
# Control buttons
button_frame = ttk.Frame(control_frame)
button_frame.pack(fill=tk.X, pady=5)
ttk.Button(
button_frame,
text="Clean Working Dir",
command=self.clean_working_dir
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="Select Input",
command=self.select_input_file
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="Run Split 360",
command=self.run_split_360
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="Run Material Recognition",
command=self.run_material_recognition
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="Run Combine",
command=self.run_combine
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="Run All Steps",
command=self.run_all_steps
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="Clear Status",
command=self.clear_status
).pack(side=tk.RIGHT, padx=5)
# Status section
status_frame = ttk.LabelFrame(parent, text="Status", padding="5")
status_frame.pack(fill=tk.BOTH, expand=True, pady=5)
# Add scrollbar to status
status_scroll = ttk.Scrollbar(status_frame)
status_scroll.pack(side=tk.RIGHT, fill=tk.Y)
self.status_text = tk.Text(
status_frame,
height=10,
wrap=tk.WORD,
yscrollcommand=status_scroll.set
)
self.status_text.pack(fill=tk.BOTH, expand=True)
status_scroll.config(command=self.status_text.yview)
progress_group = QGroupBox("Progress")
progress_layout = QVBoxLayout(progress_group)
self.split_status = create_status_label("Split 360:", "Not started")
self.recognition_status = create_status_label("Material Recognition:", "Not started")
self.combine_status = create_status_label("Combine Output:", "Not started")
progress_layout.addLayout(self.split_status)
progress_layout.addLayout(self.recognition_status)
progress_layout.addLayout(self.combine_status)
layout.addWidget(progress_group)
# Buttons
buttons = [
("Clean Working Dir", self.clean_working_dir, 'left'),
("Select Input", self.select_input, 'left'),
("Run Split 360", self.run_split_360, 'left'),
("Run Recognition", self.run_material_recognition, 'left'),
("Run Combine", self.run_combine, 'left'),
("Run All Steps", self.run_all_steps, 'left'),
("Clear Status", lambda: self.status_text.clear(), 'right')
]
layout.addLayout(create_button_layout(*buttons))
# Status display
status_group, self.status_text = create_group_with_text("Status", 150)
layout.addWidget(status_group)
def setup_preview_panel(self, parent):
notebook = ttk.Notebook(parent)
notebook.pack(fill=tk.BOTH, expand=True)
def setup_preview_panel(self, layout):
preview_tabs = QTabWidget()
# Input/Output preview tab
io_frame = ttk.Frame(notebook)
notebook.add(io_frame, text='Input/Output')
io_tab = QWidget()
io_layout = QVBoxLayout(io_tab)
# Input preview
input_frame = ttk.LabelFrame(io_frame, text="Input Image")
input_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
input_group, self.input_preview = create_preview_group("Input Image")
output_group, self.output_preview = create_preview_group("Material Map")
self.input_preview = ttk.Label(input_frame)
self.input_preview.pack(padx=5, pady=5)
io_layout.addWidget(input_group)
io_layout.addWidget(output_group)
preview_tabs.addTab(io_tab, "Input/Output")
# Material map preview
output_frame = ttk.LabelFrame(io_frame, text="Material Map")
output_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# RGB faces preview tab
rgb_tab = QWidget()
rgb_layout = QVBoxLayout(rgb_tab)
self.output_preview = ttk.Label(output_frame)
self.output_preview.pack(padx=5, pady=5)
self.rgb_face_previews = {}
faces_layout = create_preview_grid(
['front', 'back', 'left', 'right', 'top', 'bottom'],
self.rgb_face_previews
)
rgb_layout.addLayout(faces_layout)
preview_tabs.addTab(rgb_tab, "RGB Cube Faces")
# RGB Cube faces preview tab
rgb_faces_frame = ttk.Frame(notebook)
notebook.add(rgb_faces_frame, text='RGB Cube Faces')
# Material faces preview tab
material_tab = QWidget()
material_layout = QVBoxLayout(material_tab)
# Create grid for RGB cube faces
self.rgb_face_previews = {}
face_names = ['front', 'back', 'left', 'right', 'top', 'bottom']
row = 0
col = 0
for face in face_names:
frame = ttk.LabelFrame(rgb_faces_frame, text=face)
frame.grid(row=row, column=col, padx=5, pady=5, sticky='nsew')
label = ttk.Label(frame)
label.pack(padx=5, pady=5)
self.rgb_face_previews[face] = label
col += 1
if col > 2: # 3 columns
col = 0
row += 1
# Configure grid weights for RGB faces
rgb_faces_frame.grid_columnconfigure(0, weight=1)
rgb_faces_frame.grid_columnconfigure(1, weight=1)
rgb_faces_frame.grid_columnconfigure(2, weight=1)
# Material Cube faces preview tab
material_faces_frame = ttk.Frame(notebook)
notebook.add(material_faces_frame, text='Material Cube Faces')
# Create grid for material cube faces
self.material_face_previews = {}
row = 0
col = 0
face_names = ['frontrgb', 'backrgb', 'leftrgb', 'rightrgb', 'toprgb', 'bottomrgb']
for face in face_names:
frame = ttk.LabelFrame(material_faces_frame, text=face)
frame.grid(row=row, column=col, padx=5, pady=5, sticky='nsew')
label = ttk.Label(frame)
label.pack(padx=5, pady=5)
self.material_face_previews[face] = label
col += 1
if col > 2: # 3 columns
col = 0
row += 1
# Configure grid weights for material faces
material_faces_frame.grid_columnconfigure(0, weight=1)
material_faces_frame.grid_columnconfigure(1, weight=1)
material_faces_frame.grid_columnconfigure(2, weight=1)
material_faces_layout = create_preview_grid(
['front', 'back', 'left', 'right', 'top', 'bottom'],
self.material_face_previews
)
material_layout.addLayout(material_faces_layout)
preview_tabs.addTab(material_tab, "Material Cube Faces")
def clean_working_dir(self):
"""Clean all working directories"""
try:
directories_to_clean = [
# Main cubemap_faces directory
self.cubemap_dir,
# Output cubemap_faces directory for material maps
os.path.join(self.material_recog_dir, "output", "cubemap_faces"),
]
layout.addWidget(preview_tabs)
for directory in directories_to_clean:
if os.path.exists(directory):
self.update_status(f"Cleaning directory: {directory}")
shutil.rmtree(directory)
# Recreate directories
os.makedirs(directory, exist_ok=True)
self.update_status("All working directories cleaned")
# Reset status indicators
self.split_status.config(text="Not started")
self.recog_status.config(text="Not started")
self.combine_status.config(text="Not started")
# Clear all previews
self.clear_previews()
except Exception as e:
error_msg = f"Error cleaning directories: {str(e)}"
self.update_status(error_msg)
messagebox.showerror("Error", error_msg)
def clear_previews(self):
"""Clear all image previews"""
self.input_preview.configure(image='')
self.output_preview.configure(image='')
for face_preview in self.rgb_face_previews.values():
face_preview.configure(image='')
for face_preview in self.material_face_previews.values():
face_preview.configure(image='')
def select_input_file(self):
filepath = filedialog.askopenfilename(
filetypes=[("Image files", "*.png *.jpg *.jpeg")]
def select_input(self):
file_path = select_file(
self,
"Select Input Image",
"Images (*.png *.jpg *.jpeg)"
)
if filepath:
self.input_file_path = os.path.normpath(filepath)
self.input_label.config(text=os.path.basename(filepath))
self.update_status(f"Selected input file: {filepath}")
self.update_input_preview()
# Reset status indicators
self.split_status.config(text="Not started")
self.recog_status.config(text="Not started")
self.combine_status.config(text="Not started")
if file_path:
self.input_file_path = file_path
self.info_labels["Input file:"].setText(os.path.basename(file_path))
self.update_status(f"Selected input file: {file_path}")
update_preview(self.input_preview, file_path,
error_callback=self.update_status)
self.reset_status_indicators()
def clean_working_dir(self):
dirs_to_clean = [self.cubemap_dir, self.material_output_dir]
for directory in dirs_to_clean:
if not clean_directory(directory, self.update_status):
QMessageBox.critical(self, "Error", f"Failed to clean directory: {directory}")
return
clear_previews(
self.input_preview,
self.output_preview,
self.rgb_face_previews,
self.material_face_previews
)
self.reset_status_indicators()
def run_split_360(self):
if not self.input_file_path:
messagebox.showwarning("Warning", "Please select an input file first")
QMessageBox.warning(self, "Warning", "Please select an input file first")
return
try:
self.update_status("Running 360 image splitting...")
self.split_status.config(text="Running...", foreground="orange")
update_status_indicator(self.split_status, "Running")
# Change to material recognition directory
original_dir = os.getcwd()
os.chdir(self.material_recog_dir)
# Run split_img.py
cmd = f'''call "{self.config_reader.config["condaDir"]}\\condabin\\activate.bat" {self.config_reader.config["materialEnv"]} && python split_img.py "{self.input_file_path}" && call "{self.config_reader.config["condaDir"]}\\condabin\\deactivate.bat"'''
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
text=True
)
stdout, stderr = process.communicate()
success, _ = run_command(self, cmd, self.update_status)
# Change back to original directory
os.chdir(original_dir)
if process.returncode == 0:
self.update_status("Split 360 completed successfully")
self.split_status.config(text="✓ Complete", foreground="green")
self.update_face_previews()
if success:
update_status_indicator(self.split_status, "Complete")
self.update_face_previews('rgb')
else:
self.update_status(f"Split 360 failed:\n{stderr}")
self.split_status.config(text="✗ Failed", foreground="red")
raise Exception(stderr)
except Exception as e:
self.update_status(f"Error in split 360: {str(e)}")
self.split_status.config(text="✗ Failed", foreground="red")
messagebox.showerror("Error", f"Split 360 failed: {str(e)}")
def run_command(self, cmd, description):
"""Run a single command and return its output"""
self.update_status(f"Executing {description}:\n{cmd}")
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
text=True
)
stdout, stderr = process.communicate()
if process.returncode != 0:
self.update_status(f"Error in {description}:\n{stderr}")
raise Exception(f"{description} failed: {stderr}")
if stdout:
self.update_status(f"{description} output:\n{stdout}")
return process.returncode == 0
update_status_indicator(self.split_status, "Failed")
def run_material_recognition(self):
if not os.path.exists(self.cubemap_dir):
messagebox.showwarning("Warning", "Please run Split 360 first")
QMessageBox.warning(self, "Warning", "Please run Split 360 first")
return
try:
self.update_status("Running material recognition...")
self.recog_status.config(text="Running...", foreground="orange")
update_status_indicator(self.recognition_status, "Running")
# Save current directory
original_dir = os.getcwd()
# Change to material recognition directory
os.chdir(self.material_recog_dir)
# Combine conda activation and Python command into a single command using cmd /c
material_cmd = (
cmd = (
f'cmd /c ""{self.config_reader.config["condaDir"]}\\Scripts\\activate.bat" {self.config_reader.config["materialEnv"]} && '
f'python train_sota.py --data-root "./datasets" '
f'--batch-size 1 --tag dpglt --gpus 1 --num-nodes 1 '
......@@ -365,293 +193,79 @@ class MaterialTab:
f'--infer "{self.material_recog_dir}/cubemap_faces/"'
)
self.update_status(f"Executing command:\n{material_cmd}")
success, _ = run_command(self, cmd, self.update_status)
process = subprocess.Popen(
material_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
text=True
)
stdout, stderr = process.communicate()
if stdout:
self.update_status("\nOutput:\n" + stdout)
if stderr:
self.update_status("\nError output:\n" + stderr)
# Check error level
if process.returncode != 0:
self.update_status("Error: Material recognition failed. Please check the output above for more details.")
raise Exception(stderr if stderr else "Material recognition failed")
self.update_status("Material recognition completed successfully")
self.recog_status.config(text="✓ Complete", foreground="green")
except Exception as e:
self.update_status(f"Error in material recognition: {str(e)}")
self.recog_status.config(text="✗ Failed", foreground="red")
messagebox.showerror("Error", f"Material recognition failed: {str(e)}")
finally:
self.update_material_face_previews()
if original_dir:
os.chdir(original_dir)
def verify_input_directory(self):
"""Verify that the input directory has the correct files"""
required_files = ['front.png', 'back.png', 'left.png', 'right.png', 'top.png', 'bottom.png']
missing_files = []
for file in required_files:
if not os.path.exists(os.path.join(self.cubemap_dir, file)):
missing_files.append(file)
if missing_files:
self.update_status("Missing required files:")
for file in missing_files:
self.update_status(f"- {file}")
return False
self.update_status("All required input files present")
return True
def verify_working_directory(self):
"""Verify that we're in the correct directory with required files"""
required_paths = [
"./datasets",
self.checkpoint_file,
"train_sota.py"
]
missing_paths = []
for path in required_paths:
if not os.path.exists(path):
missing_paths.append(path)
if missing_paths:
self.update_status("Missing required paths:")
for path in missing_paths:
self.update_status(f"- {path}")
return False
self.update_status("All required paths present")
return True
# Add a method to verify conda environment
def verify_conda_env(self):
"""Verify that the conda environment exists"""
try:
cmd = f'call "{self.config_reader.config["condaDir"]}\\condabin\\conda.bat" env list'
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
text=True
)
stdout, stderr = process.communicate()
if process.returncode == 0:
env_name = self.config_reader.config["materialEnv"]
if env_name in stdout:
self.update_status(f"Found conda environment: {env_name}")
return True
else:
self.update_status(f"Conda environment not found: {env_name}")
return False
if success:
update_status_indicator(self.recognition_status, "Complete")
self.update_face_previews('material')
else:
self.update_status(f"Failed to list conda environments: {stderr}")
return False
except Exception as e:
self.update_status(f"Error checking conda environment: {str(e)}")
return False
update_status_indicator(self.recognition_status, "Failed")
def run_combine(self):
try:
self.update_status("Running combine step...")
self.combine_status.config(text="Running...", foreground="orange")
update_status_indicator(self.combine_status, "Running")
# Change to material recognition directory
original_dir = os.getcwd()
os.chdir(self.material_recog_dir)
# Run combine script
cmd = f'''call "{self.config_reader.config["condaDir"]}\\condabin\\activate.bat" {self.config_reader.config["materialEnv"]} && python combine_img.py && call "{self.config_reader.config["condaDir"]}\\condabin\\deactivate.bat"'''
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
text=True
)
stdout, stderr = process.communicate()
success, _ = run_command(self, cmd, self.update_status)
# Change back to original directory
os.chdir(original_dir)
if process.returncode == 0:
self.update_status("Combine step completed successfully")
self.combine_status.config(text="✓ Complete", foreground="green")
self.update_output_preview()
if success:
update_status_indicator(self.combine_status, "Complete")
output_path = os.path.join(
self.config_reader.directories['edgeNetDir'],
'Data', 'Input', 'material.png'
)
update_preview(self.output_preview, output_path,
error_callback=self.update_status)
else:
self.update_status(f"Combine step failed:\n{stderr}")
self.combine_status.config(text="✗ Failed", foreground="red")
raise Exception(stderr)
except Exception as e:
self.update_status(f"Error in combine step: {str(e)}")
self.combine_status.config(text="✗ Failed", foreground="red")
messagebox.showerror("Error", f"Combine step failed: {str(e)}")
update_status_indicator(self.combine_status, "Failed")
def run_all_steps(self):
"""Run all steps in sequence"""
if not self.input_file_path:
messagebox.showwarning("Warning", "Please select an input file first")
QMessageBox.warning(self, "Warning", "Please select an input file first")
return
try:
# Run all steps
self.run_split_360()
if self.split_status.cget("text") == "Complete":
if get_status_text(self.split_status) == "Complete":
self.run_material_recognition()
if self.recog_status.cget("text") == "Complete":
if get_status_text(self.recognition_status) == "Complete":
self.run_combine()
except Exception as e:
self.update_status(f"Error in pipeline: {str(e)}")
messagebox.showerror("Error", f"Pipeline failed: {str(e)}")
def update_status(self, message):
self.status_text.insert(tk.END, f"{message}\n")
self.status_text.see(tk.END)
def clear_status(self):
self.status_text.delete(1.0, tk.END)
def update_input_preview(self):
"""Update the input image preview"""
if self.input_file_path and os.path.exists(self.input_file_path):
try:
preview_size = (300, 150) # Adjust size as needed for 360 image
input_img = Image.open(self.input_file_path)
input_img.thumbnail(preview_size)
input_photo = ImageTk.PhotoImage(input_img)
self.input_preview.configure(image=input_photo)
self.input_preview.image = input_photo
except Exception as e:
self.update_status(f"Failed to load input preview: {str(e)}")
def update_rgb_face_previews(self):
"""Update the RGB cube face previews"""
preview_size = (150, 150)
face_names = {
'front': 'front',
'back': 'back',
'left': 'left',
'right': 'right',
'top': 'top',
'bottom': 'bottom'
}
for face, filename in face_names.items():
face_path = os.path.join(self.cubemap_dir, f"{filename}.png")
if os.path.exists(face_path):
try:
face_img = Image.open(face_path)
face_img.thumbnail(preview_size)
face_photo = ImageTk.PhotoImage(face_img)
self.rgb_face_previews[face].configure(image=face_photo)
self.rgb_face_previews[face].image = face_photo
except Exception as e:
self.update_status(f"Failed to load RGB {face} preview: {str(e)}")
def update_material_face_previews(self):
"""Update the material map cube face previews"""
preview_size = (150, 150)
material_dir = os.path.join(self.material_recog_dir, "output", "cubemap_faces")
face_names = {
'frontrgb': 'frontrgb',
'backrgb': 'backrgb',
'leftrgb': 'leftrgb',
'rightrgb': 'rightrgb',
'toprgb': 'toprgb',
'bottomrgb': 'bottomrgb'
}
for face, filename in face_names.items():
face_path = os.path.join(material_dir, f"{filename}.png")
if os.path.exists(face_path):
try:
face_img = Image.open(face_path)
face_img.thumbnail(preview_size)
face_photo = ImageTk.PhotoImage(face_img)
self.material_face_previews[face].configure(image=face_photo)
self.material_face_previews[face].image = face_photo
except Exception as e:
self.update_status(f"Failed to load material {face} preview: {str(e)}")
def update_face_previews(self):
"""Update both RGB and material cube face previews"""
self.update_rgb_face_previews()
self.update_material_face_previews()
"""Update the material map cube face previews"""
preview_size = (150, 150)
material_dir = os.path.join(self.material_recog_dir, "output", "cubemap_faces")
face_names = {
'front': 'front',
'back': 'back',
'left': 'left',
'right': 'right',
'top': 'top',
'bottom': 'bottom'
}
for face, filename in face_names.items():
face_path = os.path.join(material_dir, f"{filename}.png")
if os.path.exists(face_path):
try:
face_img = Image.open(face_path)
face_img.thumbnail(preview_size)
face_photo = ImageTk.PhotoImage(face_img)
self.material_face_previews[face].configure(image=face_photo)
self.material_face_previews[face].image = face_photo
except Exception as e:
self.update_status(f"Failed to load material {face} preview: {str(e)}")
def update_output_preview(self):
"""Update the material map preview"""
try:
# First check in EdgeNet Input directory
output_path = os.path.join(
self.config_reader.directories['edgeNetDir'],
'Data',
'Input',
'material.png'
self.status_text.append(message)
scrollbar = self.status_text.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum())
def reset_status_indicators(self):
for status in [self.split_status, self.recognition_status, self.combine_status]:
update_status_indicator(status, "Not started")
def update_face_previews(self, preview_type='rgb'):
if preview_type == 'rgb':
update_face_previews(
self.rgb_face_previews,
self.cubemap_dir,
'.png',
self.update_status
)
else:
update_face_previews(
self.material_face_previews,
self.material_output_dir,
'rgb.png',
self.update_status
)
if not os.path.exists(output_path):
self.update_status("Material map not found in expected location")
return
preview_size = (300, 150) # Adjust size for 360 image
output_img = Image.open(output_path)
output_img.thumbnail(preview_size)
output_photo = ImageTk.PhotoImage(output_img)
self.output_preview.configure(image=output_photo)
self.output_preview.image = output_photo
except Exception as e:
self.update_status(f"Failed to load material map preview: {str(e)}")
def verify_checkpoint(self):
"""Verify that the checkpoint file exists"""
if not os.path.exists(self.checkpoint_file):
self.update_status("Warning: Checkpoint file not found!")
self.checkpoint_label.config(text="✗ Missing", foreground="red")
return False
self.checkpoint_label.config(text="✓ Found", foreground="green")
return True
\ No newline at end of file
exists = os.path.exists(self.checkpoint_file)
self.info_labels["Checkpoint:"].setText("✓ Found" if exists else "✗ Missing")
self.info_labels["Checkpoint:"].setStyleSheet(
"color: green" if exists else "color: red")
return exists
\ No newline at end of file
......@@ -75,3 +75,31 @@ def update_preview(preview_label, image_path, max_size=300, error_callback=None)
preview_label.clear()
if error_callback:
error_callback(f"Image not found: {image_path}")
def update_face_previews(preview_dict, src_dir, suffix='', error_callback=None):
"""
Updates a dictionary of face preview labels with images from directory.
Args:
preview_dict: Dictionary of face preview labels
src_dir: Directory containing face images
suffix: Suffix for face image filenames
error_callback: Optional callback function for error handling
"""
for face, preview in preview_dict.items():
face_path = os.path.join(src_dir, face + suffix)
update_preview(preview, face_path, error_callback=error_callback)
def clear_previews(*preview_widgets):
"""
Clears multiple preview widgets.
Args:
preview_widgets: List of preview widgets to clear
"""
for widget in preview_widgets:
if isinstance(widget, dict):
for preview in widget.values():
preview.clear()
else:
widget.clear()
\ No newline at end of file
......@@ -100,3 +100,86 @@ def create_preview_group(title):
preview.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(preview)
return group, preview
def create_status_label(label_text, initial_status="Not started"):
"""
Creates a status indicator layout with label and status.
Args:
label_text: Text for the label
initial_status: Initial status text
Returns:
QHBoxLayout layout with label and status
"""
layout = QHBoxLayout()
label = QLabel(label_text)
status = QLabel(initial_status)
layout.addWidget(label)
layout.addWidget(status, stretch=1)
return layout
def create_preview_grid(face_names, preview_dict, cols=3):
"""
Creates a grid layout of preview groups for cubemap faces.
Args:
face_names: List of face names
preview_dict: Dictionary to store preview widgets
cols: Number of columns
Returns:
QVBoxLayout layout with preview groups in grids for cubemap faces
"""
grid = QVBoxLayout()
row_layout = QHBoxLayout()
count = 0
for face in face_names:
group, preview = create_preview_group(face)
preview_dict[face] = preview
row_layout.addWidget(group)
count += 1
if count % cols == 0:
grid.addLayout(row_layout)
row_layout = QHBoxLayout()
if count % cols != 0:
grid.addLayout(row_layout)
return grid
def update_status_indicator(status_layout, state):
"""
Updates a status indicator with new state and color.
Args:
status_layout: QHBoxLayout layout with label and status
state: New status text
"""
label = status_layout.itemAt(1).widget()
states = {
"Running": ("Running...", "orange"),
"Complete": ("✓ Complete", "green"),
"Failed": ("✗ Failed", "red"),
"Not started": ("Not started", "black")
}
if state in states:
text, color = states[state]
label.setText(text)
label.setStyleSheet(f"color: {color}")
else:
label.setText(state)
label.setStyleSheet("")
def get_status_text(status_layout):
"""
Gets the current status text without markers.
Args:
status_layout: QHBoxLayout layout with label and status
Returns:
str: Current status text
"""
text = status_layout.itemAt(1).widget().text()
return text.replace("", "").replace("", "")
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment