A bunch of changes
This commit is contained in:
100
imageviewer.py
100
imageviewer.py
@@ -29,6 +29,7 @@ from PySide6.QtCore import (
|
||||
|
||||
from constants import (
|
||||
APP_CONFIG, DEFAULT_FACE_BOX_COLOR, DEFAULT_PET_BOX_COLOR, DEFAULT_VIEWER_SHORTCUTS,
|
||||
DEFAULT_BODY_BOX_COLOR,
|
||||
DEFAULT_OBJECT_BOX_COLOR, DEFAULT_LANDMARK_BOX_COLOR, FORCE_X11, ICON_THEME_VIEWER,
|
||||
ICON_THEME_VIEWER_FALLBACK, KSCREEN_DOCTOR_MARGIN, KWINOUTPUTCONFIG_PATH,
|
||||
VIEWER_AUTO_RESIZE_WINDOW_DEFAULT, VIEWER_FORM_MARGIN, VIEWER_LABEL,
|
||||
@@ -47,6 +48,9 @@ class FaceNameDialog(QDialog):
|
||||
if region_type == "Pet":
|
||||
self.setWindowTitle(UITexts.ADD_PET_TITLE)
|
||||
layout_label = UITexts.ADD_PET_LABEL
|
||||
elif region_type == "Body":
|
||||
self.setWindowTitle(UITexts.ADD_BODY_TITLE)
|
||||
layout_label = UITexts.ADD_BODY_LABEL
|
||||
elif region_type == "Object":
|
||||
self.setWindowTitle(UITexts.ADD_OBJECT_TITLE)
|
||||
layout_label = UITexts.ADD_OBJECT_LABEL
|
||||
@@ -441,6 +445,8 @@ class FaceCanvas(QLabel):
|
||||
face_color = QColor(face_color_str)
|
||||
pet_color_str = APP_CONFIG.get("pet_box_color", DEFAULT_PET_BOX_COLOR)
|
||||
pet_color = QColor(pet_color_str)
|
||||
body_color_str = APP_CONFIG.get("body_box_color", DEFAULT_BODY_BOX_COLOR)
|
||||
body_color = QColor(body_color_str)
|
||||
object_color_str = APP_CONFIG.get("object_box_color", DEFAULT_OBJECT_BOX_COLOR)
|
||||
object_color = QColor(object_color_str)
|
||||
landmark_color_str = APP_CONFIG.get("landmark_box_color",
|
||||
@@ -452,11 +458,14 @@ class FaceCanvas(QLabel):
|
||||
rect = self.map_from_source(face)
|
||||
|
||||
is_pet = face.get('type') == 'Pet'
|
||||
is_body = face.get('type') == 'Body'
|
||||
is_object = face.get('type') == 'Object'
|
||||
is_landmark = face.get('type') == 'Landmark'
|
||||
|
||||
if is_pet:
|
||||
color = pet_color
|
||||
elif is_body:
|
||||
color = body_color
|
||||
elif is_object:
|
||||
color = object_color
|
||||
elif is_landmark:
|
||||
@@ -677,8 +686,10 @@ class FaceCanvas(QLabel):
|
||||
elif event.button() == Qt.LeftButton:
|
||||
self.dragging = True
|
||||
self.drag_start_pos = event.globalPosition().toPoint()
|
||||
self.drag_start_scroll_x = self.viewer.scroll_area.horizontalScrollBar().value()
|
||||
self.drag_start_scroll_y = self.viewer.scroll_area.verticalScrollBar().value()
|
||||
self.drag_start_scroll_x = \
|
||||
self.viewer.scroll_area.horizontalScrollBar().value()
|
||||
self.drag_start_scroll_y = \
|
||||
self.viewer.scroll_area.verticalScrollBar().value()
|
||||
self.setCursor(Qt.ClosedHandCursor)
|
||||
event.accept()
|
||||
else:
|
||||
@@ -863,12 +874,15 @@ class FaceCanvas(QLabel):
|
||||
menu = QMenu(self)
|
||||
action_face = menu.addAction(UITexts.TYPE_FACE)
|
||||
action_pet = menu.addAction(UITexts.TYPE_PET)
|
||||
action_body = menu.addAction(UITexts.TYPE_BODY)
|
||||
action_object = menu.addAction(UITexts.TYPE_OBJECT)
|
||||
action_landmark = menu.addAction(UITexts.TYPE_LANDMARK)
|
||||
# Show menu at mouse release position
|
||||
res = menu.exec(event.globalPosition().toPoint())
|
||||
if res == action_pet:
|
||||
region_type = "Pet"
|
||||
elif res == action_body:
|
||||
region_type = "Body"
|
||||
elif res == action_object:
|
||||
region_type = "Object"
|
||||
elif res == action_landmark:
|
||||
@@ -885,6 +899,8 @@ class FaceCanvas(QLabel):
|
||||
if self.viewer.main_win:
|
||||
if region_type == "Pet":
|
||||
history_list = self.viewer.main_win.pet_names_history
|
||||
elif region_type == "Body":
|
||||
history_list = self.viewer.main_win.body_names_history
|
||||
elif region_type == "Object":
|
||||
history_list = self.viewer.main_win.object_names_history
|
||||
elif region_type == "Landmark":
|
||||
@@ -903,6 +919,8 @@ class FaceCanvas(QLabel):
|
||||
if self.viewer.main_win:
|
||||
if region_type == "Pet":
|
||||
self.viewer.main_win.pet_names_history = updated_history
|
||||
elif region_type == "Body":
|
||||
self.viewer.main_win.body_names_history = updated_history
|
||||
elif region_type == "Object":
|
||||
self.viewer.main_win.object_names_history = updated_history
|
||||
elif region_type == "Landmark":
|
||||
@@ -1192,6 +1210,7 @@ class ImageViewer(QWidget):
|
||||
"flip_vertical": self.toggle_flip_vertical,
|
||||
"detect_faces": self.run_face_detection,
|
||||
"detect_pets": self.run_pet_detection,
|
||||
"detect_bodies": self.run_body_detection,
|
||||
"fast_tag": self.show_fast_tag_menu,
|
||||
"rotate_right": lambda: self.apply_rotation(90, True),
|
||||
"rotate_left": lambda: self.apply_rotation(-90, True),
|
||||
@@ -1217,7 +1236,7 @@ class ImageViewer(QWidget):
|
||||
Optimized to update the existing list if possible, rather than
|
||||
rebuilding it entirely.
|
||||
"""
|
||||
if not self.filmstrip.isVisible():
|
||||
if self.filmstrip.isHidden():
|
||||
return
|
||||
|
||||
# --- OPTIMIZATION ---
|
||||
@@ -1887,9 +1906,14 @@ class ImageViewer(QWidget):
|
||||
zoom = int(self.controller.zoom_factor * 100)
|
||||
self.sb_info_label.setText(f"{w} x {h} px | {zoom}%")
|
||||
|
||||
# Use tags from controller's internal state
|
||||
# Use tags from metadata if provided (priority to avoid race conditions),
|
||||
# otherwise fallback to controller's internal state.
|
||||
tags_source = self.controller._current_tags
|
||||
if metadata and 'tags' in metadata:
|
||||
tags_source = metadata['tags']
|
||||
|
||||
display_tags = [t.strip().split('/')[-1]
|
||||
for t in self.controller._current_tags if t.strip()]
|
||||
for t in tags_source if t.strip()]
|
||||
self.sb_tags_label.setText(", ".join(display_tags))
|
||||
|
||||
@Slot(str, dict)
|
||||
@@ -2080,8 +2104,8 @@ class ImageViewer(QWidget):
|
||||
return False
|
||||
|
||||
menu = QMenu(self)
|
||||
action_del = menu.addAction(UITexts.DELETE_FACE)
|
||||
action_ren = menu.addAction(UITexts.RENAME_FACE_TITLE)
|
||||
action_del = menu.addAction(UITexts.DELETE_AREA_TITLE)
|
||||
action_ren = menu.addAction(UITexts.RENAME_AREA_TITLE)
|
||||
res = menu.exec(event.globalPos())
|
||||
|
||||
if res == action_del:
|
||||
@@ -2107,6 +2131,8 @@ class ImageViewer(QWidget):
|
||||
if self.main_win:
|
||||
if region_type == "Pet":
|
||||
history_list = self.main_win.pet_names_history
|
||||
elif region_type == "Body":
|
||||
history_list = self.main_win.body_names_history
|
||||
elif region_type == "Object":
|
||||
history_list = self.main_win.object_names_history
|
||||
elif region_type == "Landmark":
|
||||
@@ -2135,6 +2161,8 @@ class ImageViewer(QWidget):
|
||||
if self.main_win:
|
||||
if region_type == "Pet":
|
||||
self.main_win.pet_names_history = updated_history
|
||||
elif region_type == "Body":
|
||||
self.main_win.body_names_history = updated_history
|
||||
elif region_type == "Object":
|
||||
self.main_win.object_names_history = updated_history
|
||||
elif region_type == "Landmark":
|
||||
@@ -2185,6 +2213,9 @@ class ImageViewer(QWidget):
|
||||
{"text": UITexts.DETECT_PETS, "action": "detect_pets",
|
||||
"icon": "edit-image-face-recognize"},
|
||||
"separator",
|
||||
{"text": UITexts.DETECT_BODIES, "action": "detect_bodies",
|
||||
"icon": "edit-image-face-recognize"},
|
||||
"separator",
|
||||
{"text": UITexts.VIEWER_MENU_ROTATE, "icon": "transform-rotate",
|
||||
"submenu": [
|
||||
{"text": UITexts.VIEWER_MENU_ROTATE_LEFT,
|
||||
@@ -2491,6 +2522,61 @@ class ImageViewer(QWidget):
|
||||
if added_count > 0:
|
||||
self.controller.save_faces()
|
||||
|
||||
def run_body_detection(self):
|
||||
"""Runs body detection on the current image."""
|
||||
QApplication.setOverrideCursor(Qt.WaitCursor)
|
||||
try:
|
||||
new_bodies = self.controller.detect_bodies()
|
||||
finally:
|
||||
QApplication.restoreOverrideCursor()
|
||||
|
||||
if not new_bodies:
|
||||
return
|
||||
|
||||
IOU_THRESHOLD = 0.7
|
||||
added_count = 0
|
||||
for new_body in new_bodies:
|
||||
is_duplicate = False
|
||||
for existing_face in self.controller.faces:
|
||||
iou = self._calculate_iou(new_body, existing_face)
|
||||
if iou > IOU_THRESHOLD:
|
||||
is_duplicate = True
|
||||
break
|
||||
|
||||
if is_duplicate:
|
||||
continue
|
||||
|
||||
if not self.controller.show_faces:
|
||||
self.toggle_faces()
|
||||
|
||||
self.controller.faces.append(new_body)
|
||||
self.canvas.update()
|
||||
|
||||
w = self.canvas.width()
|
||||
h = self.canvas.height()
|
||||
self.scroll_area.ensureVisible(int(new_body.get('x', 0) * w),
|
||||
int(new_body.get('y', 0) * h), 50, 50)
|
||||
QApplication.processEvents()
|
||||
|
||||
# For bodies, we typically don't ask for a name immediately unless desired
|
||||
# Or we can treat it like pets/faces and ask. Let's ask.
|
||||
history = self.main_win.body_names_history if self.main_win else []
|
||||
full_tag, updated_history, ok = FaceNameDialog.get_name(
|
||||
self, history, main_win=self.main_win, region_type="Body")
|
||||
|
||||
if ok and full_tag:
|
||||
new_body['name'] = full_tag
|
||||
self.controller.toggle_tag(full_tag, True)
|
||||
if self.main_win:
|
||||
self.main_win.body_names_history = updated_history
|
||||
added_count += 1
|
||||
else:
|
||||
self.controller.faces.pop()
|
||||
self.canvas.update()
|
||||
|
||||
if added_count > 0:
|
||||
self.controller.save_faces()
|
||||
|
||||
def toggle_filmstrip(self):
|
||||
"""Shows or hides the filmstrip widget."""
|
||||
visible = not self.filmstrip.isVisible()
|
||||
|
||||
Reference in New Issue
Block a user