154 lines
6.1 KiB
Python
154 lines
6.1 KiB
Python
# display.py
|
|
"""
|
|
This module manages the display of images using OpenCV.
|
|
It handles window creation, image updates, and mouse event callbacks.
|
|
"""
|
|
|
|
import cv2
|
|
import logging
|
|
import numpy as np
|
|
import config # Import the config module
|
|
import queue # Import the queue module
|
|
|
|
class DisplayManager:
|
|
"""
|
|
A class to manage the display of images using OpenCV.
|
|
"""
|
|
def __init__(self, app, sar_queue, mouse_queue, sar_x, sar_y, mfd_x, mfd_y):
|
|
"""
|
|
Initializes the DisplayManager.
|
|
|
|
Args:
|
|
app (App): The main application instance.
|
|
sar_queue (queue.Queue): The queue for SAR images.
|
|
mouse_queue (queue.Queue): The queue for mouse coordinates.
|
|
sar_x (int): The x-coordinate of the SAR window.
|
|
sar_y (int): The y-coordinate of the SAR window.
|
|
mfd_x (int): The x-coordinate of the MFD window.
|
|
mfd_y (int): The y-coordinate of the MFD window.
|
|
"""
|
|
self.app = app
|
|
self.sar_queue = sar_queue
|
|
self.mouse_queue = mouse_queue
|
|
self.sar_x = sar_x
|
|
self.sar_y = sar_y
|
|
self.mfd_x = mfd_x
|
|
self.mfd_y = mfd_y
|
|
self.sar_window_initialized = False
|
|
self.mfd_window_initialized = False
|
|
self.sar_mouse_callback_set = False # Flag to track if the callback has been set
|
|
self.last_mouse_update = 0 # Last time the mouse position was updated
|
|
|
|
def show_mfd_image(self, image):
|
|
"""
|
|
Displays the MFD image in an OpenCV window.
|
|
|
|
Args:
|
|
image (numpy.ndarray): The MFD image to display.
|
|
"""
|
|
try:
|
|
# Create and move window only once
|
|
if not self.mfd_window_initialized:
|
|
cv2.imshow("MFD", image)
|
|
try:
|
|
cv2.moveWindow("MFD", self.mfd_x, self.mfd_y)
|
|
self.mfd_window_initialized = True
|
|
except cv2.error as e:
|
|
print(f"Error moving MFD window on initialization: {e}")
|
|
logging.error(f"Error moving MFD window on initialization: {e}")
|
|
else:
|
|
cv2.imshow("MFD", image) # Just update the image
|
|
except Exception as e:
|
|
print(f"Error displaying MFD image: {e}")
|
|
logging.exception(f"Error displaying MFD image: {e}")
|
|
|
|
def show_sar_image(self, image):
|
|
"""
|
|
Displays the SAR image in an OpenCV window.
|
|
|
|
Args:
|
|
image (numpy.ndarray): The SAR image to display.
|
|
"""
|
|
if image is None or not isinstance(image, np.ndarray) or image.size == 0 or image.shape[0] == 0 or image.shape[1] == 0:
|
|
print("Error: Invalid SAR image dimensions. Skipping display.")
|
|
logging.error("Error: Invalid SAR image dimensions. Skipping display.")
|
|
return # Skip
|
|
|
|
try:
|
|
# Create and move window only once
|
|
if not self.sar_window_initialized:
|
|
cv2.imshow("SAR", image)
|
|
try:
|
|
cv2.moveWindow("SAR", self.sar_x, self.sar_y)
|
|
self.sar_window_initialized = True
|
|
except cv2.error as e:
|
|
print(f"Error moving SAR window on initialization: {e}")
|
|
logging.error(f"Error moving SAR window on initialization: {e}")
|
|
|
|
# Set mouse callback *after* the window is created
|
|
cv2.setMouseCallback("SAR", self.sar_mouse_callback)
|
|
self.sar_mouse_callback_set = True
|
|
|
|
else:
|
|
cv2.imshow("SAR", image) # Just update the image
|
|
except Exception as e:
|
|
print(f"Error displaying SAR image: {e}")
|
|
logging.exception(f"Error displaying SAR image: {e}")
|
|
|
|
def sar_mouse_callback(self, event, x, y, flags, param):
|
|
"""
|
|
Callback function for mouse events on the SAR window.
|
|
Calculates the latitude and longitude based on the mouse coordinates and puts them in the queue.
|
|
|
|
Args:
|
|
event (int): The type of mouse event.
|
|
x (int): The x-coordinate of the mouse pointer.
|
|
y (int): The y-coordinate of the mouse pointer.
|
|
flags (int): Any flags passed by the event.
|
|
param (None): Any extra parameters passed by the event.
|
|
"""
|
|
if event == cv2.EVENT_MOUSEMOVE:
|
|
# Convert pixel coordinates to normalized coordinates (0.0 - 1.0)
|
|
normalized_x = x / self.app.sar_display_width
|
|
normalized_y = y / self.app.sar_display_height
|
|
|
|
# Convert normalized coordinates to kilometers from the center
|
|
km_x = (normalized_x - 0.5) * config.SAR_IMAGE_SIZE_KM
|
|
km_y = (0.5 - normalized_y) * config.SAR_IMAGE_SIZE_KM # Y axis is inverted
|
|
|
|
# Convert kilometers to latitude and longitude offset
|
|
lat_offset = km_y / 111.0 # Approximate km to latitude conversion
|
|
lon_offset = km_x / (111.0 * np.cos(np.radians(config.SAR_CENTER_LAT))) # Approximate km to longitude
|
|
|
|
# Calculate latitude and longitude
|
|
latitude = config.SAR_CENTER_LAT + lat_offset
|
|
longitude = config.SAR_CENTER_LON + lon_offset
|
|
|
|
# Put the coordinates in the queue
|
|
try:
|
|
self.sar_queue.put((latitude, longitude), block=False)
|
|
except queue.Full:
|
|
pass # Drop value
|
|
|
|
def process_sar_queue(self):
|
|
"""
|
|
This function get the new Sar image from queue and displays
|
|
"""
|
|
try:
|
|
image = self.sar_queue.get(block=False)
|
|
if isinstance(image, np.ndarray):
|
|
self.show_sar_image(image)
|
|
except queue.Empty:
|
|
pass
|
|
|
|
def process_mouse_queue(self):
|
|
"""Processes the mouse coordinate queue and updates the Tkinter label."""
|
|
try:
|
|
latitude, longitude = self.mouse_queue.get(block=False)
|
|
# Limit the update rate to 10 times per second (100 ms interval)
|
|
current_time = time.time()
|
|
if current_time - self.last_mouse_update >= 0.1:
|
|
self.app.update_mouse_latlon_label(latitude, longitude)
|
|
self.last_mouse_update = current_time
|
|
except queue.Empty:
|
|
pass |