correct dim for sar window, auto delete older kml files
This commit is contained in:
parent
d367985d26
commit
713c761521
12
app.py
12
app.py
@ -20,6 +20,7 @@ import sys
|
|||||||
import socket # Required for network setup
|
import socket # Required for network setup
|
||||||
from typing import Optional, Tuple, Any, Dict, TYPE_CHECKING
|
from typing import Optional, Tuple, Any, Dict, TYPE_CHECKING
|
||||||
import datetime
|
import datetime
|
||||||
|
import cv2
|
||||||
|
|
||||||
# --- Third-party imports ---
|
# --- Third-party imports ---
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
@ -60,6 +61,7 @@ from utils import (
|
|||||||
decimal_to_dms,
|
decimal_to_dms,
|
||||||
generate_sar_kml,
|
generate_sar_kml,
|
||||||
launch_google_earth,
|
launch_google_earth,
|
||||||
|
cleanup_old_kml_files
|
||||||
)
|
)
|
||||||
from network import create_udp_socket, close_udp_socket
|
from network import create_udp_socket, close_udp_socket
|
||||||
from receiver import UdpReceiver
|
from receiver import UdpReceiver
|
||||||
@ -1390,9 +1392,17 @@ class App:
|
|||||||
) # Passa geo_info
|
) # Passa geo_info
|
||||||
|
|
||||||
if kml_success:
|
if kml_success:
|
||||||
logging.info(
|
logging.debug(
|
||||||
f"{kml_log_prefix} KML file generated successfully: {kml_output_path}"
|
f"{kml_log_prefix} KML file generated successfully: {kml_output_path}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logging.debug(f"{kml_log_prefix} Calling KML cleanup utility...")
|
||||||
|
try:
|
||||||
|
cleanup_old_kml_files(config.KML_OUTPUT_DIRECTORY, config.MAX_KML_FILES)
|
||||||
|
except Exception as cleanup_e:
|
||||||
|
# Log error during cleanup but don't stop subsequent actions (like GE launch)
|
||||||
|
logging.exception(f"{kml_log_prefix} Error during KML cleanup call:")
|
||||||
|
|
||||||
# Lancia Google Earth se richiesto
|
# Lancia Google Earth se richiesto
|
||||||
if config.AUTO_LAUNCH_GOOGLE_EARTH:
|
if config.AUTO_LAUNCH_GOOGLE_EARTH:
|
||||||
logging.debug(
|
logging.debug(
|
||||||
|
|||||||
@ -180,5 +180,11 @@ AUTO_LAUNCH_GOOGLE_EARTH = False # Imposta a True per tentare di aprire automat
|
|||||||
# Opzionale: potresti aggiungere un percorso esplicito all'eseguibile di Google Earth se non è nel PATH
|
# Opzionale: potresti aggiungere un percorso esplicito all'eseguibile di Google Earth se non è nel PATH
|
||||||
# GOOGLE_EARTH_EXECUTABLE_PATH = "C:/Program Files/Google/Google Earth Pro/client/googleearth.exe" # Esempio Windows
|
# GOOGLE_EARTH_EXECUTABLE_PATH = "C:/Program Files/Google/Google Earth Pro/client/googleearth.exe" # Esempio Windows
|
||||||
|
|
||||||
|
# Maximum number of KML files to keep in the output directory.
|
||||||
|
# Older files will be deleted when a new one is created if the count exceeds this limit.
|
||||||
|
# Set to 0 or less to disable cleanup.
|
||||||
|
MAX_KML_FILES = 50
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# --- END OF FILE config.py ---
|
# --- END OF FILE config.py ---
|
||||||
|
|||||||
@ -194,40 +194,68 @@ class ImagePipeline:
|
|||||||
if not self._app_state.shutting_down:
|
if not self._app_state.shutting_down:
|
||||||
logging.exception(f"{log_prefix} Error during SAR processing pipeline:")
|
logging.exception(f"{log_prefix} Error during SAR processing pipeline:")
|
||||||
|
|
||||||
|
# Only the modified function _rotate_image is sent.
|
||||||
|
# The process_sar_for_display function does not need changes for this specific request,
|
||||||
|
# as it will receive the potentially larger image from the modified _rotate_image
|
||||||
|
# and pass it correctly to _resize_sar_image.
|
||||||
|
|
||||||
|
# Function to be modified: _rotate_image
|
||||||
|
|
||||||
def _rotate_image(self, img: np.ndarray, angle_rad: float) -> Optional[np.ndarray]:
|
def _rotate_image(self, img: np.ndarray, angle_rad: float) -> Optional[np.ndarray]:
|
||||||
"""
|
"""
|
||||||
Helper method to rotate an image using OpenCV.
|
Helper method to rotate an image using OpenCV, ensuring the entire
|
||||||
|
rotated image is contained within the output canvas by resizing the canvas
|
||||||
|
and adding borders as necessary.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
img (np.ndarray): Input image.
|
img (np.ndarray): Input image (can be grayscale or BGR).
|
||||||
angle_rad (float): Rotation angle in radians.
|
angle_rad (float): Rotation angle in radians.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Optional[np.ndarray]: The rotated image, or None on critical error.
|
Optional[np.ndarray]: The rotated image within an expanded canvas,
|
||||||
|
or None on critical error.
|
||||||
"""
|
"""
|
||||||
log_prefix = f"{self._log_prefix} SAR Rotate Helper"
|
log_prefix = f"{self._log_prefix} SAR Rotate Helper"
|
||||||
try:
|
try:
|
||||||
deg = math.degrees(angle_rad)
|
# 1. Get image dimensions and center
|
||||||
h, w = img.shape[:2]
|
h, w = img.shape[:2]
|
||||||
center = (w // 2, h // 2)
|
center_x, center_y = w // 2, h // 2
|
||||||
# Get rotation matrix
|
|
||||||
M = cv2.getRotationMatrix2D(center, deg, 1.0)
|
# 2. Calculate rotation matrix for the original center
|
||||||
# Determine border color (black for BGR, 0 for grayscale)
|
deg = math.degrees(angle_rad)
|
||||||
|
M = cv2.getRotationMatrix2D((center_x, center_y), deg, 1.0)
|
||||||
|
|
||||||
|
# 3. Calculate the new bounding box dimensions
|
||||||
|
cos = np.abs(M[0, 0])
|
||||||
|
sin = np.abs(M[0, 1])
|
||||||
|
new_w = int((h * sin) + (w * cos))
|
||||||
|
new_h = int((h * cos) + (w * sin))
|
||||||
|
logging.debug(f"{log_prefix} Original dims ({w}x{h}), Rotated BBox dims ({new_w}x{new_h}) for angle {deg:.2f} deg.")
|
||||||
|
|
||||||
|
# 4. Adjust the rotation matrix to account for translation
|
||||||
|
# The matrix needs to shift the image center to the center of the new, larger canvas.
|
||||||
|
M[0, 2] += (new_w / 2) - center_x
|
||||||
|
M[1, 2] += (new_h / 2) - center_y
|
||||||
|
logging.debug(f"{log_prefix} Rotation matrix adjusted for translation.")
|
||||||
|
|
||||||
|
# 5. Determine border color (black)
|
||||||
border_color = [0, 0, 0] if img.ndim == 3 else 0
|
border_color = [0, 0, 0] if img.ndim == 3 else 0
|
||||||
# Perform affine warp
|
|
||||||
|
# 6. Perform the affine transformation on the larger canvas
|
||||||
rotated_img = cv2.warpAffine(
|
rotated_img = cv2.warpAffine(
|
||||||
img,
|
img,
|
||||||
M,
|
M,
|
||||||
(w, h), # Output size same as input
|
(new_w, new_h), # Use the new bounding box dimensions
|
||||||
flags=cv2.INTER_LINEAR, # Linear interpolation
|
flags=cv2.INTER_LINEAR,
|
||||||
borderMode=cv2.BORDER_CONSTANT,
|
borderMode=cv2.BORDER_CONSTANT,
|
||||||
borderValue=border_color, # Fill borders with black
|
borderValue=border_color # Fill borders with black
|
||||||
)
|
)
|
||||||
logging.debug(f"{log_prefix} Rotation successful.")
|
logging.debug(f"{log_prefix} Rotation and warpAffine successful. Output shape: {rotated_img.shape}")
|
||||||
return rotated_img
|
return rotated_img
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Log error and return None to indicate failure
|
# Log error and return None to indicate failure
|
||||||
logging.exception(f"{log_prefix} Rotation warpAffine error:")
|
logging.exception(f"{log_prefix} Rotation/warpAffine error:")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _resize_sar_image(
|
def _resize_sar_image(
|
||||||
|
|||||||
84
utils.py
84
utils.py
@ -13,11 +13,12 @@ Uses standardized logging prefixes. Drop counts are now managed within AppState.
|
|||||||
import queue
|
import queue
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import os # Aggiunto
|
import os
|
||||||
import datetime # Aggiunto per timestamp
|
import datetime
|
||||||
import sys # Aggiunto per platform check
|
import sys
|
||||||
import subprocess # Aggiunto per lanciare processi
|
import subprocess
|
||||||
import shutil # Aggiunto per trovare eseguibili (opzionale)
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
# Importa le librerie KML e GEO, gestendo l'ImportError
|
# Importa le librerie KML e GEO, gestendo l'ImportError
|
||||||
try:
|
try:
|
||||||
@ -377,7 +378,7 @@ def generate_sar_kml(geo_info_radians, output_path) -> bool:
|
|||||||
# Salva il file KML
|
# Salva il file KML
|
||||||
logging.debug(f"{log_prefix} Saving KML to: {output_path}")
|
logging.debug(f"{log_prefix} Saving KML to: {output_path}")
|
||||||
kml.save(output_path)
|
kml.save(output_path)
|
||||||
logging.info(f"{log_prefix} KML file saved successfully: {output_path}")
|
logging.debug(f"{log_prefix} KML file saved successfully: {output_path}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -436,5 +437,76 @@ def launch_google_earth(kml_path):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception(f"{log_prefix} Unexpected error launching Google Earth:")
|
logging.exception(f"{log_prefix} Unexpected error launching Google Earth:")
|
||||||
|
|
||||||
|
def cleanup_old_kml_files(kml_directory: str, max_files_to_keep: int):
|
||||||
|
"""
|
||||||
|
Removes the oldest KML files from the specified directory if the total number
|
||||||
|
of KML files exceeds max_files_to_keep.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
kml_directory (str): The path to the directory containing KML files.
|
||||||
|
max_files_to_keep (int): The maximum number of KML files to retain.
|
||||||
|
If 0 or less, cleanup is disabled.
|
||||||
|
"""
|
||||||
|
log_prefix = "[Utils KML Cleanup]"
|
||||||
|
if max_files_to_keep <= 0:
|
||||||
|
logging.debug(f"{log_prefix} KML cleanup disabled (max_files_to_keep={max_files_to_keep}).")
|
||||||
|
return
|
||||||
|
|
||||||
|
logging.debug(f"{log_prefix} Checking directory '{kml_directory}' for KML files older than the newest {max_files_to_keep}.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
kml_dir_path = Path(kml_directory)
|
||||||
|
if not kml_dir_path.is_dir():
|
||||||
|
logging.warning(f"{log_prefix} Directory '{kml_directory}' not found. Cannot perform cleanup.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 1. List all .kml files with their modification times
|
||||||
|
kml_files = []
|
||||||
|
for item in kml_dir_path.glob('*.kml'):
|
||||||
|
if item.is_file():
|
||||||
|
try:
|
||||||
|
# Get modification time
|
||||||
|
mtime = item.stat().st_mtime
|
||||||
|
kml_files.append((item, mtime))
|
||||||
|
except OSError as stat_err:
|
||||||
|
logging.warning(f"{log_prefix} Could not get modification time for '{item.name}': {stat_err}")
|
||||||
|
except Exception as stat_e:
|
||||||
|
logging.exception(f"{log_prefix} Unexpected error getting stat for '{item.name}':")
|
||||||
|
|
||||||
|
|
||||||
|
# 2. Check if cleanup is needed
|
||||||
|
current_file_count = len(kml_files)
|
||||||
|
logging.debug(f"{log_prefix} Found {current_file_count} KML files. Max allowed: {max_files_to_keep}.")
|
||||||
|
if current_file_count <= max_files_to_keep:
|
||||||
|
logging.debug(f"{log_prefix} File count is within limit. No cleanup needed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 3. Sort files by modification time (oldest first)
|
||||||
|
kml_files.sort(key=lambda x: x[1]) # Sort by the second element (mtime)
|
||||||
|
|
||||||
|
# 4. Determine files to delete
|
||||||
|
num_to_delete = current_file_count - max_files_to_keep
|
||||||
|
files_to_delete = kml_files[:num_to_delete] # Get the oldest ones
|
||||||
|
|
||||||
|
logging.debug(f"{log_prefix} Need to delete {num_to_delete} oldest KML files.")
|
||||||
|
|
||||||
|
# 5. Delete the oldest files
|
||||||
|
deleted_count = 0
|
||||||
|
for file_path, _ in files_to_delete:
|
||||||
|
try:
|
||||||
|
file_path.unlink() # Use unlink() for Path objects (equivalent to os.remove)
|
||||||
|
logging.debug(f"{log_prefix} Deleted old KML file: {file_path.name}")
|
||||||
|
deleted_count += 1
|
||||||
|
except OSError as delete_err:
|
||||||
|
logging.error(f"{log_prefix} Failed to delete file '{file_path.name}': {delete_err}")
|
||||||
|
except Exception as delete_e:
|
||||||
|
logging.exception(f"{log_prefix} Unexpected error deleting file '{file_path.name}':")
|
||||||
|
|
||||||
|
|
||||||
|
logging.debug(f"{log_prefix} Cleanup finished. Deleted {deleted_count}/{num_to_delete} files.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(f"{log_prefix} Error during KML cleanup process:")
|
||||||
|
|
||||||
|
|
||||||
# --- END OF FILE utils.py ---
|
# --- END OF FILE utils.py ---
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user