Refactor AutoMatchGUI layout and enhance confidence display
This commit refines the layout of the AutoMatchGUI by adjusting the positioning of elements for better usability. The photo icon placement is now calculated based on the actual image dimensions, ensuring accurate positioning. Additionally, a new confidence badge feature is introduced, providing a visual representation of confidence levels alongside filenames. The layout adjustments improve the overall user experience by ensuring that images and related information are displayed more intuitively. The IdentifyGUI is also updated to reflect similar layout enhancements for consistency across the application.
This commit is contained in:
parent
38f931a7a7
commit
b75e12816c
@ -677,10 +677,12 @@ class AutoMatchGUI:
|
||||
matched_canvas.image = photo
|
||||
|
||||
# Add photo icon to the matched person face - exactly in corner
|
||||
# Use actual image dimensions instead of assuming 300x300
|
||||
# Compute top-left of the centered image for accurate placement
|
||||
actual_width, actual_height = pil_image.size
|
||||
top_left_x = 150 - (actual_width // 2)
|
||||
top_left_y = 150 - (actual_height // 2)
|
||||
self.gui_core.create_photo_icon(matched_canvas, matched_photo_path, icon_size=20,
|
||||
face_x=150, face_y=150,
|
||||
face_x=top_left_x, face_y=top_left_y,
|
||||
face_width=actual_width, face_height=actual_height,
|
||||
canvas_width=300, canvas_height=300)
|
||||
except Exception as e:
|
||||
@ -755,27 +757,21 @@ class AutoMatchGUI:
|
||||
|
||||
# Configure match frame for grid layout
|
||||
match_frame.columnconfigure(0, weight=0) # Checkbox column - fixed width
|
||||
match_frame.columnconfigure(1, weight=1) # Text column - expandable
|
||||
match_frame.columnconfigure(2, weight=0) # Image column - fixed width
|
||||
match_frame.columnconfigure(1, weight=0) # Image column - fixed width
|
||||
match_frame.columnconfigure(2, weight=1) # Text column - expandable
|
||||
|
||||
# Checkbox without text
|
||||
checkbox = ttk.Checkbutton(match_frame, variable=match_var)
|
||||
checkbox.grid(row=0, column=0, rowspan=2, sticky=(tk.W, tk.N), padx=(0, 5))
|
||||
match_checkboxes.append(checkbox)
|
||||
|
||||
# Create labels for confidence and filename
|
||||
confidence_label = ttk.Label(match_frame, text=f"{confidence_pct:.1f}% {confidence_desc}", font=("Arial", 9, "bold"))
|
||||
confidence_label.grid(row=0, column=1, sticky=tk.W, padx=(0, 10))
|
||||
|
||||
filename_label = ttk.Label(match_frame, text=f"📁 {match['unidentified_filename']}", font=("Arial", 8), foreground="gray")
|
||||
filename_label.grid(row=1, column=1, sticky=tk.W, padx=(0, 10))
|
||||
|
||||
# Unidentified face image
|
||||
# Unidentified face image now immediately after checkbox (right panel face to the right of checkbox)
|
||||
match_canvas = None
|
||||
if show_faces:
|
||||
style = ttk.Style()
|
||||
canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9'
|
||||
match_canvas = tk.Canvas(match_frame, width=100, height=100, bg=canvas_bg_color, highlightthickness=0)
|
||||
match_canvas.grid(row=0, column=2, rowspan=2, sticky=(tk.W, tk.N), padx=(10, 0))
|
||||
match_canvas.grid(row=0, column=1, rowspan=2, sticky=(tk.W, tk.N), padx=(5, 10))
|
||||
|
||||
unidentified_crop_path = self.face_processor._extract_face_crop(
|
||||
unidentified_photo_path,
|
||||
@ -791,15 +787,25 @@ class AutoMatchGUI:
|
||||
match_canvas.create_image(50, 50, image=photo)
|
||||
match_canvas.image = photo
|
||||
|
||||
# Add photo icon to the unidentified face
|
||||
# Add photo icon exactly at top-right of the face area
|
||||
self.gui_core.create_photo_icon(match_canvas, unidentified_photo_path, icon_size=15,
|
||||
face_x=50, face_y=50,
|
||||
face_x=0, face_y=0,
|
||||
face_width=100, face_height=100,
|
||||
canvas_width=100, canvas_height=100)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
match_canvas.create_text(50, 50, text="❌", fill="red")
|
||||
else:
|
||||
match_canvas.create_text(50, 50, text="🖼️", fill="gray")
|
||||
|
||||
# Confidence badge and filename to the right of image
|
||||
info_container = ttk.Frame(match_frame)
|
||||
info_container.grid(row=0, column=2, rowspan=2, sticky=(tk.W, tk.E))
|
||||
|
||||
badge = self.gui_core.create_confidence_badge(info_container, confidence_pct)
|
||||
badge.pack(anchor=tk.W)
|
||||
|
||||
filename_label = ttk.Label(info_container, text=f"📁 {match['unidentified_filename']}", font=("Arial", 8), foreground="gray")
|
||||
filename_label.pack(anchor=tk.W, pady=(2, 0))
|
||||
|
||||
# Update Select All / Clear All button states after populating
|
||||
update_match_control_buttons_state()
|
||||
@ -892,3 +898,4 @@ class AutoMatchGUI:
|
||||
data_cache['photo_paths'] = {row[0]: row[1] for row in cursor.fetchall()}
|
||||
|
||||
return data_cache
|
||||
|
||||
|
||||
45
gui_core.py
45
gui_core.py
@ -172,6 +172,51 @@ class GUICore:
|
||||
|
||||
return tooltip # Return tooltip reference for cleanup if needed
|
||||
|
||||
def create_confidence_badge(self, parent, confidence_pct: float):
|
||||
"""Create a colorful confidence badge with percentage and label.
|
||||
Returns a frame containing a small colored circle (with percent) and a text label.
|
||||
"""
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
|
||||
# Determine color and label
|
||||
if confidence_pct >= 80:
|
||||
color = "#27AE60" # green
|
||||
label = "Very High"
|
||||
text_color = "white"
|
||||
elif confidence_pct >= 70:
|
||||
color = "#F1C40F" # yellow
|
||||
label = "High"
|
||||
text_color = "black"
|
||||
elif confidence_pct >= 60:
|
||||
color = "#E67E22" # orange
|
||||
label = "Medium"
|
||||
text_color = "white"
|
||||
elif confidence_pct >= 50:
|
||||
color = "#E74C3C" # red
|
||||
label = "Low"
|
||||
text_color = "white"
|
||||
else:
|
||||
color = "#2C3E50" # dark blue/black
|
||||
label = "Very Low"
|
||||
text_color = "white"
|
||||
|
||||
badge_frame = ttk.Frame(parent)
|
||||
|
||||
# Draw circle sized to roughly match the label font height
|
||||
size = 14
|
||||
style = ttk.Style()
|
||||
bg_color = style.lookup('TFrame', 'background') or '#d9d9d9'
|
||||
canvas = tk.Canvas(badge_frame, width=size, height=size, highlightthickness=0, bg=bg_color)
|
||||
canvas.grid(row=0, column=0, padx=(0, 4))
|
||||
canvas.create_oval(1, 1, size-1, size-1, fill=color, outline=color)
|
||||
|
||||
# Text label right to the circle
|
||||
label_widget = ttk.Label(badge_frame, text=f"{int(round(confidence_pct))}% {label}", font=("Arial", 9, "bold"))
|
||||
label_widget.grid(row=0, column=1, sticky="w")
|
||||
|
||||
return badge_frame
|
||||
|
||||
def create_face_crop_image(self, photo_path: str, face_location: tuple,
|
||||
face_id: int, crop_size: int = 100) -> Optional[str]:
|
||||
"""Create a face crop image for display"""
|
||||
|
||||
@ -1539,12 +1539,23 @@ class IdentifyGUI:
|
||||
# Add to similar face variables list
|
||||
similar_face_vars.append((similar_face_id, match_var))
|
||||
|
||||
# Create labels for confidence and filename
|
||||
confidence_label = ttk.Label(match_frame, text=f"{confidence_pct:.1f}% {confidence_desc}", font=("Arial", 9, "bold"))
|
||||
confidence_label.grid(row=0, column=2, sticky=tk.W, padx=(0, 10))
|
||||
# Right panel requirement: image immediately to the right of checkbox
|
||||
# Create canvas for face image next to checkbox
|
||||
style = ttk.Style()
|
||||
canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9'
|
||||
match_canvas = tk.Canvas(match_frame, width=80, height=80, bg=canvas_bg_color, highlightthickness=0)
|
||||
match_canvas.grid(row=0, column=1, rowspan=2, sticky=(tk.W, tk.N), padx=(5, 10))
|
||||
|
||||
filename_label = ttk.Label(match_frame, text=f"📁 {filename}", font=("Arial", 8), foreground="gray")
|
||||
filename_label.grid(row=1, column=2, sticky=tk.W, padx=(0, 10))
|
||||
# Create labels container to the right of image
|
||||
info_container = ttk.Frame(match_frame)
|
||||
info_container.grid(row=0, column=2, rowspan=2, sticky=(tk.W, tk.E))
|
||||
|
||||
# Confidence badge
|
||||
badge = self.gui_core.create_confidence_badge(info_container, confidence_pct)
|
||||
badge.pack(anchor=tk.W)
|
||||
|
||||
filename_label = ttk.Label(info_container, text=f"📁 {filename}", font=("Arial", 8), foreground="gray")
|
||||
filename_label.pack(anchor=tk.W, pady=(2, 0))
|
||||
|
||||
# Face image (reusing auto-match image display)
|
||||
try:
|
||||
@ -1568,20 +1579,14 @@ class IdentifyGUI:
|
||||
# Extract face crop using existing method
|
||||
face_crop_path = self.face_processor._extract_face_crop(photo_path, face_data['location'], similar_face_id)
|
||||
if face_crop_path and os.path.exists(face_crop_path):
|
||||
# Create canvas for face image (like in auto-match)
|
||||
style = ttk.Style()
|
||||
canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9'
|
||||
match_canvas = tk.Canvas(match_frame, width=80, height=80, bg=canvas_bg_color, highlightthickness=0)
|
||||
match_canvas.grid(row=0, column=1, rowspan=2, sticky=(tk.W, tk.N), padx=(5, 10))
|
||||
|
||||
# Load and display image (reusing auto-match image loading)
|
||||
# Load and display image
|
||||
pil_image = Image.open(face_crop_path)
|
||||
pil_image.thumbnail((80, 80), Image.Resampling.LANCZOS)
|
||||
photo = ImageTk.PhotoImage(pil_image)
|
||||
match_canvas.create_image(40, 40, image=photo)
|
||||
match_canvas.image = photo # Keep reference
|
||||
|
||||
# Add photo icon to the similar face
|
||||
# Add photo icon exactly at the image's top-right corner
|
||||
self.gui_core.create_photo_icon(match_canvas, photo_path, icon_size=15,
|
||||
face_x=0, face_y=0,
|
||||
face_width=80, face_height=80,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user