cvat-ai / cvat

Annotate better with CVAT, the industry-leading data engine for machine learning. Used and trusted by teams at any scale, for data of any scale.
https://cvat.ai
MIT License
12.48k stars 2.99k forks source link

find countour and draw polygon in the AI tool for semantic segmentation #4660

Closed waqarsqureshi closed 2 years ago

waqarsqureshi commented 2 years ago

In the picture below we can see the polygon drawn automatically by the function approximate_polygon, which has two input find contours from find_countours and the tolerance. The tolerance controls the number of points in the polygons while the contour is the point for the polygon to draw. Screenshot from 2022-05-27 09-16-10 As we can see clearly the road is not identified properly. It should cover all the way down touching the ends of the image. This happens with all of the images and it surely is a limitation in the approximate polygon method or find_contour method. When the same mask is generated using the OpenVino in an offline model the mask covers the whole road. below is the expected output from the software.

Screenshot from 2022-05-27 09-23-44

Steps to Reproduce (for bugs)

  1. Follow the guidelines to install cvat and serverless AI components
  2. run the semantic segmentation on any of the images you have for roads similar to ADAS
waqarsqureshi commented 2 years ago

I found a solution. just use the opencv findContour function. the code is below `# Copyright (C) 2020 Intel Corporation #

SPDX-License-Identifier: MIT

import os import cv2 import numpy as np from skimage.measure import approximate_polygon, find_contours from model_loader import ModelLoader

class ModelHandler: def init(self, labels): base_dir = os.path.abspath(os.environ.get("MODEL_PATH", "/opt/nuclio/open_model_zoo/intel/semantic-segmentation-adas-0001/FP32")) model_xml = os.path.join(base_dir, "semantic-segmentation-adas-0001.xml") model_bin = os.path.join(base_dir, "semantic-segmentation-adas-0001.bin") self.model = ModelLoader(model_xml, model_bin) self.labels = labels

def infer(self, image, threshold):
    output_layer = self.model.infer(image)

    results = []
    mask = output_layer[0, 0, :, :]
    width, height = mask.shape

    for i in range(len(self.labels)):
        mask_by_label = np.zeros((width, height), dtype=np.uint8)
        mask_by_label = ((mask == float(i)) * 255).astype(np.uint8)
        mask_by_label = cv2.resize(mask_by_label,
            dsize=(image.width, image.height),
            interpolation=cv2.INTER_NEAREST)

        #contours = find_contours(mask_by_label, 0.5)
        contours, hierarchy  = cv2.findContours(mask_by_label, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        for contour in contours:
            contour = np.flip(contour, axis=1)
            #contour = approximate_polygon(contour, tolerance=2.5)
            if len(contour) < 3:
                continue

            results.append({
                "confidence": None,
                "label": self.labels.get(i, "unknown"),
                "points": contour.ravel().tolist(),
                "type": "polygon",
            })

    return results`