Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolaiPetukhov committed Sep 28, 2023
1 parent ea5864c commit 3f6e331
Show file tree
Hide file tree
Showing 69 changed files with 4,884 additions and 2,944 deletions.
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ git+https://github.com/supervisely/supervisely.git@NikolaiPetukhov
jsonschema
networkx
scikit-image>=0.17.1, <1.0.0
cacheout
cacheout
markdown
json2html
31 changes: 17 additions & 14 deletions src/compute/Net.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ def __init__(self, graph_desc, output_folder):
if not os.path.exists(graph_path):
raise RuntimeError('No such config file "%s"' % graph_path)
else:
graph = json.load(open(graph_path, "r"))
self.graph = json.load(open(graph_path, "r"))
else:
graph = graph_desc
self.graph = graph_desc

for layer_config in graph:
for layer_config in self.graph:
if "action" not in layer_config:
raise RuntimeError('No "action" field in layer "{}".'.format(layer_config))
action = layer_config["action"]
Expand Down Expand Up @@ -203,20 +203,23 @@ def start(self, data_el):
for output in output_generator:
yield output

def start_iterate(self, data_el):
def start_iterate(self, data_el, layer_idx: int = None):
img_pr_name = data_el[0].get_pr_name()
img_ds_name = data_el[0].get_ds_name()

start_layer_indxs = set()
for idx, layer in enumerate(self.layers):
if layer.type != "data":
continue
if layer.project_name == img_pr_name and (
"*" in layer.dataset_names or img_ds_name in layer.dataset_names
):
start_layer_indxs.add(idx)
if len(start_layer_indxs) == 0:
raise RuntimeError("Can not find data layer for the image: {}".format(data_el))
if layer_idx is not None:
start_layer_indxs = [layer_idx]
else:
start_layer_indxs = set()
for idx, layer in enumerate(self.layers):
if layer.type != "data":
continue
if layer.project_name == img_pr_name and (
"*" in layer.dataset_names or img_ds_name in layer.dataset_names
):
start_layer_indxs.add(idx)
if len(start_layer_indxs) == 0:
raise RuntimeError("Can not find data layer for the image: {}".format(data_el))

for start_layer_indx in start_layer_indxs:
output_generator = self.process_iterate(start_layer_indx, data_el)
Expand Down
58 changes: 24 additions & 34 deletions src/compute/layers/processing/BlurLayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@


class BlurLayer(Layer):

action = 'blur'
action = "blur"

layer_settings = {
"required": ["settings"],
Expand All @@ -22,62 +21,53 @@ class BlurLayer(Layer):
"oneOf": [
{
"type": "object",
"required": [
"name",
"sigma"
],
"required": ["name", "sigma"],
"properties": {
"name": {
"type": "string",
"enum": [
"gaussian",
]
],
},
"sigma": {
"type": "object",
"required": ["min", "max"],
"properties": {
"min": {"type": "number", "minimum": 0.01},
"max": {"type": "number", "minimum": 0.01},
}
}
}
},
},
},
},
{
"type": "object",
"required": [
"name",
"kernel"
],
"required": ["name", "kernel"],
"properties": {
"name": {
"type": "string",
"enum": [
"median",
]
],
},
"kernel": {
"type": "integer",
"minimum": 3
}
}
}
]
"kernel": {"type": "integer", "minimum": 3},
},
},
],
}
}
},
}

def __init__(self, config):
Layer.__init__(self, config)
if (self.settings['name'] == 'median') and (self.settings['kernel'] % 2 == 0):
raise RuntimeError('Kernel for median blur must be odd.')
if (self.settings["name"] == "median") and (self.settings["kernel"] % 2 == 0):
raise RuntimeError("Kernel for median blur must be odd.")

def check_min_max(dictionary, text):
if dictionary['min'] > dictionary['max']:
if dictionary["min"] > dictionary["max"]:
raise RuntimeError('"min" should be <= than "max" for "{}".'.format(text))

if self.settings['name'] == 'gaussian':
check_min_max(self.settings['sigma'], 'sigma')
if self.settings["name"] == "gaussian":
check_min_max(self.settings["sigma"], "sigma")

def requires_image(self):
return True
Expand All @@ -86,13 +76,13 @@ def process(self, data_el: Tuple[ImageDescriptor, Annotation]):
img_desc, ann = data_el

img = img_desc.read_image()
img = img.astype(np.float32)
if self.settings['name'] == 'gaussian':
sigma_b = self.settings['sigma']
sigma_value = np.random.uniform(sigma_b['min'], sigma_b['max'])
img = img.astype(np.uint8)
if self.settings["name"] == "gaussian":
sigma_b = self.settings["sigma"]
sigma_value = np.random.uniform(sigma_b["min"], sigma_b["max"])
res_img = cv2.GaussianBlur(img, ksize=(0, 0), sigmaX=sigma_value)
elif self.settings['name'] == 'median':
res_img = cv2.medianBlur(img, ksize=self.settings['kernel'])
elif self.settings["name"] == "median":
res_img = cv2.medianBlur(img, ksize=self.settings["kernel"])
else:
raise NotImplementedError()

Expand Down
17 changes: 13 additions & 4 deletions src/compute/layers/processing/RotateLayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ def expand_image_with_rect(img: np.ndarray, req_rect: Rectangle):
def process(self, data_el: Tuple[ImageDescriptor, Annotation]):
img_desc, ann = data_el

aug.rotate(mode=aug.RotationModes.KEEP)

angle_dct = self.settings["rotate_angles"]
min_degrees, max_degrees = angle_dct["min_degrees"], angle_dct["max_degrees"]
rotate_degrees = np.random.uniform(min_degrees, max_degrees)
Expand All @@ -103,9 +101,20 @@ def process(self, data_el: Tuple[ImageDescriptor, Annotation]):
if black_reg_mode == "preserve_size":
rect_to_crop = Rectangle.from_array(img)
new_img, (delta_x, delta_y) = self.expand_image_with_rect(new_img, rect_to_crop)
new_ann.img_size = new_img.shape[:2]

new_ann = apply_to_labels(ann, lambda x: x.translate(delta_x, delta_y))
top_pad = max((new_img.shape[0] - ann.img_size[0]) // 2, 0)
lefet_pad = max((new_img.shape[1] - ann.img_size[1]) // 2, 0)
new_img, new_ann = aug.crop(
new_img,
new_ann,
top_pad=top_pad,
bottom_pad=new_img.shape[0] - top_pad - ann.img_size[0],
left_pad=lefet_pad,
right_pad=new_img.shape[1] - lefet_pad - ann.img_size[1],
)
new_ann.clone(img_size=new_img.shape[:2])

new_ann = apply_to_labels(new_ann, lambda x: [x.translate(delta_x, delta_y)])

if new_img is None:
return # no yield
Expand Down
117 changes: 117 additions & 0 deletions src/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
from typing import Optional, Union
import traceback

from supervisely import logger
from supervisely import ProjectMeta


class CustomException(Exception):
def __init__(
self, message: str, error: Optional[Exception] = None, extra: Optional[dict] = None
):
super().__init__(message)
self.message = message
self.error = error
self.extra = extra

def __str__(self):
return self.message

def log(self):
exc_info = (
traceback.format_tb(self.error.__traceback__)
if self.error
else traceback.format_tb(self.__traceback__)
)
logger.error(self.message, exc_info=exc_info, extra=self.extra)


class ActionNotFoundError(CustomException):
def __init__(self, action_name: str, extra: Optional[dict] = {}):
self.action_name = action_name
extra["action_name"] = action_name
super().__init__("Action not found", extra=extra)


class CreateLayerError(CustomException):
def __init__(self, action_name: str, error: Exception, extra: Optional[dict] = {}):
self.action_name = action_name
extra["action_name"] = action_name
super().__init__(f"Error creating Layer", error=error, extra=extra)


class LayerNotFoundError(CustomException):
def __init__(self, layer_id: str, extra: Optional[dict] = {}):
self.layer_id = layer_id
extra["layer_id"] = layer_id
super().__init__("Layer not found", extra=extra)


class CreateNodeError(CustomException):
def __init__(self, layer_name, error: Exception, extra: Optional[dict] = {}):
self.layer_name = layer_name
extra["layer_name"] = layer_name
super().__init__(f"Error creating Node", error=error, extra=extra)


class UpdateMetaError(CustomException):
def __init__(
self,
layer_name: str,
project_meta: ProjectMeta,
error: Exception,
extra: Optional[dict] = {},
):
self.layer_name = layer_name
self.project_meta = project_meta
extra["layer_name"] = layer_name
extra["project_meta"] = project_meta.to_json()
super().__init__(
f"Error updating project meta",
error=error,
extra=extra,
)


class GraphCalculationError(CustomException):
def __init__(
self,
dtl_json: list,
error: Exception,
layer_name: Optional[str] = "",
extra: Optional[dict] = {},
):
extra["dtl_json"] = dtl_json
extra["layer_name"] = layer_name
super().__init__(
"Error performing transformations",
error=error,
extra=extra,
)


class BadSettingsError(CustomException):
def __init__(
self,
layer_name: str,
settings_json: dict,
error: Exception = None,
extra: Optional[dict] = {},
):
extra["layer_name"] = layer_name
extra["settings"] = settings_json
super().__init__("Bad settings", error, extra=extra)


def handle_exception(func):
"""Decorator to log exception and silence it"""

def inner(*args, **kwargs):
try:
return func(*args, **kwargs)
except CustomException as e:
e.log()
except Exception as e:
logger.error("Unexpected error", exc_info=traceback.format_exc())

return inner
12 changes: 12 additions & 0 deletions src/globals.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import queue
from dotenv import load_dotenv

import supervisely as sly
Expand Down Expand Up @@ -29,3 +30,14 @@

layers_count = 0
layers = {}


update_queue = queue.Queue()


def updater(update: str):
global update_queue
update_queue.put(update)


context_menu_position = None
34 changes: 34 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,44 @@
import shutil
import os
import threading
import time
from supervisely import Application

from src.ui.ui import layout
from src.ui.tabs.configure import update_metas, update_nodes
from src.ui.tabs.json_preview import load_json
import src.globals as g

shutil.rmtree(g.STATIC_DIR, ignore_errors=True)
os.mkdir(g.STATIC_DIR)
app = Application(layout=layout, static_dir=g.STATIC_DIR)


def _update_f():
while True:
updates = []
while not g.update_queue.empty():
updates.append(g.update_queue.get())
if len(updates) == 0:
time.sleep(0.1)
continue
try:
if "load_json" in updates:
load_json()
elif "nodes" in updates:
update_nodes()
else:
update_metas()
finally:
for _ in range(len(updates)):
g.update_queue.task_done()
time.sleep(0.1)


update_loop = threading.Thread(
target=_update_f,
name="App update loop",
daemon=True,
)

update_loop.start()
Loading

0 comments on commit 3f6e331

Please sign in to comment.