From 40275cf4b6acad06bc6618c25a4ad64fbceb0e4b Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Mon, 12 Oct 2020 21:58:38 +0300 Subject: [PATCH 01/24] Initial version of Inside Outside Guidance serverless function --- components/serverless/README.md | 83 +++++++++++++ .../shiyinzhang/iog/nuclio/function.yaml | 65 ++++++++++ .../pytorch/shiyinzhang/iog/nuclio/main.py | 33 +++++ .../shiyinzhang/iog/nuclio/model_handler.py | 117 ++++++++++++++++++ 4 files changed, 298 insertions(+) create mode 100644 serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml create mode 100644 serverless/pytorch/shiyinzhang/iog/nuclio/main.py create mode 100644 serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py diff --git a/components/serverless/README.md b/components/serverless/README.md index 03edc6e803db..5a64033ad855 100644 --- a/components/serverless/README.md +++ b/components/serverless/README.md @@ -5,3 +5,86 @@ # From project root directory docker-compose -f docker-compose.yml -f components/serverless/docker-compose.serverless.yml up -d ``` + +### Tutorial how to add your own DL model for automatic annotation + +Let's try to integration [IOG algorithms for interactive segmentation](https://github.com/shiyinzhang/Inside-Outside-Guidance). + +First of all let's run the model on your local machine. The repo doesn't have good instructions and look +like uses outdated versions of packages. The building process is going to be funny. For old version of +pytorch packages it is better to use conda. See below a possible instructions how to run the model on a +local machine. + +```bash +git clone https://github.com/shiyinzhang/Inside-Outside-Guidance +cd Inside-Outside-Guidance/ +conda create --name iog python=3.6 +conda activate iog +conda install pytorch=0.4 torchvision=0.2 -c pytorch +conda install -c conda-forge pycocotools +conda install -c conda-forge opencv +conda install -c conda-forge scipy +``` + +Download weights from google drive: https://github.com/shiyinzhang/Inside-Outside-Guidance#pretrained-models +Also we will need VOCtrainval_11-May-2012.tar dataset for evaluation: http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar + +Modify `mypath.py` in accordance with instructions inside the repo. In my case `git diff` below: + +```python +diff --git a/mypath.py b/mypath.py +index 0df1565..cd0fa3f 100644 +--- a/mypath.py ++++ b/mypath.py +@@ -3,15 +3,15 @@ class Path(object): + @staticmethod + def db_root_dir(database): + if database == 'pascal': +- return '/path/to/PASCAL/VOC2012' # folder that contains VOCdevkit/. ++ return '/Users/nmanovic/Workspace/datasets/VOCtrainval_11-May-2012/' # folder that contains VOCdevkit/. + + elif database == 'sbd': +- return '/path/to/SBD/' # folder with img/, inst/, cls/, etc. ++ return '/Users/nmanovic/Workspace/datasets/SBD/dataset/' # folder with img/, inst/, cls/, etc. + else: + print('Database {} not available.'.format(database)) + raise NotImplementedError + + @staticmethod + def models_dir(): +- return '/path/to/models/resnet101-5d3b4d8f.pth' ++ return '/Users/nmanovic/Workspace/Inside-Outside-Guidance/IOG_PASCAL_SBD.pth' + #'resnet101-5d3b4d8f.pth' #resnet50-19c8e357.pth' +``` + +It looks like need to update `test.py` to run it without `train.py` script. + +```python +diff --git a/test.py b/test.py +index f85969a..8e481d0 100644 +--- a/test.py ++++ b/test.py +@@ -51,9 +51,10 @@ net = Network(nInputChannels=nInputChannels,num_classes=1, + freeze_bn=False) + + # load pretrain_dict +-pretrain_dict = torch.load(os.path.join(save_dir, 'models', modelName + '_epoch-' + str(resume_epoch - 1) + '.pth')) +-print("Initializing weights from: {}".format( +- os.path.join(save_dir, 'models', modelName + '_epoch-' + str(resume_epoch - 1) + '.pth'))) ++#pretrain_dict = torch.load(os.path.join(save_dir, 'models', modelName + '_epoch-' + str(resume_epoch - 1) + '.pth')) ++#print("Initializing weights from: {}".format( ++# os.path.join(save_dir, 'models', modelName + '_epoch-' + str(resume_epoch - 1) + '.pth'))) ++pretrain_dict = torch.load('/Users/nmanovic/Workspace/Inside-Outside-Guidance/IOG_PASCAL_SBD.pth') + net.load_state_dict(pretrain_dict) + net.to(device) + ``` + +Now it is possible to run `test.py` and it will generate results inside `./run_0/Results` directory. +It is already a great progress. We can run the pretrained model and get results. Next step is to +implement a simple script which will accept an image with a bounding box and generate a mask for the +object. Let's do that. + +```bash +cp test.py model_handler.py +``` + diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml new file mode 100644 index 000000000000..398821e12bb0 --- /dev/null +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -0,0 +1,65 @@ +metadata: + name: pth.shiyinzhang.iog + namespace: cvat + annotations: + name: IOG + type: interactor + spec: + framework: pytorch + min_pos_points: 1 + +spec: + description: Interactive Object Segmentation with Inside-Outside Guidance + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + env: + - name: PYTHONPATH + value: /opt/nuclio/iog + + build: + image: cvat/pth.shiyinzhang.iog + baseImage: continuumio/miniconda3 + + directives: + preCopy: + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: git clone https://github.com/shiyinzhang/Inside-Outside-Guidance.git iog + - kind: WORKDIR + value: /opt/nuclio/iog + - kind: ENV + value: fileid=1Lm1hhMhhjjnNwO4Pf7SC6tXLayH2iH0l + - kind: ENV + value: filename=IOG_PASCAL_SBD.pth + - kind: RUN + value: curl -c ./cookie -s -L "https://drive.google.com/uc?export=download&id=${fileid}" + - kind: RUN + value: curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk '/download/ {print $NF}' ./cookie`&id=${fileid}" -o ${filename} + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: conda create -y -n iog python=3.6 + - kind: SHELL + value: '["conda", "run", "-n", "iog", "/bin/bash", "-c"]' + - kind: RUN + value: conda install pytorch=0.4 torchvision=0.2 -c pytorch + - kind: RUN + value: conda install -c conda-forge pycocotools opencv scipy + - kind: ENTRYPOINT + value: '["conda", "run", "-n", "iog"]' + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/main.py b/serverless/pytorch/shiyinzhang/iog/nuclio/main.py new file mode 100644 index 000000000000..84b8eac6f31c --- /dev/null +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/main.py @@ -0,0 +1,33 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import json +import base64 +from PIL import Image +import io +from model_handler import ModelHandler + +def init_context(context): + context.logger.info("Init context... 0%") + + model = ModelHandler() + setattr(context.user_data, 'model', model) + + context.logger.info("Init context...100%") + +def handler(context, event): + context.logger.info("call handler") + data = event.body + pos_points = data["points"][:1] + neg_points = data["points"][1:] + threshold = data.get("threshold", 0.9) + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + image = Image.open(buf) + + polygon = context.user_data.model.handle(image, pos_points, + neg_points, threshold) + return context.Response(body=json.dumps(polygon), + headers={}, + content_type='application/json', + status_code=200) diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py new file mode 100644 index 000000000000..a59c0c67469c --- /dev/null +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py @@ -0,0 +1,117 @@ +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT + +import numpy as np +import os +import cv2 +import torch +from torchvision import transforms +from dataloaders import custom_transforms as tr +from networks.mainnetwork import Network +from PIL import Image +from dataloaders import helpers +import os + +def convert_mask_to_polygon(mask): + mask = np.array(mask, dtype=np.uint8) + cv2.normalize(mask, mask, 0, 255, cv2.NORM_MINMAX) + contours = None + if int(cv2.__version__.split('.')[0]) > 3: + contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)[0] + else: + contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS)[1] + + contours = max(contours, key=lambda arr: arr.size) + if contours.shape.count(1): + contours = np.squeeze(contours) + if contours.size < 3 * 2: + raise Exception('Less then three point have been detected. Can not build a polygon.') + + polygon = [] + for point in contours: + polygon.append([int(point[0]), int(point[1])]) + + return polygon + +class ModelHandler: + def __init__(self): + base_dir = os.environ.get("MODEL_PATH", "/opt/nuclio/iog") + model_path = os.path.join(base_dir, "IOG_PASCAL_SBD.pth") + self.device = torch.device("cpu") + + # Number of input channels (RGB + heatmap of IOG points) + self.net = Network(nInputChannels=5, num_classes=1, backbone='resnet101', + output_stride=16, sync_bn=None, freeze_bn=False) + + pretrain_dict = torch.load(model_path) + self.net.load_state_dict(pretrain_dict) + self.net.to(self.device) + self.net.eval() + + def handle(self, image, pos_points, neg_points, threshold): + with torch.no_grad(): + input_bbox = cv2.boundingBox(np.array(neg_points)) + # extract a crop from the image + crop_padding = 30 + crop_bbox = [ + max(input_bbox[0] - crop_padding, 0), + max(input_bbox[1] - crop_padding, 0), + min(input_bbox[2] + crop_padding, image.width - 1), + min(input_bbox[3] + crop_padding, image.height - 1) + ] + crop_shape = ( + int(crop_bbox[2] - crop_bbox[0] + 1), # width + int(crop_bbox[3] - crop_bbox[1] + 1), # height + ) + + # try to use crop_from_bbox(img, bbox, zero_pad) here + input_crop = np.array(image.crop(crop_bbox)).astype(np.float32) + + # resize the crop + input_crop = cv2.resize(input_crop, (512, 512), interpolation=cv2.INTER_NEAREST) + crop_scale = (512 / crop_shape[0], 512 / crop_shape[1]) + + def translate_points(points): + points = [ + ((p[0] - crop_bbox[0]) * crop_scale[0], # x + (p[1] - crop_bbox[1]) * crop_scale[1]) # y + for p in points] + + return points + + pos_points = translate_points(pos_points) + neg_points = translate_points(neg_points) + + # FIXME: need to constract correct gt (pos_points can be more than 1) + iog_image = helpers.make_gt(input_crop, pos_points + neg_points) + + # Convert iog_image to an image (0-255 values) + iog_image = 255. * (iog_image - iog_image.min()) / (iog_image.max() - iog_image.min() + 1e-10) + + # Concatenate input crop and IOG image + input_blob = np.concatenate((input_crop, iog_image), axis=2) + + # numpy image: H x W x C + # torch image: C X H X W + input_blob = input_blob.transpose((2, 0, 1)) + # batch size is 1 + input_blob = np.array([input_blob]) + input_tensor = torch.from_numpy(input_blob) + + input_tensor = input_tensor.to(self.device) + output_mask = self.net.forward(input_tensor)[4] + output_mask = output_mask.to(self.device) + pred = np.transpose(output_mask.data.numpy()[0, :, :, :], (1, 2, 0)) + pred = pred > threshold + pred = np.squeeze(pred) + + # Convert a mask to a polygon + polygon = convert_mask_to_polygon(pred) + polygon = [ + (int(p[0] + crop_bbox[0]), int(p[1] + crop_bbox[1])) + for p in polygon + ] + + return polygon + From f8bfb5fe75271ddc91a974deb12ddcbf6e598eb4 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Mon, 12 Oct 2020 22:35:33 +0300 Subject: [PATCH 02/24] Fix function.yaml for IOG --- .../shiyinzhang/iog/nuclio/function.yaml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml index 398821e12bb0..eff10325c499 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -25,6 +25,16 @@ spec: preCopy: - kind: WORKDIR value: /opt/nuclio + - kind: RUN + value: conda create -y -n iog python=3.6 + - kind: SHELL + value: '["conda", "run", "-n", "iog", "/bin/bash", "-c"]' + - kind: RUN + value: conda install -y -c anaconda curl + - kind: RUN + value: conda install -y pytorch=0.4 torchvision=0.2 -c pytorch + - kind: RUN + value: conda install -y -c conda-forge pycocotools opencv scipy - kind: RUN value: git clone https://github.com/shiyinzhang/Inside-Outside-Guidance.git iog - kind: WORKDIR @@ -39,14 +49,6 @@ spec: value: curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk '/download/ {print $NF}' ./cookie`&id=${fileid}" -o ${filename} - kind: WORKDIR value: /opt/nuclio - - kind: RUN - value: conda create -y -n iog python=3.6 - - kind: SHELL - value: '["conda", "run", "-n", "iog", "/bin/bash", "-c"]' - - kind: RUN - value: conda install pytorch=0.4 torchvision=0.2 -c pytorch - - kind: RUN - value: conda install -c conda-forge pycocotools opencv scipy - kind: ENTRYPOINT value: '["conda", "run", "-n", "iog"]' From 5e8ccd9eef7e308601e8da728fb5ab579d4f7a6f Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 13 Oct 2020 10:59:36 +0300 Subject: [PATCH 03/24] Add "processorMountMode: volume" to restart containers after reboot (requires nuctl 1.5.0) --- components/serverless/docker-compose.serverless.yml | 2 +- serverless/openvino/dextr/nuclio/function.yaml | 1 + .../person-reidentification-retail-300/nuclio/function.yaml | 1 + .../semantic-segmentation-adas-0001/nuclio/function.yaml | 1 + .../omz/intel/text-detection-0004/nuclio/function.yaml | 1 + .../faster_rcnn_inception_v2_coco/nuclio/function.yaml | 1 + .../nuclio/function.yaml | 1 + .../openvino/omz/public/yolo-v3-tf/nuclio/function.yaml | 1 + serverless/pytorch/foolwood/siammask/nuclio/function.yaml | 1 + serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml | 1 + serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml | 5 ++++- .../faster_rcnn_inception_v2_coco/nuclio/function.yaml | 1 + .../tensorflow/matterport/mask_rcnn/nuclio/function.yaml | 1 + 13 files changed, 16 insertions(+), 2 deletions(-) diff --git a/components/serverless/docker-compose.serverless.yml b/components/serverless/docker-compose.serverless.yml index a0aabf7f101f..527baca77fc0 100644 --- a/components/serverless/docker-compose.serverless.yml +++ b/components/serverless/docker-compose.serverless.yml @@ -2,7 +2,7 @@ version: '3.3' services: serverless: container_name: nuclio - image: quay.io/nuclio/dashboard:1.4.8-amd64 + image: quay.io/nuclio/dashboard:1.5.0-amd64 restart: always networks: default: diff --git a/serverless/openvino/dextr/nuclio/function.yaml b/serverless/openvino/dextr/nuclio/function.yaml index f91182ff10f4..05e247a2d680 100644 --- a/serverless/openvino/dextr/nuclio/function.yaml +++ b/serverless/openvino/dextr/nuclio/function.yaml @@ -48,6 +48,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml index f4a5d2fb0993..9cc1ece99a5c 100644 --- a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml @@ -43,6 +43,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml index 03a1f3c15b8b..4cc25ee7eb57 100644 --- a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml @@ -71,6 +71,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml index 663170077e4c..4191b9e84e0d 100644 --- a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml @@ -44,6 +44,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml index 9cb8b6bf3e4e..2ad17d5ea99c 100644 --- a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -125,6 +125,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml index f08ef796ebd7..0e67e925973d 100644 --- a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml @@ -134,6 +134,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml index 31ea02b4fc48..4051161f6832 100644 --- a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml +++ b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml @@ -126,6 +126,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml index bb165c79d56b..60984ef2d09b 100644 --- a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml +++ b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml @@ -51,6 +51,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml b/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml index d0027e0ff220..1f03125638d4 100644 --- a/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml +++ b/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml @@ -54,6 +54,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml index eff10325c499..e0291dc1d7ee 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -46,7 +46,9 @@ spec: - kind: RUN value: curl -c ./cookie -s -L "https://drive.google.com/uc?export=download&id=${fileid}" - kind: RUN - value: curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk '/download/ {print $NF}' ./cookie`&id=${fileid}" -o ${filename} + value: echo "/download/ {print \$NF}" > confirm_code.awk + - kind: RUN + value: curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk -f confirm_code.awk ./cookie`&id=${fileid}" -o ${filename} - kind: WORKDIR value: /opt/nuclio - kind: ENTRYPOINT @@ -62,6 +64,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml index c58617cea040..838dfabe700c 100644 --- a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml +++ b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -127,6 +127,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml index b50868a6be95..c886acb76ceb 100644 --- a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml +++ b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml @@ -128,6 +128,7 @@ spec: platform: attributes: + processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 From 5e4c8e0118b084259cd2b90d7032ced0f4ac1dff Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 13 Oct 2020 13:24:55 +0300 Subject: [PATCH 04/24] Fix crash in IOG serverless function (it doesn't work right now as well) --- .../pytorch/shiyinzhang/iog/nuclio/function.yaml | 8 ++++---- .../pytorch/shiyinzhang/iog/nuclio/model_handler.py | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml index e0291dc1d7ee..325f512303d0 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -27,8 +27,10 @@ spec: value: /opt/nuclio - kind: RUN value: conda create -y -n iog python=3.6 - - kind: SHELL - value: '["conda", "run", "-n", "iog", "/bin/bash", "-c"]' + - kind: RUN + value: echo "source activate iog" > ~/.bashrc + - kind: ENV + value: PATH=/opt/conda/envs/env/bin:$PATH - kind: RUN value: conda install -y -c anaconda curl - kind: RUN @@ -51,8 +53,6 @@ spec: value: curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk -f confirm_code.awk ./cookie`&id=${fileid}" -o ${filename} - kind: WORKDIR value: /opt/nuclio - - kind: ENTRYPOINT - value: '["conda", "run", "-n", "iog"]' triggers: myHttpTrigger: diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py index a59c0c67469c..da1bfd6757bc 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py @@ -51,14 +51,15 @@ def __init__(self): def handle(self, image, pos_points, neg_points, threshold): with torch.no_grad(): - input_bbox = cv2.boundingBox(np.array(neg_points)) + x, y = np.split(np.transpose(np.array(neg_points)), 2) + bbox = [np.min(x), np.min(y), np.max(x), np.max(y)] # extract a crop from the image crop_padding = 30 crop_bbox = [ - max(input_bbox[0] - crop_padding, 0), - max(input_bbox[1] - crop_padding, 0), - min(input_bbox[2] + crop_padding, image.width - 1), - min(input_bbox[3] + crop_padding, image.height - 1) + max(bbox[0] - crop_padding, 0), + max(bbox[1] - crop_padding, 0), + min(bbox[2] + crop_padding, image.width - 1), + min(bbox[3] + crop_padding, image.height - 1) ] crop_shape = ( int(crop_bbox[2] - crop_bbox[0] + 1), # width From 3cbd3c0710a7f9c5e705c16793dd3680e76548c9 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 13 Oct 2020 14:40:51 +0300 Subject: [PATCH 05/24] Fix for points translation from crop to image. --- .../pytorch/shiyinzhang/iog/nuclio/main.py | 2 +- .../shiyinzhang/iog/nuclio/model_handler.py | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/main.py b/serverless/pytorch/shiyinzhang/iog/nuclio/main.py index 84b8eac6f31c..3d64e4c40cea 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/main.py +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/main.py @@ -21,7 +21,7 @@ def handler(context, event): data = event.body pos_points = data["points"][:1] neg_points = data["points"][1:] - threshold = data.get("threshold", 0.9) + threshold = data.get("threshold", 0.8) buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) image = Image.open(buf) diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py index da1bfd6757bc..aa45cfbec96c 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py @@ -73,7 +73,7 @@ def handle(self, image, pos_points, neg_points, threshold): input_crop = cv2.resize(input_crop, (512, 512), interpolation=cv2.INTER_NEAREST) crop_scale = (512 / crop_shape[0], 512 / crop_shape[1]) - def translate_points(points): + def translate_points_to_crop(points): points = [ ((p[0] - crop_bbox[0]) * crop_scale[0], # x (p[1] - crop_bbox[1]) * crop_scale[1]) # y @@ -81,8 +81,8 @@ def translate_points(points): return points - pos_points = translate_points(pos_points) - neg_points = translate_points(neg_points) + pos_points = translate_points_to_crop(pos_points) + neg_points = translate_points_to_crop(neg_points) # FIXME: need to constract correct gt (pos_points can be more than 1) iog_image = helpers.make_gt(input_crop, pos_points + neg_points) @@ -109,10 +109,15 @@ def translate_points(points): # Convert a mask to a polygon polygon = convert_mask_to_polygon(pred) - polygon = [ - (int(p[0] + crop_bbox[0]), int(p[1] + crop_bbox[1])) - for p in polygon - ] + def translate_points_to_image(points): + points = [ + (p[0] / crop_scale[0] + crop_bbox[0], # x + p[1] / crop_scale[1] + crop_bbox[1]) # y + for p in points] + + return points + + polygon = translate_points_to_image(polygon) return polygon From afc7eef001fe09ede98987dc951b4eb32f22b0ef Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Thu, 22 Oct 2020 16:54:05 +0300 Subject: [PATCH 06/24] Add crop_box parameter to IOG function --- .../shiyinzhang/iog/nuclio/function.yaml | 1 + .../pytorch/shiyinzhang/iog/nuclio/main.py | 15 +++++++++++---- .../shiyinzhang/iog/nuclio/model_handler.py | 18 +++++++++++------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml index 325f512303d0..d3d2da14a522 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -7,6 +7,7 @@ metadata: spec: framework: pytorch min_pos_points: 1 + input: crop, points spec: description: Interactive Object Segmentation with Inside-Outside Guidance diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/main.py b/serverless/pytorch/shiyinzhang/iog/nuclio/main.py index 3d64e4c40cea..50711cd4f6c9 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/main.py +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/main.py @@ -6,6 +6,7 @@ import base64 from PIL import Image import io +import numpy as np from model_handler import ModelHandler def init_context(context): @@ -19,14 +20,20 @@ def init_context(context): def handler(context, event): context.logger.info("call handler") data = event.body - pos_points = data["points"][:1] - neg_points = data["points"][1:] + pos_points = data.get("pos_points", data["points"][:1]) + neg_points = data.get("neg_points", data["points"][1:]) + crop_bbox = data.get("crop_bbox", None) threshold = data.get("threshold", 0.8) buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) image = Image.open(buf) - polygon = context.user_data.model.handle(image, pos_points, - neg_points, threshold) + if crop_bbox is None: + x, y = np.split(np.transpose(np.array(neg_points)), 2) + crop_bbox = [np.min(x), np.min(y), np.max(x), np.max(y)] + neg_points = [] + + polygon = context.user_data.model.handle(image, crop_bbox, + pos_points, neg_points, threshold) return context.Response(body=json.dumps(polygon), headers={}, content_type='application/json', diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py index aa45cfbec96c..1d4456854321 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py @@ -49,11 +49,9 @@ def __init__(self): self.net.to(self.device) self.net.eval() - def handle(self, image, pos_points, neg_points, threshold): + def handle(self, image, bbox, pos_points, neg_points, threshold): with torch.no_grad(): - x, y = np.split(np.transpose(np.array(neg_points)), 2) - bbox = [np.min(x), np.min(y), np.max(x), np.max(y)] - # extract a crop from the image + # extract a crop with padding from the image crop_padding = 30 crop_bbox = [ max(bbox[0] - crop_padding, 0), @@ -84,11 +82,17 @@ def translate_points_to_crop(points): pos_points = translate_points_to_crop(pos_points) neg_points = translate_points_to_crop(neg_points) - # FIXME: need to constract correct gt (pos_points can be more than 1) - iog_image = helpers.make_gt(input_crop, pos_points + neg_points) + # Create IOG image + gt_0 = np.zeros(shape=input_crop.shape[:2], dtype=np.float64) + gt_1 = np.zeros(shape=input_crop.shape[:2], dtype=np.float64) + for p in pos_points: + gt_0 = np.maximum(gt_0, helpers.make_gaussian(gt_0.shape, center=p)) + for p in neg_points: + gt_1 = np.maximum(gt_1, helpers.make_gaussian(gt_1.shape, center=p)) + iog_image = np.stack((gt_0, gt_1), axis=2).astype(dtype=input_crop.dtype) # Convert iog_image to an image (0-255 values) - iog_image = 255. * (iog_image - iog_image.min()) / (iog_image.max() - iog_image.min() + 1e-10) + cv2.normalize(iog_image, iog_image, 0, 255, cv2.NORM_MINMAX) # Concatenate input crop and IOG image input_blob = np.concatenate((input_crop, iog_image), axis=2) From d23e76b2bda77ea82a26f92893c94c0e24e6f748 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Thu, 22 Oct 2020 17:26:11 +0300 Subject: [PATCH 07/24] Update nuclio dashboard till 1.5.1 version --- components/serverless/docker-compose.serverless.yml | 2 +- .../pytorch/shiyinzhang/iog/nuclio/model_handler.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/serverless/docker-compose.serverless.yml b/components/serverless/docker-compose.serverless.yml index 527baca77fc0..659ce81a0b7c 100644 --- a/components/serverless/docker-compose.serverless.yml +++ b/components/serverless/docker-compose.serverless.yml @@ -2,7 +2,7 @@ version: '3.3' services: serverless: container_name: nuclio - image: quay.io/nuclio/dashboard:1.5.0-amd64 + image: quay.io/nuclio/dashboard:1.5.1-amd64 restart: always networks: default: diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py index 1d4456854321..19a8874bb3c9 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py @@ -83,13 +83,13 @@ def translate_points_to_crop(points): neg_points = translate_points_to_crop(neg_points) # Create IOG image - gt_0 = np.zeros(shape=input_crop.shape[:2], dtype=np.float64) - gt_1 = np.zeros(shape=input_crop.shape[:2], dtype=np.float64) + pos_gt = np.zeros(shape=input_crop.shape[:2], dtype=np.float64) + neg_gt = np.zeros(shape=input_crop.shape[:2], dtype=np.float64) for p in pos_points: - gt_0 = np.maximum(gt_0, helpers.make_gaussian(gt_0.shape, center=p)) + pos_gt = np.maximum(pos_gt, helpers.make_gaussian(pos_gt.shape, center=p)) for p in neg_points: - gt_1 = np.maximum(gt_1, helpers.make_gaussian(gt_1.shape, center=p)) - iog_image = np.stack((gt_0, gt_1), axis=2).astype(dtype=input_crop.dtype) + neg_gt = np.maximum(neg_gt, helpers.make_gaussian(neg_gt.shape, center=p)) + iog_image = np.stack((pos_gt, neg_gt), axis=2).astype(dtype=input_crop.dtype) # Convert iog_image to an image (0-255 values) cv2.normalize(iog_image, iog_image, 0, 255, cv2.NORM_MINMAX) From 119d30fd9033d6b027bcdbb508dd9a2404c9427b Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Fri, 23 Oct 2020 06:59:17 +0300 Subject: [PATCH 08/24] Support neg_points in interactors --- .vscode/launch.json | 3 ++ .../controls-side-bar/tools-control.tsx | 7 +++-- cvat/apps/lambda_manager/views.py | 30 +++++++++++++------ serverless/openvino/dextr/nuclio/main.py | 2 +- .../pytorch/saic-vul/fbrs/nuclio/main.py | 4 +-- .../shiyinzhang/iog/nuclio/function.yaml | 2 +- .../pytorch/shiyinzhang/iog/nuclio/main.py | 12 ++++---- 7 files changed, 38 insertions(+), 22 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 48bc45835ce0..69dfa0bdf71a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -29,6 +29,9 @@ "justMyCode": false, "pythonPath": "${command:python.interpreterPath}", "program": "${workspaceRoot}/manage.py", + "env": { + "CVAT_SERVERLESS": "1", + }, "args": [ "runserver", "--noreload", diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx index 89d89912df27..b51d4a9860d6 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/controls-side-bar/tools-control.tsx @@ -91,7 +91,7 @@ const mapDispatchToProps = { createAnnotations: createAnnotationsAsync, }; -function convertShapesForInteractor(shapes: InteractionResult[]): number[][] { +function convertShapesForInteractor(shapes: InteractionResult[], button: number): number[][] { const reducer = (acc: number[][], _: number, index: number, array: number[]): number[][] => { if (!(index % 2)) { // 0, 2, 4 acc.push([ @@ -102,7 +102,7 @@ function convertShapesForInteractor(shapes: InteractionResult[]): number[][] { return acc; }; - return shapes.filter((shape: InteractionResult): boolean => shape.shapeType === 'points' && shape.button === 0) + return shapes.filter((shape: InteractionResult): boolean => shape.shapeType === 'points' && shape.button === button) .map((shape: InteractionResult): number[] => shape.points) .flat().reduce(reducer, []); } @@ -238,7 +238,8 @@ export class ToolsControlComponent extends React.PureComponent { try { result = await core.lambda.call(jobInstance.task, interactor, { frame, - points: convertShapesForInteractor((e as CustomEvent).detail.shapes), + pos_points: convertShapesForInteractor((e as CustomEvent).detail.shapes, 0), + neg_points: convertShapesForInteractor((e as CustomEvent).detail.shapes, 2), }); if (this.interactionIsAborted) { diff --git a/cvat/apps/lambda_manager/views.py b/cvat/apps/lambda_manager/views.py index 4e5ede354934..674db1a7fc67 100644 --- a/cvat/apps/lambda_manager/views.py +++ b/cvat/apps/lambda_manager/views.py @@ -86,13 +86,14 @@ def __init__(self, gateway, data): # ID of the function (e.g. omz.public.yolo-v3) self.id = data['metadata']['name'] # type of the function (e.g. detector, interactor) - kind = data['metadata']['annotations'].get('type') + meta_anno = data['metadata']['annotations'] + kind = meta_anno.get('type') try: self.kind = LambdaType(kind) except ValueError: self.kind = LambdaType.UNKNOWN # dictionary of labels for the function (e.g. car, person) - spec = json.loads(data['metadata']['annotations'].get('spec') or '[]') + spec = json.loads(meta_anno.get('spec') or '[]') labels = [item['name'] for item in spec] if len(labels) != len(set(labels)): raise ValidationError( @@ -106,10 +107,11 @@ def __init__(self, gateway, data): # http port to access the serverless function self.port = data["status"].get("httpPort") # framework which is used for the function (e.g. tensorflow, openvino) - self.framework = data['metadata']['annotations'].get('framework') + self.framework = meta_anno.get('framework') # display name for the function - self.name = data['metadata']['annotations'].get('name', self.id) - self.min_pos_points = int(data['metadata']['annotations'].get('min_pos_points', 1)) + self.name = meta_anno.get('name', self.id) + self.min_pos_points = int(meta_anno.get('min_pos_points', 1)) + self.startswith_box = bool(meta_anno.get('startswith_box', False)) self.gateway = gateway def to_dict(self): @@ -117,13 +119,22 @@ def to_dict(self): 'id': self.id, 'kind': str(self.kind), 'labels': self.labels, - 'state': self.state, 'description': self.description, 'framework': self.framework, - 'name': self.name, - 'min_pos_points': self.min_pos_points + 'name': self.name } + if self.kind is LambdaType.INTERACTOR: + response.update({ + 'min_pos_points': self.min_pos_points, + 'startswith_box': self.startswith_box + }) + + if self.kind is LambdaType.TRACKER: + response.update({ + 'state': self.state + }) + return response def invoke(self, db_task, data): @@ -153,7 +164,8 @@ def invoke(self, db_task, data): elif self.kind == LambdaType.INTERACTOR: payload.update({ "image": self._get_image(db_task, data["frame"], quality), - "points": data["points"], + "pos_points": data["pos_points"], + "neg_points": data["neg_points"] }) elif self.kind == LambdaType.REID: payload.update({ diff --git a/serverless/openvino/dextr/nuclio/main.py b/serverless/openvino/dextr/nuclio/main.py index 73617002c69d..10f47026bb29 100644 --- a/serverless/openvino/dextr/nuclio/main.py +++ b/serverless/openvino/dextr/nuclio/main.py @@ -15,7 +15,7 @@ def init_context(context): def handler(context, event): context.logger.info("call handler") data = event.body - points = data["points"] + points = data["pos_points"] buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) image = Image.open(buf) diff --git a/serverless/pytorch/saic-vul/fbrs/nuclio/main.py b/serverless/pytorch/saic-vul/fbrs/nuclio/main.py index 300bc294c6a7..ad1f8eddf880 100644 --- a/serverless/pytorch/saic-vul/fbrs/nuclio/main.py +++ b/serverless/pytorch/saic-vul/fbrs/nuclio/main.py @@ -19,8 +19,8 @@ def init_context(context): def handler(context, event): context.logger.info("call handler") data = event.body - pos_points = data["points"] - neg_points = [] + pos_points = data["pos_points"] + neg_points = data["neg_points"] threshold = data.get("threshold", 0.5) buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) image = Image.open(buf) diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml index d3d2da14a522..4672627a3585 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -7,7 +7,7 @@ metadata: spec: framework: pytorch min_pos_points: 1 - input: crop, points + startswith_box: true spec: description: Interactive Object Segmentation with Inside-Outside Guidance diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/main.py b/serverless/pytorch/shiyinzhang/iog/nuclio/main.py index 50711cd4f6c9..16c4d732dbe1 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/main.py +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/main.py @@ -20,19 +20,19 @@ def init_context(context): def handler(context, event): context.logger.info("call handler") data = event.body - pos_points = data.get("pos_points", data["points"][:1]) - neg_points = data.get("neg_points", data["points"][1:]) - crop_bbox = data.get("crop_bbox", None) + pos_points = data["pos_points"] + neg_points = data["neg_points"] + obj_bbox = data.get("obj_bbox", None) threshold = data.get("threshold", 0.8) buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) image = Image.open(buf) - if crop_bbox is None: + if obj_bbox is None: x, y = np.split(np.transpose(np.array(neg_points)), 2) - crop_bbox = [np.min(x), np.min(y), np.max(x), np.max(y)] + obj_bbox = [np.min(x), np.min(y), np.max(x), np.max(y)] neg_points = [] - polygon = context.user_data.model.handle(image, crop_bbox, + polygon = context.user_data.model.handle(image, obj_bbox, pos_points, neg_points, threshold) return context.Response(body=json.dumps(polygon), headers={}, From 208528d1e8128457fb62186297053dd0103fab59 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Fri, 23 Oct 2020 10:34:09 +0300 Subject: [PATCH 09/24] Add dummy serverless function for optimization --- serverless/dummy/nuclio/function.yaml | 41 +++++++++++++++++++++++++++ serverless/dummy/nuclio/main.py | 14 +++++++++ 2 files changed, 55 insertions(+) create mode 100644 serverless/dummy/nuclio/function.yaml create mode 100644 serverless/dummy/nuclio/main.py diff --git a/serverless/dummy/nuclio/function.yaml b/serverless/dummy/nuclio/function.yaml new file mode 100644 index 000000000000..d6d79aaa3170 --- /dev/null +++ b/serverless/dummy/nuclio/function.yaml @@ -0,0 +1,41 @@ +metadata: + name: dummy + namespace: cvat + annotations: + name: dummy + type: detector + framework: custom + spec: | + [ + { "id": 1, "name": "person" } + ] + +spec: + description: Dummy function for testing overhead + runtime: "python:3.6" + handler: main:handler + eventTimeout: 30s + + build: + image: cvat/dummy + baseImage: python:3.6.11 + + directives: + postCopy: + - kind: RUN + value: pip install pillow + + triggers: + myHttpTrigger: + maxWorkers: 2 + kind: "http" + workerAvailabilityTimeoutMilliseconds: 10000 + attributes: + maxRequestBodySize: 33554432 # 32MB + + platform: + attributes: + processorMountMode: volume + restartPolicy: + name: always + maximumRetryCount: 3 diff --git a/serverless/dummy/nuclio/main.py b/serverless/dummy/nuclio/main.py new file mode 100644 index 000000000000..9c46e7116883 --- /dev/null +++ b/serverless/dummy/nuclio/main.py @@ -0,0 +1,14 @@ +import json +import base64 +from PIL import Image +import io + +def handler(context, event): + context.logger.info("Run yolo-v3-tf model") + data = event.body + buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) + image = Image.open(buf) + image.rotate(90) # dummy work and avoid an unused variable warnings + + return context.Response(body=json.dumps([]), headers={}, + content_type='application/json', status_code=200) From 3f647d08c400929ed78d824b68f52db0fb7b3df7 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Fri, 23 Oct 2020 11:06:18 +0300 Subject: [PATCH 10/24] Remove dummy serverless function and update the list of available serverless functions --- README.md | 12 +++++--- serverless/dummy/nuclio/function.yaml | 41 --------------------------- serverless/dummy/nuclio/main.py | 14 --------- 3 files changed, 8 insertions(+), 59 deletions(-) delete mode 100644 serverless/dummy/nuclio/function.yaml delete mode 100644 serverless/dummy/nuclio/main.py diff --git a/README.md b/README.md index 552f41a99c9d..8190943ae09b 100644 --- a/README.md +++ b/README.md @@ -59,18 +59,22 @@ via its command line tool and Python library. | [MOT](https://motchallenge.net/) | X | X | | [LabelMe 3.0](http://labelme.csail.mit.edu/Release3.0) | X | X | -## Deep learning models for automatic labeling +## Deep learning serverless functions for automatic labeling | Name | Type | Framework | | ------------------------------------------------------------------------------------------------------- | ---------- | ---------- | | [Deep Extreme Cut](/serverless/openvino/dextr/nuclio) | interactor | OpenVINO | -| [Faster RCNN](/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio) | detector | TensorFlow | +| [Faster RCNN](/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio) | detector | OpenVINO | | [Mask RCNN](/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio) | detector | OpenVINO | | [YOLO v3](/serverless/openvino/omz/public/yolo-v3-tf/nuclio) | detector | OpenVINO | -| [Text detection v4](/serverless/openvino/omz/intel/text-detection-0004/nuclio) | detector | OpenVINO | +| [Object reidentification](/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio) | reid | OpenVINO | | [Semantic segmentation for ADAS](/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio) | detector | OpenVINO | +| [Text detection v4](/serverless/openvino/omz/intel/text-detection-0004/nuclio) | detector | OpenVINO | +| [SiamMask](/serverless/pytorch/foolwood/siammask/nuclio) | tracker | PyTorch | +| [f-BRS](/serverless/pytorch/saic-vul/fbrs/nuclio) | interactor | PyTorch | +| [Inside-Outside Guidance](/serverless/pytorch/shiyinzhang/iog/nuclio) | interactor | PyTorch | +| [Faster RCNN](/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio) | detector | TensorFlow | | [Mask RCNN](/serverless/tensorflow/matterport/mask_rcnn/nuclio) | detector | TensorFlow | -| [Object reidentification](/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio) | reid | OpenVINO | ## Online demo: [cvat.org](https://cvat.org) diff --git a/serverless/dummy/nuclio/function.yaml b/serverless/dummy/nuclio/function.yaml deleted file mode 100644 index d6d79aaa3170..000000000000 --- a/serverless/dummy/nuclio/function.yaml +++ /dev/null @@ -1,41 +0,0 @@ -metadata: - name: dummy - namespace: cvat - annotations: - name: dummy - type: detector - framework: custom - spec: | - [ - { "id": 1, "name": "person" } - ] - -spec: - description: Dummy function for testing overhead - runtime: "python:3.6" - handler: main:handler - eventTimeout: 30s - - build: - image: cvat/dummy - baseImage: python:3.6.11 - - directives: - postCopy: - - kind: RUN - value: pip install pillow - - triggers: - myHttpTrigger: - maxWorkers: 2 - kind: "http" - workerAvailabilityTimeoutMilliseconds: 10000 - attributes: - maxRequestBodySize: 33554432 # 32MB - - platform: - attributes: - processorMountMode: volume - restartPolicy: - name: always - maximumRetryCount: 3 diff --git a/serverless/dummy/nuclio/main.py b/serverless/dummy/nuclio/main.py deleted file mode 100644 index 9c46e7116883..000000000000 --- a/serverless/dummy/nuclio/main.py +++ /dev/null @@ -1,14 +0,0 @@ -import json -import base64 -from PIL import Image -import io - -def handler(context, event): - context.logger.info("Run yolo-v3-tf model") - data = event.body - buf = io.BytesIO(base64.b64decode(data["image"].encode('utf-8'))) - image = Image.open(buf) - image.rotate(90) # dummy work and avoid an unused variable warnings - - return context.Response(body=json.dumps([]), headers={}, - content_type='application/json', status_code=200) From 8f7a05521bd907b984e9ec2b882427b3a812270b Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Sat, 24 Oct 2020 16:48:47 +0300 Subject: [PATCH 11/24] Improved deployment process of serverless functions --- .../openvino}/model_loader.py | 0 .../common => common/openvino}/python3 | 2 +- serverless/deploy.sh | 59 ++++--------------- .../openvino/dextr/nuclio/function.yaml | 2 +- .../nuclio/function.yaml | 2 +- .../nuclio/function.yaml | 2 +- .../text-detection-0004/nuclio/function.yaml | 2 +- .../nuclio/function.yaml | 2 +- .../nuclio/function.yaml | 2 +- .../public/yolo-v3-tf/nuclio/function.yaml | 2 +- 10 files changed, 19 insertions(+), 56 deletions(-) rename serverless/{openvino/common => common/openvino}/model_loader.py (100%) rename serverless/{openvino/common => common/openvino}/python3 (62%) diff --git a/serverless/openvino/common/model_loader.py b/serverless/common/openvino/model_loader.py similarity index 100% rename from serverless/openvino/common/model_loader.py rename to serverless/common/openvino/model_loader.py diff --git a/serverless/openvino/common/python3 b/serverless/common/openvino/python3 similarity index 62% rename from serverless/openvino/common/python3 rename to serverless/common/openvino/python3 index fca7518d4099..dfd05669c2b2 100755 --- a/serverless/openvino/common/python3 +++ b/serverless/common/openvino/python3 @@ -3,5 +3,5 @@ args=$@ . /opt/intel/openvino/bin/setupvars.sh -PYTHONPATH=/opt/nuclio/common:$PYTHONPATH +PYTHONPATH=/opt/nuclio/common/openvino:$PYTHONPATH /usr/bin/python3 $args diff --git a/serverless/deploy.sh b/serverless/deploy.sh index 20face66bf55..bdaff1fbabb3 100755 --- a/serverless/deploy.sh +++ b/serverless/deploy.sh @@ -1,57 +1,20 @@ #!/bin/bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +FUNCTIONS_DIR=${1:-$SCRIPT_DIR} nuctl create project cvat -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio" \ - --volume "$SCRIPT_DIR/openvino/common:/opt/nuclio/common" \ - --platform local -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio" \ - --volume "$SCRIPT_DIR/openvino/common:/opt/nuclio/common" \ - --platform local +for func_config in $(find "$FUNCTIONS_DIR" -name "function.yaml") +do + func_root=$(dirname "$func_config") + func_name=$(dirname "$func_root") + echo Deploying $func_name function... + nuctl deploy --project-name cvat --path "$func_root" \ + --volume "$SCRIPT_DIR/common:/opt/nuclio/common" \ + --platform local +done -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/openvino/omz/public/yolo-v3-tf/nuclio" \ - --volume "$SCRIPT_DIR/openvino/common:/opt/nuclio/common" \ - --platform local - -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/openvino/omz/intel/text-detection-0004/nuclio" \ - --volume "$SCRIPT_DIR/openvino/common:/opt/nuclio/common" \ - --platform local - -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio" \ - --volume "$SCRIPT_DIR/openvino/common:/opt/nuclio/common" \ - --platform local - -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/openvino/omz/intel/person-reidentification-retail-300/nuclio" \ - --volume "$SCRIPT_DIR/openvino/common:/opt/nuclio/common" \ - --platform local - -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/openvino/dextr/nuclio" \ - --volume "$SCRIPT_DIR/openvino/common:/opt/nuclio/common" \ - --platform local - -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/tensorflow/matterport/mask_rcnn/nuclio" \ - --platform local - -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/tensorflow/faster_rcnn_inception_v2_coco/nuclio" \ - --platform local - -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/pytorch/foolwood/siammask/nuclio" \ - --platform local +nuctl get function -nuctl deploy --project-name cvat \ - --path "$SCRIPT_DIR/pytorch/saic-vul/fbrs/nuclio" \ - --platform local -nuctl get function diff --git a/serverless/openvino/dextr/nuclio/function.yaml b/serverless/openvino/dextr/nuclio/function.yaml index 05e247a2d680..65e001136edb 100644 --- a/serverless/openvino/dextr/nuclio/function.yaml +++ b/serverless/openvino/dextr/nuclio/function.yaml @@ -15,7 +15,7 @@ spec: eventTimeout: 30s env: - name: NUCLIO_PYTHON_EXE_PATH - value: /opt/nuclio/common/python3 + value: /opt/nuclio/common/openvino/python3 build: image: cvat/openvino.dextr diff --git a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml index 9cc1ece99a5c..e5ef833204ef 100644 --- a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml @@ -14,7 +14,7 @@ spec: eventTimeout: 30s env: - name: NUCLIO_PYTHON_EXE_PATH - value: /opt/nuclio/common/python3 + value: /opt/nuclio/common/openvino/python3 build: image: cvat/openvino.omz.intel.person-reidentification-retail-0300 diff --git a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml index 4cc25ee7eb57..c0b381a67449 100644 --- a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml @@ -37,7 +37,7 @@ spec: eventTimeout: 30s env: - name: NUCLIO_PYTHON_EXE_PATH - value: /opt/nuclio/common/python3 + value: /opt/nuclio/common/openvino/python3 build: image: cvat/openvino.omz.intel.semantic-segmentation-adas-0001 diff --git a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml index 4191b9e84e0d..c7163364cd42 100644 --- a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml @@ -17,7 +17,7 @@ spec: eventTimeout: 30s env: - name: NUCLIO_PYTHON_EXE_PATH - value: /opt/nuclio/common/python3 + value: /opt/nuclio/common/openvino/python3 build: image: cvat/openvino.omz.intel.text-detection-0004 diff --git a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml index 2ad17d5ea99c..08ad11d33cda 100644 --- a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -96,7 +96,7 @@ spec: eventTimeout: 30s env: - name: NUCLIO_PYTHON_EXE_PATH - value: /opt/nuclio/common/python3 + value: /opt/nuclio/common/openvino/python3 build: image: cvat/openvino.omz.public.faster_rcnn_inception_v2_coco diff --git a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml index 0e67e925973d..be4cd2c09dff 100644 --- a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml @@ -99,7 +99,7 @@ spec: eventTimeout: 60s env: - name: NUCLIO_PYTHON_EXE_PATH - value: /opt/nuclio/common/python3 + value: /opt/nuclio/common/openvino/python3 build: image: cvat/openvino.omz.public.mask_rcnn_inception_resnet_v2_atrous_coco diff --git a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml index 4051161f6832..d29060725f4e 100644 --- a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml +++ b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml @@ -96,7 +96,7 @@ spec: eventTimeout: 30s env: - name: NUCLIO_PYTHON_EXE_PATH - value: /opt/nuclio/common/python3 + value: /opt/nuclio/common/openvino/python3 build: image: cvat/openvino.omz.public.yolo-v3-tf From 1b14f38f7d5a4b6436550ed91abec1254bdbb0aa Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Sat, 24 Oct 2020 23:01:04 +0300 Subject: [PATCH 12/24] Improve installation.md for serverless functions. --- cvat/apps/documentation/installation.md | 47 +++++++++++++------------ serverless/deploy.sh | 3 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/cvat/apps/documentation/installation.md b/cvat/apps/documentation/installation.md index c7ecfdb3abf0..272c56c42dae 100644 --- a/cvat/apps/documentation/installation.md +++ b/cvat/apps/documentation/installation.md @@ -277,37 +277,38 @@ Please see the [Docker documentation](https://docs.docker.com/network/proxy/) fo ```bash # Build and run containers with Analytics component support: -docker-compose -f docker-compose.yml -f components/analytics/docker-compose.analytics.yml up -d --build +docker-compose -f docker-compose.yml \ + -f components/analytics/docker-compose.analytics.yml up -d --build ``` ### Semi-automatic and automatic annotation -- You have to install `nuctl` command line tool to build and deploy serverless -functions. Download [the latest release](https://github.com/nuclio/nuclio/releases). -- Create `cvat` project inside nuclio dashboard where you will deploy new -serverless functions and deploy a couple of DL models. Commands below should -be run only after CVAT has been installed using docker-compose because it -runs nuclio dashboard which manages all serverless functions. +- You have to install `nuctl` command line tool to build and deploy serverless + functions. Download [1.5.x release](https://github.com/nuclio/nuclio/releases). + It wil be used to install prepared serverless functions which can run DL models + to automatically annotate images on the server. -```bash -nuctl create project cvat -``` +- Be sure that nuclio dashboard is up and running. It manages all serverless + functions for automatic and semi-automatic annotation. To do that you should + specify docker-compose.serverless.yml in command line. See an example below: -```bash -nuctl deploy --project-name cvat \ - --path serverless/openvino/dextr/nuclio \ - --volume `pwd`/serverless/openvino/common:/opt/nuclio/common \ - --platform local -``` + ```bash + # Build and run containers with the serverless component support: + docker-compose -f docker-compose.yml \ + -f components/serverless/docker-compose.serverless.yml up -d --build + ``` -```bash -nuctl deploy --project-name cvat \ - --path serverless/openvino/omz/public/yolo-v3-tf/nuclio \ - --volume `pwd`/serverless/openvino/common:/opt/nuclio/common \ - --platform local -``` +- Deploy built-in serverless functions from [serverless directory](/serverless) + or deploy your own custom serverless functions. Use [deploy.sh](/serverless/deploy.sh) + script which is a wrapper for `nuctl` command. Basically you need to provide to + the script a directory with one or more serverless functions and all of them + will be deployed. Commands below install DEXTR for semi-automatic + segmentation and YOLOv3 to detect objects automatically. -Note: see [deploy.sh](/serverless/deploy.sh) script for more examples. + ```bash + deploy.sh serverless/openvino/dextr + deploy.sh serverless/openvino/omz/public/yolo-v3-tf + ``` ### Stop all containers diff --git a/serverless/deploy.sh b/serverless/deploy.sh index bdaff1fbabb3..f31d9d48721b 100755 --- a/serverless/deploy.sh +++ b/serverless/deploy.sh @@ -8,8 +8,7 @@ nuctl create project cvat for func_config in $(find "$FUNCTIONS_DIR" -name "function.yaml") do func_root=$(dirname "$func_config") - func_name=$(dirname "$func_root") - echo Deploying $func_name function... + echo Deploying $(dirname "$func_root") function... nuctl deploy --project-name cvat --path "$func_root" \ --volume "$SCRIPT_DIR/common:/opt/nuclio/common" \ --platform local From ec08d4ad7c3804586809fb78deec0af1f0ce62c7 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Sat, 24 Oct 2020 23:05:36 +0300 Subject: [PATCH 13/24] Minor changes in doc for serverless --- components/serverless/README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/components/serverless/README.md b/components/serverless/README.md index 5a64033ad855..b86a3f296c20 100644 --- a/components/serverless/README.md +++ b/components/serverless/README.md @@ -1,11 +1,26 @@ ## Serverless for Computer Vision Annotation Tool (CVAT) ### Run docker container + +To use automatic and semi-automatic annotation models you need to install extra +components which are used by CVAT to implement the functionality. You can do that +by the command below: + ```bash # From project root directory docker-compose -f docker-compose.yml -f components/serverless/docker-compose.serverless.yml up -d ``` +It will run [nuclio](https://github.com/nuclio/nuclio). Nuclio is a +high-performance `serverless` framework focused on data, I/O, and compute +intensive workloads. + +But it isn't enough. You have to deploy one or several serverless functions +which you can use in UI to annotate images. Basically a serverless function +for us is a docker container with HTTP interface which accepts some input in +json format, executes some code to process the input, and + + ### Tutorial how to add your own DL model for automatic annotation Let's try to integration [IOG algorithms for interactive segmentation](https://github.com/shiyinzhang/Inside-Outside-Guidance). @@ -27,7 +42,7 @@ conda install -c conda-forge scipy ``` Download weights from google drive: https://github.com/shiyinzhang/Inside-Outside-Guidance#pretrained-models -Also we will need VOCtrainval_11-May-2012.tar dataset for evaluation: http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar +Also we will need `VOCtrainval_11-May-2012.tar` dataset for evaluation: http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar Modify `mypath.py` in accordance with instructions inside the repo. In my case `git diff` below: From b7b4d795bf053b4c8b0e3172ef640c745f1b895d Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 15 Dec 2020 23:38:21 +0300 Subject: [PATCH 14/24] Revert the tutorial. --- components/serverless/README.md | 97 --------------------------------- 1 file changed, 97 deletions(-) diff --git a/components/serverless/README.md b/components/serverless/README.md index b86a3f296c20..94edd9af100f 100644 --- a/components/serverless/README.md +++ b/components/serverless/README.md @@ -2,104 +2,7 @@ ### Run docker container -To use automatic and semi-automatic annotation models you need to install extra -components which are used by CVAT to implement the functionality. You can do that -by the command below: - ```bash # From project root directory docker-compose -f docker-compose.yml -f components/serverless/docker-compose.serverless.yml up -d ``` - -It will run [nuclio](https://github.com/nuclio/nuclio). Nuclio is a -high-performance `serverless` framework focused on data, I/O, and compute -intensive workloads. - -But it isn't enough. You have to deploy one or several serverless functions -which you can use in UI to annotate images. Basically a serverless function -for us is a docker container with HTTP interface which accepts some input in -json format, executes some code to process the input, and - - -### Tutorial how to add your own DL model for automatic annotation - -Let's try to integration [IOG algorithms for interactive segmentation](https://github.com/shiyinzhang/Inside-Outside-Guidance). - -First of all let's run the model on your local machine. The repo doesn't have good instructions and look -like uses outdated versions of packages. The building process is going to be funny. For old version of -pytorch packages it is better to use conda. See below a possible instructions how to run the model on a -local machine. - -```bash -git clone https://github.com/shiyinzhang/Inside-Outside-Guidance -cd Inside-Outside-Guidance/ -conda create --name iog python=3.6 -conda activate iog -conda install pytorch=0.4 torchvision=0.2 -c pytorch -conda install -c conda-forge pycocotools -conda install -c conda-forge opencv -conda install -c conda-forge scipy -``` - -Download weights from google drive: https://github.com/shiyinzhang/Inside-Outside-Guidance#pretrained-models -Also we will need `VOCtrainval_11-May-2012.tar` dataset for evaluation: http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar - -Modify `mypath.py` in accordance with instructions inside the repo. In my case `git diff` below: - -```python -diff --git a/mypath.py b/mypath.py -index 0df1565..cd0fa3f 100644 ---- a/mypath.py -+++ b/mypath.py -@@ -3,15 +3,15 @@ class Path(object): - @staticmethod - def db_root_dir(database): - if database == 'pascal': -- return '/path/to/PASCAL/VOC2012' # folder that contains VOCdevkit/. -+ return '/Users/nmanovic/Workspace/datasets/VOCtrainval_11-May-2012/' # folder that contains VOCdevkit/. - - elif database == 'sbd': -- return '/path/to/SBD/' # folder with img/, inst/, cls/, etc. -+ return '/Users/nmanovic/Workspace/datasets/SBD/dataset/' # folder with img/, inst/, cls/, etc. - else: - print('Database {} not available.'.format(database)) - raise NotImplementedError - - @staticmethod - def models_dir(): -- return '/path/to/models/resnet101-5d3b4d8f.pth' -+ return '/Users/nmanovic/Workspace/Inside-Outside-Guidance/IOG_PASCAL_SBD.pth' - #'resnet101-5d3b4d8f.pth' #resnet50-19c8e357.pth' -``` - -It looks like need to update `test.py` to run it without `train.py` script. - -```python -diff --git a/test.py b/test.py -index f85969a..8e481d0 100644 ---- a/test.py -+++ b/test.py -@@ -51,9 +51,10 @@ net = Network(nInputChannels=nInputChannels,num_classes=1, - freeze_bn=False) - - # load pretrain_dict --pretrain_dict = torch.load(os.path.join(save_dir, 'models', modelName + '_epoch-' + str(resume_epoch - 1) + '.pth')) --print("Initializing weights from: {}".format( -- os.path.join(save_dir, 'models', modelName + '_epoch-' + str(resume_epoch - 1) + '.pth'))) -+#pretrain_dict = torch.load(os.path.join(save_dir, 'models', modelName + '_epoch-' + str(resume_epoch - 1) + '.pth')) -+#print("Initializing weights from: {}".format( -+# os.path.join(save_dir, 'models', modelName + '_epoch-' + str(resume_epoch - 1) + '.pth'))) -+pretrain_dict = torch.load('/Users/nmanovic/Workspace/Inside-Outside-Guidance/IOG_PASCAL_SBD.pth') - net.load_state_dict(pretrain_dict) - net.to(device) - ``` - -Now it is possible to run `test.py` and it will generate results inside `./run_0/Results` directory. -It is already a great progress. We can run the pretrained model and get results. Next step is to -implement a simple script which will accept an image with a bounding box and generate a mask for the -object. Let's do that. - -```bash -cp test.py model_handler.py -``` - From 63eb39d1c51151073c4d2a07d08ba23d109a0099 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 9 Feb 2021 21:19:17 +0300 Subject: [PATCH 15/24] Fix codacy issues --- .vscode/launch.json | 14 +++++++------- README.md | 13 ++++++++----- .../shiyinzhang/iog/nuclio/model_handler.py | 4 ---- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index eb21070a54a0..658abd2fe482 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -42,7 +42,7 @@ "request": "launch", "stopOnEntry": false, "justMyCode": false, - "pythonPath": "${command:python.interpreterPath}", + "python": "${command:python.interpreterPath}", "program": "${workspaceRoot}/manage.py", "env": { "CVAT_SERVERLESS": "1", @@ -76,7 +76,7 @@ "request": "launch", "stopOnEntry": false, "justMyCode": false, - "pythonPath": "${command:python.interpreterPath}", + "python": "${command:python.interpreterPath}", "program": "${workspaceRoot}/manage.py", "args": [ "rqworker", @@ -95,7 +95,7 @@ "request": "launch", "stopOnEntry": false, "justMyCode": false, - "pythonPath": "${command:python.interpreterPath}", + "python": "${command:python.interpreterPath}", "program": "${workspaceRoot}/manage.py", "args": [ "rqscheduler", @@ -111,7 +111,7 @@ "request": "launch", "justMyCode": false, "stopOnEntry": false, - "pythonPath":"${command:python.interpreterPath}", + "python":"${command:python.interpreterPath}", "program": "${workspaceRoot}/manage.py", "args": [ "rqworker", @@ -130,7 +130,7 @@ "request": "launch", "justMyCode": false, "stopOnEntry": false, - "pythonPath": "${command:python.interpreterPath}", + "python": "${command:python.interpreterPath}", "program": "${workspaceRoot}/manage.py", "args": [ "update_git_states" @@ -146,7 +146,7 @@ "request": "launch", "justMyCode": false, "stopOnEntry": false, - "pythonPath": "${command:python.interpreterPath}", + "python": "${command:python.interpreterPath}", "program": "${workspaceRoot}/manage.py", "args": [ "migrate" @@ -162,7 +162,7 @@ "request": "launch", "justMyCode": false, "stopOnEntry": false, - "pythonPath": "${command:python.interpreterPath}", + "python": "${command:python.interpreterPath}", "program": "${workspaceRoot}/manage.py", "args": [ "test", diff --git a/README.md b/README.md index 12e6c889489f..77b53e75a336 100644 --- a/README.md +++ b/README.md @@ -97,11 +97,12 @@ Limitations: ## REST API -Automatically generated Swagger documentation for Django REST API is -available on `/api/swagger` -(default: `localhost:8080/api/swagger`). +Automatically generated Swagger documentation for Django REST API is available +on `/api/swagger`(default: `localhost:8080/api/swagger`). -Swagger documentation is visiable on allowed hostes, Update environement variable in docker-compose.yml file with cvat hosted machine IP or domain name. Example - `ALLOWED_HOSTS: 'localhost, 127.0.0.1'`) +Swagger documentation is visiable on allowed hostes, Update environement +variable in docker-compose.yml file with cvat hosted machine IP or domain +name. Example - `ALLOWED_HOSTS: 'localhost, 127.0.0.1'`. ## LICENSE @@ -133,4 +134,6 @@ Other ways to ask questions and get our support: ## Projects using CVAT -- [Onepanel](https://github.com/onepanelio/core) - Onepanel is an open source vision AI platform that fully integrates CVAT with scalable data processing and parallelized training pipelines. +- [Onepanel](https://github.com/onepanelio/core) - Onepanel is an open source + vision AI platform that fully integrates CVAT with scalable data processing + and parallelized training pipelines. diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py index 19a8874bb3c9..5d972915d35d 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/model_handler.py @@ -6,12 +6,8 @@ import os import cv2 import torch -from torchvision import transforms -from dataloaders import custom_transforms as tr from networks.mainnetwork import Network -from PIL import Image from dataloaders import helpers -import os def convert_mask_to_polygon(mask): mask = np.array(mask, dtype=np.uint8) From 2defc22f0476c9844b4904b2f0fea58cd292a129 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 9 Feb 2021 21:40:10 +0300 Subject: [PATCH 16/24] Update CHANGELOG, use NUCLIO_DASHBOARD_DEFAULT_FUNCTION_MOUNT_MODE as recommended by nuclio developers. --- CHANGELOG.md | 4 ++++ .../serverless/docker-compose.serverless.yml | 3 ++- .../installation_automatic_annotation.md | 22 +++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3da1ccdcc19e..31d1b373cd5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,11 +13,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - CVAT-3D: Load all frames corresponding to the job instance () - Intelligent scissors with OpenCV javascript () +- [Inside Outside Guidence](https://github.com/shiyinzhang/Inside-Outside-Guidance) serverless + function for interative segmentation ### Changed - Updated HTTPS install README section (cleanup and described more robust deploy) - Logstash is improved for using with configurable elasticsearch outputs () +- Bumped nuclio version to 1.5.16 +- All methods for interative segmentation accept negative points as well ### Deprecated diff --git a/components/serverless/docker-compose.serverless.yml b/components/serverless/docker-compose.serverless.yml index de94f6166b83..8938d5c53207 100644 --- a/components/serverless/docker-compose.serverless.yml +++ b/components/serverless/docker-compose.serverless.yml @@ -2,7 +2,7 @@ version: '3.3' services: serverless: container_name: nuclio - image: quay.io/nuclio/dashboard:1.5.8-amd64 + image: quay.io/nuclio/dashboard:1.5.16-amd64 restart: always networks: default: @@ -16,6 +16,7 @@ services: https_proxy: no_proxy: 172.28.0.1,${no_proxy} NUCLIO_CHECK_FUNCTION_CONTAINERS_HEALTHINESS: 'true' + NUCLIO_DASHBOARD_DEFAULT_FUNCTION_MOUNT_MODE: 'volume' ports: - '8070:8070' diff --git a/cvat/apps/documentation/installation_automatic_annotation.md b/cvat/apps/documentation/installation_automatic_annotation.md index e3343211ffd5..e68ce8b48128 100644 --- a/cvat/apps/documentation/installation_automatic_annotation.md +++ b/cvat/apps/documentation/installation_automatic_annotation.md @@ -1,13 +1,14 @@ - ### Semi-automatic and Automatic Annotation - > **⚠ WARNING: Do not use `docker-compose up`** -> If you did, make sure all containers are stopped by `docker-compose down`. +> If you did, make sure all containers are stopped by `docker-compose down`. + - To bring up cvat with auto annotation tool, from cvat root directory, you need to run: + ```bash docker-compose -f docker-compose.yml -f components/serverless/docker-compose.serverless.yml up -d ``` + If you did any changes to the docker-compose files, make sure to add `--build` at the end. To stop the containers, simply run: @@ -17,10 +18,11 @@ ``` - You have to install `nuctl` command line tool to build and deploy serverless - functions. Download [version 1.5.8](https://github.com/nuclio/nuclio/releases). + functions. Download [version 1.5.16](https://github.com/nuclio/nuclio/releases/tag/1.5.16). It is important that the version you download matches the version in [docker-compose.serverless.yml](/components/serverless/docker-compose.serverless.yml) After downloading the nuclio, give it a proper permission and do a softlink + ``` sudo chmod +x nuctl--linux-amd64 sudo ln -sf $(pwd)/nuctl--linux-amd64 /usr/local/bin/nuctl @@ -45,10 +47,13 @@ --volume `pwd`/serverless/openvino/common:/opt/nuclio/common \ --platform local ``` + **Note:** + - See [deploy_cpu.sh](/serverless/deploy_cpu.sh) for more examples. #### GPU Support + You will need to install Nvidia Container Toolkit and make sure your docker supports GPU. Follow [Nvidia docker instructions](https://www.tensorflow.org/install/docker#gpu_support). Also you will need to add `--resource-limit nvidia.com/gpu=1` to the nuclio deployment command. As an example, below will run on the GPU: @@ -63,9 +68,10 @@ ``` **Note:** - - Since the model is loaded during deployment, the number of GPU functions you can deploy will be limited to your GPU memory. - - See [deploy_gpu.sh](/serverless/deploy_gpu.sh) script for more examples. + - Since the model is loaded during deployment, the number of GPU functions you can deploy will be limited to your GPU memory. + + - See [deploy_gpu.sh](/serverless/deploy_gpu.sh) script for more examples. ####Debugging Nuclio Functions: @@ -76,6 +82,7 @@ ```bash docker logs ``` + e.g., ```bash @@ -83,9 +90,10 @@ ``` - If you would like to debug a code inside a container, you can use vscode to directly attach to a container [instructions](https://code.visualstudio.com/docs/remote/attach-container). To apply your changes, make sure to restart the container. + ```bash docker restart ``` > **⚠ WARNING:** - > Do not use nuclio dashboard to stop the container because with any modifications, it rebuilds the container and you will lose your changes. \ No newline at end of file + > Do not use nuclio dashboard to stop the container because with any modifications, it rebuilds the container and you will lose your changes. From d64c0efbbe7c775b6abf275f14a9d24ffbc00e85 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 9 Feb 2021 21:49:39 +0300 Subject: [PATCH 17/24] Removed volume mode from functions (it is handled by NUCLIO_DASHBOARD_DEFAULT_FUNCTION_MOUNT_MODE now) https://github.com/nuclio/nuclio/pull/2058 --- .../openvino/dextr/nuclio/function.yaml | 1 - .../nuclio/function.yaml | 1 - .../nuclio/function.yaml | 1 - .../text-detection-0004/nuclio/function.yaml | 1 - .../nuclio/function.yaml | 1 - .../nuclio/function.yaml | 1 - .../public/yolo-v3-tf/nuclio/function.yaml | 1 - .../foolwood/siammask/nuclio/function.yaml | 1 - .../saic-vul/fbrs/nuclio/function.yaml | 1 - .../shiyinzhang/iog/nuclio/function.yaml | 65 +++++++++---------- .../nuclio/function.yaml | 1 - .../matterport/mask_rcnn/nuclio/function.yaml | 1 - 12 files changed, 32 insertions(+), 44 deletions(-) diff --git a/serverless/openvino/dextr/nuclio/function.yaml b/serverless/openvino/dextr/nuclio/function.yaml index 6128c80885f1..63944e535e4e 100644 --- a/serverless/openvino/dextr/nuclio/function.yaml +++ b/serverless/openvino/dextr/nuclio/function.yaml @@ -48,7 +48,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml index ab4554f12f76..6a721983f5d1 100644 --- a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml @@ -43,7 +43,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml index 60bb3dffd592..407a8c971c84 100644 --- a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml @@ -70,7 +70,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml index 6acc0e97d8cd..be06326dc459 100644 --- a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml @@ -44,7 +44,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml index 842c16a1b890..fbc44c00c33f 100644 --- a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -125,7 +125,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml index a9b61d35e8da..b4a8622b66ed 100644 --- a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml @@ -134,7 +134,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml index 16d042fcb845..c2474728b10f 100644 --- a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml +++ b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml @@ -125,7 +125,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml index ae568d318d22..a19fdb52bb3e 100644 --- a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml +++ b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml @@ -51,7 +51,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml b/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml index 03e13fbdb9f8..4d36482a0f27 100644 --- a/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml +++ b/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml @@ -54,7 +54,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml index 4672627a3585..e16871a336eb 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -11,7 +11,7 @@ metadata: spec: description: Interactive Object Segmentation with Inside-Outside Guidance - runtime: "python:3.6" + runtime: 'python:3.6' handler: main:handler eventTimeout: 30s env: @@ -24,48 +24,47 @@ spec: directives: preCopy: - - kind: WORKDIR - value: /opt/nuclio - - kind: RUN - value: conda create -y -n iog python=3.6 - - kind: RUN - value: echo "source activate iog" > ~/.bashrc - - kind: ENV - value: PATH=/opt/conda/envs/env/bin:$PATH - - kind: RUN - value: conda install -y -c anaconda curl - - kind: RUN - value: conda install -y pytorch=0.4 torchvision=0.2 -c pytorch - - kind: RUN - value: conda install -y -c conda-forge pycocotools opencv scipy - - kind: RUN - value: git clone https://github.com/shiyinzhang/Inside-Outside-Guidance.git iog - - kind: WORKDIR - value: /opt/nuclio/iog - - kind: ENV - value: fileid=1Lm1hhMhhjjnNwO4Pf7SC6tXLayH2iH0l - - kind: ENV - value: filename=IOG_PASCAL_SBD.pth - - kind: RUN - value: curl -c ./cookie -s -L "https://drive.google.com/uc?export=download&id=${fileid}" - - kind: RUN - value: echo "/download/ {print \$NF}" > confirm_code.awk - - kind: RUN - value: curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk -f confirm_code.awk ./cookie`&id=${fileid}" -o ${filename} - - kind: WORKDIR - value: /opt/nuclio + - kind: WORKDIR + value: /opt/nuclio + - kind: RUN + value: conda create -y -n iog python=3.6 + - kind: RUN + value: echo "source activate iog" > ~/.bashrc + - kind: ENV + value: PATH=/opt/conda/envs/env/bin:$PATH + - kind: RUN + value: conda install -y -c anaconda curl + - kind: RUN + value: conda install -y pytorch=0.4 torchvision=0.2 -c pytorch + - kind: RUN + value: conda install -y -c conda-forge pycocotools opencv scipy + - kind: RUN + value: git clone https://github.com/shiyinzhang/Inside-Outside-Guidance.git iog + - kind: WORKDIR + value: /opt/nuclio/iog + - kind: ENV + value: fileid=1Lm1hhMhhjjnNwO4Pf7SC6tXLayH2iH0l + - kind: ENV + value: filename=IOG_PASCAL_SBD.pth + - kind: RUN + value: curl -c ./cookie -s -L "https://drive.google.com/uc?export=download&id=${fileid}" + - kind: RUN + value: echo "/download/ {print \$NF}" > confirm_code.awk + - kind: RUN + value: curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk -f confirm_code.awk ./cookie`&id=${fileid}" -o ${filename} + - kind: WORKDIR + value: /opt/nuclio triggers: myHttpTrigger: maxWorkers: 2 - kind: "http" + kind: 'http' workerAvailabilityTimeoutMilliseconds: 10000 attributes: maxRequestBodySize: 33554432 # 32MB platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml index 0d05d7145068..4e2cf02f6e2e 100644 --- a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml +++ b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -126,7 +126,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 diff --git a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml index 2b0d245ab424..ef0bf20cef4f 100644 --- a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml +++ b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml @@ -128,7 +128,6 @@ spec: platform: attributes: - processorMountMode: volume restartPolicy: name: always maximumRetryCount: 3 From 16fefe7573cfd8337416990a5c932402d57f6162 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 9 Feb 2021 22:12:03 +0300 Subject: [PATCH 18/24] Disable warning from markdown linter about max line length for a table. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 77b53e75a336..7137a54bc2ab 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,8 @@ For more information about supported formats look at the ## Deep learning serverless functions for automatic labeling + + | Name | Type | Framework | CPU | GPU | | ------------------------------------------------------------------------------------------------------- | ---------- | ---------- | --- | --- | | [Deep Extreme Cut](/serverless/openvino/dextr/nuclio) | interactor | OpenVINO | X | | @@ -80,6 +82,8 @@ For more information about supported formats look at the | [Faster RCNN](/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio) | detector | TensorFlow | X | X | | [Mask RCNN](/serverless/tensorflow/matterport/mask_rcnn/nuclio) | detector | TensorFlow | X | | + + ## Online demo: [cvat.org](https://cvat.org) This is an online demo with the latest version of the annotation tool. From 97e2984ee8de1e185f0f22e560ff8eb04fdb1c2e Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 9 Feb 2021 22:26:20 +0300 Subject: [PATCH 19/24] Revert wrong changes --- cvat-ui/src/cvat-canvas-wrapper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cvat-ui/src/cvat-canvas-wrapper.ts b/cvat-ui/src/cvat-canvas-wrapper.ts index 7138b5a87259..3b0c1e21174b 100644 --- a/cvat-ui/src/cvat-canvas-wrapper.ts +++ b/cvat-ui/src/cvat-canvas-wrapper.ts @@ -12,7 +12,7 @@ import { InteractionResult as _InteractionResult, } from 'cvat-canvas/src/typescript/canvas'; -function convertShapesForInteractor(shapes: InteractionResult[], button: number): number[][] { +export function convertShapesForInteractor(shapes: InteractionResult[], button: number): number[][] { const reducer = (acc: number[][], _: number, index: number, array: number[]): number[][] => { if (!(index % 2)) { // 0, 2, 4 @@ -32,5 +32,5 @@ export type InteractionData = _InteractionData; export type InteractionResult = _InteractionResult; export { - Canvas, CanvasMode, CanvasVersion, RectDrawingMethod, CuboidDrawingMethod, convertShapesForInteractor, + Canvas, CanvasMode, CanvasVersion, RectDrawingMethod, CuboidDrawingMethod, }; From 7f7d6f95e983b5537daf8eac9a9ecd92b5033d2f Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Tue, 9 Feb 2021 23:53:42 +0300 Subject: [PATCH 20/24] Reverted changes in requirements for cvat (numpy). --- cvat/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/requirements/base.txt b/cvat/requirements/base.txt index d4a1d3a211ff..fa5b41f3c6ad 100644 --- a/cvat/requirements/base.txt +++ b/cvat/requirements/base.txt @@ -7,7 +7,7 @@ django-compressor==2.4 django-rq==2.3.2 EasyProcess==0.3 Pillow==7.2.0 -numpy==1.19.2 +numpy==1.20.0 python-ldap==3.3.1 pytz==2020.1 pyunpack==0.2.1 From 049c6436b37ba8247c7c7e0d8daf0d09fcff6d6a Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Wed, 10 Feb 2021 11:39:26 +0300 Subject: [PATCH 21/24] Dashboard env variable doesn't work by a reason. Added back mountMode for every function. --- serverless/openvino/dextr/nuclio/function.yaml | 1 + .../person-reidentification-retail-300/nuclio/function.yaml | 1 + .../intel/semantic-segmentation-adas-0001/nuclio/function.yaml | 1 + .../openvino/omz/intel/text-detection-0004/nuclio/function.yaml | 1 + .../public/faster_rcnn_inception_v2_coco/nuclio/function.yaml | 1 + .../nuclio/function.yaml | 1 + serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml | 1 + serverless/pytorch/foolwood/siammask/nuclio/function.yaml | 1 + serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml | 1 + serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml | 1 + .../faster_rcnn_inception_v2_coco/nuclio/function.yaml | 1 + serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml | 1 + 12 files changed, 12 insertions(+) diff --git a/serverless/openvino/dextr/nuclio/function.yaml b/serverless/openvino/dextr/nuclio/function.yaml index 63944e535e4e..825599428f62 100644 --- a/serverless/openvino/dextr/nuclio/function.yaml +++ b/serverless/openvino/dextr/nuclio/function.yaml @@ -51,3 +51,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml index 6a721983f5d1..ffa81ae8111e 100644 --- a/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/person-reidentification-retail-300/nuclio/function.yaml @@ -46,3 +46,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml index 407a8c971c84..20e4941e26ec 100644 --- a/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/semantic-segmentation-adas-0001/nuclio/function.yaml @@ -73,3 +73,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml index be06326dc459..eff14c114144 100644 --- a/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml +++ b/serverless/openvino/omz/intel/text-detection-0004/nuclio/function.yaml @@ -47,3 +47,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml index fbc44c00c33f..556154e06888 100644 --- a/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -128,3 +128,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml index b4a8622b66ed..8e7854e9f972 100644 --- a/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml +++ b/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio/function.yaml @@ -137,3 +137,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml index c2474728b10f..5e3966f1421c 100644 --- a/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml +++ b/serverless/openvino/omz/public/yolo-v3-tf/nuclio/function.yaml @@ -128,3 +128,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml index a19fdb52bb3e..5b078127c2b3 100644 --- a/serverless/pytorch/foolwood/siammask/nuclio/function.yaml +++ b/serverless/pytorch/foolwood/siammask/nuclio/function.yaml @@ -54,3 +54,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml b/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml index 4d36482a0f27..50a25753d7c2 100644 --- a/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml +++ b/serverless/pytorch/saic-vul/fbrs/nuclio/function.yaml @@ -57,3 +57,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml index e16871a336eb..f6c28167ea0a 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -68,3 +68,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml index 4e2cf02f6e2e..4e6da8ebe596 100644 --- a/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml +++ b/serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio/function.yaml @@ -129,3 +129,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume diff --git a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml index ef0bf20cef4f..0026ac507281 100644 --- a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml +++ b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml @@ -131,3 +131,4 @@ spec: restartPolicy: name: always maximumRetryCount: 3 + mountMode: volume From 34177f3d21db966605d990b844adce46e3c6c055 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Wed, 10 Feb 2021 12:32:24 +0300 Subject: [PATCH 22/24] Fix IOG function with conda environment --- serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml index f6c28167ea0a..f84f543ced1a 100644 --- a/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml +++ b/serverless/pytorch/shiyinzhang/iog/nuclio/function.yaml @@ -28,10 +28,8 @@ spec: value: /opt/nuclio - kind: RUN value: conda create -y -n iog python=3.6 - - kind: RUN - value: echo "source activate iog" > ~/.bashrc - - kind: ENV - value: PATH=/opt/conda/envs/env/bin:$PATH + - kind: SHELL + value: '["conda", "run", "-n", "iog", "/bin/bash", "-c"]' - kind: RUN value: conda install -y -c anaconda curl - kind: RUN @@ -54,6 +52,8 @@ spec: value: curl -Lb ./cookie "https://drive.google.com/uc?export=download&confirm=`awk -f confirm_code.awk ./cookie`&id=${fileid}" -o ${filename} - kind: WORKDIR value: /opt/nuclio + - kind: ENTRYPOINT + value: '["conda", "run", "-n", "iog"]' triggers: myHttpTrigger: From ece913bf02c59296c3367e0ce46f38791b4099be Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Wed, 10 Feb 2021 14:41:40 +0300 Subject: [PATCH 23/24] Fix tensorflow matterport/mask_rcnn --- .../tensorflow/matterport/mask_rcnn/nuclio/function.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml index 0026ac507281..1d3ee39b4e51 100644 --- a/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml +++ b/serverless/tensorflow/matterport/mask_rcnn/nuclio/function.yaml @@ -108,15 +108,16 @@ spec: - kind: WORKDIR value: /opt/nuclio - kind: RUN - value: apt update && apt install --no-install-recommends -y git curl libsm6 libxext6 libxrender-dev + value: apt update && apt install --no-install-recommends -y git curl libsm6 libxext6 libgl1-mesa-glx - kind: RUN value: git clone https://github.com/matterport/Mask_RCNN.git - kind: RUN value: curl -L https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5 -o Mask_RCNN/mask_rcnn_coco.h5 - kind: RUN - value: pip3 install -r Mask_RCNN/requirements.txt + value: pip3 install scipy cython matplotlib scikit-image opencv-python-headless h5py \ + imgaug IPython[all] tensorflow==1.13.1 keras==2.1.0 pillow pyyaml - kind: RUN - value: pip3 install pycocotools tensorflow==1.13.1 keras==2.1.0 pillow pyyaml + value: pip3 install pycocotools triggers: myHttpTrigger: From e76be3460203717121f4b0171aa66a87ae15b7d3 Mon Sep 17 00:00:00 2001 From: Nikita Manovich Date: Wed, 10 Feb 2021 15:29:55 +0300 Subject: [PATCH 24/24] Bump version of cvat-ui. --- cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index b0d2a4fee1a8..ff9de4e803c1 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.14.1", + "version": "1.14.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 02372b86c213..e78795fb9c2f 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.14.1", + "version": "1.14.2", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": {