瀏覽代碼

merge file_ops.py and FileParser.py

Eric Tröbs 4 年之前
父節點
當前提交
250dbf29d1

+ 3 - 5
pycs/frontend/endpoints/data/GetResizedFile.py

@@ -1,15 +1,13 @@
-import cv2
 import os
 import os
 import re
 import re
 
 
-from PIL import Image
 from eventlet import tpool
 from eventlet import tpool
 from flask import abort
 from flask import abort
 from flask import send_from_directory
 from flask import send_from_directory
 from flask.views import View
 from flask.views import View
 
 
 from pycs.database.Database import Database
 from pycs.database.Database import Database
-from pycs.util import file_ops
+from pycs.util.FileOperations import resize_file
 
 
 
 
 class GetResizedFile(View):
 class GetResizedFile(View):
@@ -40,6 +38,6 @@ class GetResizedFile(View):
         max_height = int(resolution[1]) if len(resolution) > 1 else 2 ** 24
         max_height = int(resolution[1]) if len(resolution) > 1 else 2 ** 24
 
 
         # send data
         # send data
-        file_directory, file_name = tpool.execute(file_ops.resize_file,
-                                                  file, project.root_folder, max_width, max_height)
+        file_directory, file_name = tpool.execute(resize_file, file,
+                                                  project.root_folder, max_width, max_height)
         return send_from_directory(file_directory, file_name)
         return send_from_directory(file_directory, file_name)

+ 1 - 1
pycs/frontend/endpoints/data/UploadFile.py

@@ -8,7 +8,7 @@ from werkzeug import formparser
 
 
 from pycs.database.Database import Database
 from pycs.database.Database import Database
 from pycs.frontend.notifications.NotificationManager import NotificationManager
 from pycs.frontend.notifications.NotificationManager import NotificationManager
-from pycs.util.FileParser import file_info
+from pycs.util.FileOperations import file_info
 
 
 
 
 class UploadFile(View):
 class UploadFile(View):

+ 1 - 1
pycs/frontend/endpoints/projects/ExecuteExternalStorage.py

@@ -11,7 +11,7 @@ from pycs.database.Project import Project
 from pycs.frontend.notifications.NotificationManager import NotificationManager
 from pycs.frontend.notifications.NotificationManager import NotificationManager
 from pycs.jobs.JobGroupBusyException import JobGroupBusyException
 from pycs.jobs.JobGroupBusyException import JobGroupBusyException
 from pycs.jobs.JobRunner import JobRunner
 from pycs.jobs.JobRunner import JobRunner
-from pycs.util.FileParser import file_info
+from pycs.util.FileOperations import file_info
 
 
 
 
 class ExecuteExternalStorage(View):
 class ExecuteExternalStorage(View):

+ 3 - 5
pycs/frontend/endpoints/results/ResultAsCrop.py

@@ -5,7 +5,7 @@ from flask import send_from_directory
 from flask.views import View
 from flask.views import View
 
 
 from pycs.database.Database import Database
 from pycs.database.Database import Database
-from pycs.util import file_ops
+from pycs.util.FileOperations import crop_file
 
 
 
 
 class ResultAsCrop(View):
 class ResultAsCrop(View):
@@ -19,9 +19,7 @@ class ResultAsCrop(View):
         # pylint: disable=invalid-name
         # pylint: disable=invalid-name
         self.db = db
         self.db = db
 
 
-
     def dispatch_request(self, result_id: int, max_width: int = 2**24, max_height: int = 2**24):
     def dispatch_request(self, result_id: int, max_width: int = 2**24, max_height: int = 2**24):
-
         # find result
         # find result
         result = self.db.result(result_id)
         result = self.db.result(result_id)
 
 
@@ -50,13 +48,13 @@ class ResultAsCrop(View):
 
 
         project = file.project()
         project = file.project()
 
 
-        crop_path, crop_fname = file_ops.crop_file(file, project.root_folder, x, y, w, h)
+        crop_path, crop_fname = crop_file(file, project.root_folder, x, y, w, h)
 
 
         parts = os.path.splitext(crop_fname)
         parts = os.path.splitext(crop_fname)
 
 
         crop_new_fname = f"{parts[0]}_{max_width}_{max_height}.{parts[1]}"
         crop_new_fname = f"{parts[0]}_{max_width}_{max_height}.{parts[1]}"
 
 
-        resized = file_ops.resize_image(
+        resized = resize_image(
             os.path.join(crop_path, crop_fname),
             os.path.join(crop_path, crop_fname),
             os.path.join(crop_path, crop_new_fname),
             os.path.join(crop_path, crop_new_fname),
             max_width,
             max_width,

+ 56 - 8
pycs/util/file_ops.py → pycs/util/FileOperations.py

@@ -1,18 +1,59 @@
-import cv2
 import os
 import os
+from typing import Optional
+from typing import Tuple
 
 
+import cv2
 from PIL import Image
 from PIL import Image
-from typing import Tuple
-from typing import Optional
 
 
 from pycs.database.File import File
 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:
 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
     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.
     bounding box and saves the crops in the temp folder of the project.
 
 
     :param file: file object
     :param file: file object
+    :param project_root: project root folder path
     :param x: relative x-coordinate of the top left corner
     :param x: relative x-coordinate of the top left corner
     :param y: relative y-coordinate of the top left corner
     :param y: relative y-coordinate of the top left corner
     :param w: relative width of the bounding box
     :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
     :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)
     image = Image.open(file.absolute_path)
     width, height = image.size
     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):
     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)
     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.
     to resize and returns the resized files directory and name.
 
 
     :param file: file object
     :param file: file object
+    :param project_root: project root folder path
     :param max_width: maximum image or thumbnail width
     :param max_width: maximum image or thumbnail width
     :param max_height: maximum image or thumbnail height
     :param max_height: maximum image or thumbnail height
     :return: resized file directory, resized file name
     :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
     # resize image file
     abs_target_path = os.path.join(os.getcwd(), project_root,
     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)
     result = resize_image(abs_file_path, abs_target_path, max_width, max_height)
 
 
     # return path
     # 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)
     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
     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))
     resized_image = image.resize((target_width, target_height))
 
 
     # save to file
     # save to file
-    resized_image.save(target_path, quality=80)
+    resized_image.save(target_path, quality=DEFAULT_JPEG_QUALITY)
     return True
     return True
 
 
+
 def create_thumbnail(file_path: str, target_path: str) -> None:
 def create_thumbnail(file_path: str, target_path: str) -> None:
     """
     """
     extract a thumbnail from a video
     extract a thumbnail from a video

+ 0 - 40
pycs/util/FileParser.py

@@ -1,40 +0,0 @@
-from os import path
-
-import cv2
-
-
-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']:
-        ftype = 'image'
-
-    elif file_ext.lower() in ['.mp4']:
-        ftype = 'video'
-
-    else:
-        raise ValueError(f"Unsupported file extension: {file_ext}!")
-
-    # determine frames and fps for video files
-    if ftype == 'image':
-        frames = None
-        fps = None
-    else:
-        file_path = 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 ftype, frames, fps

+ 0 - 8
webui/src/App.vue

@@ -148,11 +148,3 @@ export default {
   border-bottom: 1px solid rgba(0, 0, 0, 0.2);
   border-bottom: 1px solid rgba(0, 0, 0, 0.2);
 }
 }
 </style>
 </style>
-
-<style>
-
-.btn {
-  cursor: pointer;
-}
-
-</style>

+ 0 - 2
webui/src/assets/style/main.css

@@ -1,7 +1,5 @@
 * {
 * {
     box-sizing: border-box;
     box-sizing: border-box;
-    margin: 0;
-    padding: 0;
 }
 }
 
 
 html, body {
 html, body {

+ 4 - 0
webui/src/components/media/annotation-box.vue

@@ -142,6 +142,10 @@ export default {
   border-width: 5px;
   border-width: 5px;
 }
 }
 
 
+.btn {
+  cursor: pointer;
+}
+
 .label {
 .label {
   position: absolute;
   position: absolute;
   bottom: 0.25rem;
   bottom: 0.25rem;