| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- """
- Maturity Worker Module
- Worker thread for async multispectral maturity classification processing.
- """
- from typing import Optional
- import logging
- from PyQt5.QtCore import pyqtSignal
- from PyQt5.QtGui import QImage, QPixmap
- from workers.base_worker import BaseWorker, WorkerSignals
- from models.maturity_model import MaturityModel
- logger = logging.getLogger(__name__)
- class MaturityWorkerSignals(WorkerSignals):
- """
- Signals specific to maturity processing.
-
- Signals:
- result_ready: Emitted when prediction is complete
- (gradcam_image: QImage, class_name: str, confidence: float,
- probabilities: dict)
- """
- result_ready = pyqtSignal(QImage, str, float, dict)
- class MaturityWorker(BaseWorker):
- """
- Worker for processing multispectral TIFF files and predicting maturity.
- Runs MaturityModel inference in a background thread without blocking UI.
- Supports 8-band multispectral TIFF images.
- Attributes:
- tif_path: Path to multispectral TIFF file
- model: MaturityModel instance
- signals: MaturityWorkerSignals for emitting results
- """
-
- def __init__(self, tif_path: str, model: Optional[MaturityModel] = None):
- """
- Initialize the maturity worker.
- Args:
- tif_path: Path to multispectral TIFF file to process
- model: MaturityModel instance (if None, creates new one)
- """
- super().__init__()
- self.tif_path = tif_path
- self.model = model
-
- # Replace base signals with maturity-specific signals
- self.signals = MaturityWorkerSignals()
-
- # If no model provided, create and load one
- if self.model is None:
- from utils.config import get_device
- self.model = MaturityModel(device=get_device())
- self.model.load()
-
- logger.info(f"MaturityWorker created for: {tif_path}")
-
- def process(self):
- """
- Process the multispectral TIFF file and predict maturity.
-
- Emits result_ready signal with prediction results.
- """
- if self.is_cancelled():
- logger.info("MaturityWorker cancelled before processing")
- return
-
- # Update progress
- self.emit_progress(10, "Loading multispectral image...")
-
- if not self.model.is_loaded:
- logger.warning("Model not loaded, loading now...")
- self.emit_progress(30, "Loading model...")
- if not self.model.load():
- raise RuntimeError("Failed to load maturity model")
-
- # Process TIFF
- self.emit_progress(50, "Preprocessing multispectral data...")
-
- result = self.model.predict(self.tif_path)
-
- if self.is_cancelled():
- logger.info("MaturityWorker cancelled during processing")
- return
-
- if not result['success']:
- raise RuntimeError(result['error'])
-
- self.emit_progress(70, "Generating Grad-CAM visualization...")
-
- # Generate Grad-CAM visualization
- gradcam_image, pred_name = self.model.run_gradcam(self.tif_path)
-
- if self.is_cancelled():
- logger.info("MaturityWorker cancelled during Grad-CAM generation")
- return
-
- if gradcam_image is None:
- # Create a placeholder pixmap for None Grad-CAM
- gradcam_image = QImage(256, 256, QImage.Format_RGB888)
- gradcam_image.fill(0x2c3e50) # Dark gray background
-
- self.emit_progress(90, "Finalizing results...")
-
- # Emit results
- self.signals.result_ready.emit(
- gradcam_image,
- result['prediction'],
- result['confidence'],
- result['probabilities']
- )
-
- self.emit_progress(100, "Complete!")
-
- logger.info(f"MaturityWorker completed: {result['prediction']} ({result['confidence']:.2%})")
|