Source code for endoreg_db.models.media.frame.frame

from typing import TYPE_CHECKING, Union, Optional, Dict, Tuple, List
from django.db import models
from pathlib import Path
import cv2
import numpy as np
from ...utils import FRAME_DIR, FILE_STORAGE, data_paths
if TYPE_CHECKING:
    from ..video.video_file import VideoFile
    from ...label.label import Label
    from ...label.annotation import ImageClassificationAnnotation

# Unified Frame model
[docs] class Frame(models.Model): video = models.ForeignKey( "VideoFile", on_delete=models.CASCADE, related_name="frames", blank=False, null=False, ) frame_number = models.PositiveIntegerField() relative_path = models.CharField(max_length=512) timestamp = models.FloatField(null=True, blank=True) is_extracted = models.BooleanField(default=False) class Meta: unique_together = ('video', 'frame_number') ordering = ['video', 'frame_number'] @property def file_path(self) -> Path: """Returns the absolute path to the frame file.""" base_dir = self.video.get_frame_dir_path() return base_dir / self.relative_path
[docs] def get_image(self) -> Optional[np.ndarray]: """Reads and returns the frame image using OpenCV.""" if not self.file_path.exists(): return None try: image = cv2.imread(str(self.file_path)) if image is None: pass return image except Exception as e: return None
[docs] def anonymize( self, output_path: Path, endo_roi: Optional[List[int]] = None, censor_color: Tuple[int, int, int] = (0, 0, 0), all_black: bool = False, ) -> bool: """ Anonymizes the frame image and saves it to output_path. - Applies ROI masking if endo_roi is provided. - Blacks out the entire frame if all_black is True. Returns True on success, False on failure. """ image = self.get_image() if image is None: return False try: if all_black: anonymized_image = np.zeros_like(image) elif endo_roi and len(endo_roi) == 4: mask = np.zeros(image.shape[:2], dtype=np.uint8) x, y, w, h = endo_roi x1, y1 = max(0, x), max(0, y) x2, y2 = min(image.shape[1], x + w), min(image.shape[0], y + h) mask[y1:y2, x1:x2] = 255 anonymized_image = cv2.bitwise_and(image, image, mask=mask) else: anonymized_image = image.copy() output_path.parent.mkdir(parents=True, exist_ok=True) success = cv2.imwrite(str(output_path), anonymized_image) if not success: return False return True except Exception as e: return False
def __str__(self): return f"Frame {self.frame_number} of Video {self.video.uuid}"
[docs] def get_classification_annotations(self) -> models.QuerySet["ImageClassificationAnnotation"]: return self.image_classification_annotations.all()