File size: 3,216 Bytes
b400ace
 
 
 
 
8c9c413
 
 
 
 
 
 
 
 
b400ace
 
 
 
8c9c413
 
 
 
 
 
b400ace
 
 
 
 
 
 
 
 
 
 
8c9c413
b400ace
 
 
 
 
8c9c413
 
b400ace
 
 
 
 
 
 
8c9c413
 
 
 
 
 
 
 
 
 
 
b400ace
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c9c413
b400ace
 
 
 
 
 
 
 
 
 
 
 
 
8c9c413
 
 
 
 
 
b400ace
 
 
 
 
 
 
 
8c9c413
b400ace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from dataclasses import dataclass
import cv2
from src.logger import logger
from src.utils.image import ImageUtils

# ✅ Safe import for headless environments
try:
    from screeninfo import get_monitors
    monitor_window = get_monitors()[0]
    SCREEN_WIDTH, SCREEN_HEIGHT = monitor_window.width, monitor_window.height
except Exception as e:
    # Headless fallback — e.g., Hugging Face Spaces, servers, CI
    print(f"[Headless Mode] No monitor detected. Using default size. Error: {e}")
    SCREEN_WIDTH, SCREEN_HEIGHT = 1920, 1080


@dataclass
class ImageMetrics:
    # Window dimensions
    window_width: int = SCREEN_WIDTH
    window_height: int = SCREEN_HEIGHT
    # For positioning image windows
    window_x: int = 0
    window_y: int = 0
    reset_pos = [0, 0]


class InteractionUtils:
    """Perform primary functions such as displaying images and reading responses"""

    image_metrics = ImageMetrics()

    @staticmethod
    def show(name, origin, pause=1, resize=False, reset_pos=None, config=None):
        image_metrics = InteractionUtils.image_metrics

        if origin is None:
            logger.info(f"'{name}' - NoneType image to show!")
            if pause:
                cv2.destroyAllWindows()
            return

        # Resize if required
        if resize:
            if not config:
                raise Exception("config not provided for resizing the image to show")
            img = ImageUtils.resize_util(origin, config.dimensions.display_width)
        else:
            img = origin

        # Try to show the image only if display is available
        try:
            if not is_window_available(name):
                cv2.namedWindow(name)
            cv2.imshow(name, img)
            cv2.moveWindow(name, image_metrics.window_x, image_metrics.window_y)
        except cv2.error:
            # Skip visualization entirely in headless environments
            logger.info(f"Skipping cv2.imshow for '{name}' (headless mode).")

        # Update next window position
        h, w = img.shape[:2]
        margin = 25
        w += margin
        h += margin
        w, h = w // 2, h // 2
        if image_metrics.window_x + w > image_metrics.window_width:
            image_metrics.window_x = 0
            if image_metrics.window_y + h > image_metrics.window_height:
                image_metrics.window_y = 0
            else:
                image_metrics.window_y += h
        else:
            image_metrics.window_x += w

        if pause:
            logger.info(f"Showing '{name}' (press Q to continue, Ctrl+C to exit)")
            wait_q()
            InteractionUtils.image_metrics.window_x = 0
            InteractionUtils.image_metrics.window_y = 0


@dataclass
class Stats:
    files_moved = 0
    files_not_moved = 0


def wait_q():
    esc_key = 27
    try:
        while cv2.waitKey(1) & 0xFF not in [ord("q"), esc_key]:
            pass
        cv2.destroyAllWindows()
    except cv2.error:
        # Skip in headless mode
        pass


def is_window_available(name: str) -> bool:
    """Checks if a window is available"""
    try:
        cv2.getWindowProperty(name, cv2.WND_PROP_VISIBLE)
        return True
    except Exception:
        return False