|
@@ -1,18 +1,59 @@
|
|
|
-import cv2
|
|
|
import os
|
|
|
+from typing import Optional
|
|
|
+from typing import Tuple
|
|
|
|
|
|
+import cv2
|
|
|
from PIL import Image
|
|
|
-from typing import Tuple
|
|
|
-from typing import Optional
|
|
|
|
|
|
from pycs.database.File import File
|
|
|
|
|
|
+DEFAULT_JPEG_QUALITY = 80
|
|
|
+
|
|
|
+
|
|
|
+def file_info(data_folder: str, file_name: str, file_ext: str):
|
|
|
+ """
|
|
|
+ Receive file type, frame count and frames per second.
|
|
|
+ The last two are always None for images.
|
|
|
+
|
|
|
+ :param data_folder: path to data folder
|
|
|
+ :param file_name: file name
|
|
|
+ :param file_ext: file extension
|
|
|
+ :return: file type, frame count, frames per second
|
|
|
+ """
|
|
|
+ # determine file type
|
|
|
+ if file_ext.lower() in ['.jpg', '.png']:
|
|
|
+ file_type = 'image'
|
|
|
+
|
|
|
+ elif file_ext.lower() in ['.mp4']:
|
|
|
+ file_type = 'video'
|
|
|
+
|
|
|
+ else:
|
|
|
+ raise ValueError(f"Unsupported file extension: {file_ext}!")
|
|
|
+
|
|
|
+ # determine frames and fps for video files
|
|
|
+ if file_type == 'image':
|
|
|
+ frames = None
|
|
|
+ fps = None
|
|
|
+ else:
|
|
|
+ file_path = os.path.join(data_folder, file_name + file_ext)
|
|
|
+ video = cv2.VideoCapture(file_path)
|
|
|
+
|
|
|
+ frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
|
|
|
+ fps = video.get(cv2.CAP_PROP_FPS)
|
|
|
+
|
|
|
+ video.release()
|
|
|
+
|
|
|
+ # return values
|
|
|
+ return file_type, frames, fps
|
|
|
+
|
|
|
+
|
|
|
def crop_file(file: File, project_root: str, x: float, y: float, w: float, h: float) -> str:
|
|
|
"""
|
|
|
gets a file for the given file_id, crops the according image to the
|
|
|
bounding box and saves the crops in the temp folder of the project.
|
|
|
|
|
|
:param file: file object
|
|
|
+ :param project_root: project root folder path
|
|
|
:param x: relative x-coordinate of the top left corner
|
|
|
:param y: relative y-coordinate of the top left corner
|
|
|
:param w: relative width of the bounding box
|
|
@@ -21,6 +62,9 @@ def crop_file(file: File, project_root: str, x: float, y: float, w: float, h: fl
|
|
|
:return: directory and file name of the cropped patch
|
|
|
"""
|
|
|
|
|
|
+ # TODO in browser cache
|
|
|
+ # TODO not possible for video files
|
|
|
+
|
|
|
image = Image.open(file.absolute_path)
|
|
|
width, height = image.size
|
|
|
|
|
@@ -40,8 +84,8 @@ def crop_file(file: File, project_root: str, x: float, y: float, w: float, h: fl
|
|
|
)
|
|
|
|
|
|
if not os.path.exists(target_path):
|
|
|
- crop = image.crop((x0, y0, x0+crop_width, y0+crop_height))
|
|
|
- crop.save(target_path, quality=80)
|
|
|
+ crop = image.crop((x0, y0, x0 + crop_width, y0 + crop_height))
|
|
|
+ crop.save(target_path, quality=DEFAULT_JPEG_QUALITY)
|
|
|
|
|
|
return os.path.split(target_path)
|
|
|
|
|
@@ -52,6 +96,7 @@ def resize_file(file: File, project_root: str, max_width: int, max_height: int)
|
|
|
to resize and returns the resized files directory and name.
|
|
|
|
|
|
:param file: file object
|
|
|
+ :param project_root: project root folder path
|
|
|
:param max_width: maximum image or thumbnail width
|
|
|
:param max_height: maximum image or thumbnail height
|
|
|
:return: resized file directory, resized file name
|
|
@@ -68,7 +113,7 @@ def resize_file(file: File, project_root: str, max_width: int, max_height: int)
|
|
|
|
|
|
# resize image file
|
|
|
abs_target_path = os.path.join(os.getcwd(), project_root,
|
|
|
- 'temp', f'{file.uuid}_{max_width}_{max_height}.jpg')
|
|
|
+ 'temp', f'{file.uuid}_{max_width}_{max_height}.jpg')
|
|
|
result = resize_image(abs_file_path, abs_target_path, max_width, max_height)
|
|
|
|
|
|
# return path
|
|
@@ -77,7 +122,9 @@ def resize_file(file: File, project_root: str, max_width: int, max_height: int)
|
|
|
|
|
|
return os.path.split(abs_file_path)
|
|
|
|
|
|
-def resize_image(file_path: str, target_path: str, max_width: int, max_height: int) -> Optional[bool]:
|
|
|
+
|
|
|
+def resize_image(file_path: str, target_path: str,
|
|
|
+ max_width: int, max_height: int) -> Optional[bool]:
|
|
|
"""
|
|
|
resize an image so width < max_width and height < max_height
|
|
|
|
|
@@ -111,9 +158,10 @@ def resize_image(file_path: str, target_path: str, max_width: int, max_height: i
|
|
|
resized_image = image.resize((target_width, target_height))
|
|
|
|
|
|
# save to file
|
|
|
- resized_image.save(target_path, quality=80)
|
|
|
+ resized_image.save(target_path, quality=DEFAULT_JPEG_QUALITY)
|
|
|
return True
|
|
|
|
|
|
+
|
|
|
def create_thumbnail(file_path: str, target_path: str) -> None:
|
|
|
"""
|
|
|
extract a thumbnail from a video
|