Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed Mask class to store RLE encoded masks to save RAM. #599

Merged
merged 12 commits into from
Sep 27, 2022

Conversation

ChristofferEdlund
Copy link
Contributor

@ChristofferEdlund ChristofferEdlund commented Sep 26, 2022

Changed Mask class to store RLE encoded masks to save RAM usage on large images. (Work in progress)

When doing inference on large images (5300, 3600) pixel with around 100 instances, the sahi library uses around 14 GB of RAM.
I introduced internal conversion to RLE encoded masks in the Mask class to save RAM memory and got it down to around 2GB RAM usage for our use-case (see plots).

RAM_comprison

Since pycocotools are a bit tricky to install on windows, the code are designed to utilize RLE encoding if pycocotools are available.

The inference time does not seem to increase by these changes, but only ran a single test so take the results with a grain of salt.

inference_time_comprison

@ChristofferEdlund ChristofferEdlund changed the title Changed Mask class to store RLE encoded masks to save RAM. [WIP] Changed Mask class to store RLE encoded masks to save RAM. Sep 26, 2022
@fcakyon
Copy link
Collaborator

fcakyon commented Sep 26, 2022

Wow @ChristofferEdlund this is an amazing contribution!

@fcakyon
Copy link
Collaborator

fcakyon commented Sep 26, 2022

@ChristofferEdlund you should follow these steps for proper style formatting:

pip install sahi[dev]
python -m scripts.run_code_style format

sahi/annotation.py Outdated Show resolved Hide resolved
setup.py Outdated Show resolved Hide resolved
@fcakyon
Copy link
Collaborator

fcakyon commented Sep 26, 2022

You should not reformat with the latest version of black, you should you the versions installed with pip install sahi[dev].

black version is important:

sahi/setup.py

Line 40 in 5f095d5

"dev": ["black==21.7b0", "flake8==3.9.2", "isort==5.9.2", "jupyterlab==3.0.14"],

@fcakyon
Copy link
Collaborator

fcakyon commented Sep 27, 2022

@ChristofferEdlund ram usage and inference benchmark plots seem really nice. How did you generate them?

Would you like to open a separate PR adding scripts generating such benchmark plots?

use_rle = True
except ImportError:
use_rle = False

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since pycocotools is moved to requirments.txt as a direct dependency, I think we change this import procedure, I think the following would be sufficient

from pycocotools import mask as mask_utils

but @ChristofferEdlund got a point that installing pycoctools on Windows is not straightforward, should we make this a soft dependency rather ? @fcakyon

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @fcakyon pointed out, it seems like one can actually install pycocotools on windows right now. But it is still this hurdle to get over:

https://stackoverflow.com/questions/64261546/how-to-solve-error-microsoft-visual-c-14-0-or-greater-is-required-when-inst

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then it might be better to make pycocotools optional, c ompiler might cause issues to some users.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will handle the required updates 👍

Copy link
Contributor Author

@ChristofferEdlund ChristofferEdlund Sep 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds great!

@fcakyon, regarding an other PR for the plots, maybe.. Those plots where generated by monitoring the RAM usage of a docker container running on internal models and data. Let me think if there is a good way to do something similar with default SAHI and some good open source images.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can create a dockerfile for sahi (can also push the image to dockerhub)?

Copy link
Collaborator

@fcakyon fcakyon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

setup.py Outdated Show resolved Hide resolved
@fcakyon fcakyon merged commit 261d171 into obss:main Sep 27, 2022
@lioneldaniel
Copy link

lioneldaniel commented Jan 3, 2023

@fcakyon similarly, would you accept a soft dependency to opencv in addition to pycocotools in coco.py to support json file with coco format containing RLE annotations?

Here would be my patch that automatically converts RLE segmentations to Polygon segmentations:

  • add these lines into the import section of coco.py :
try:
    from pycocotools import mask as mask_utils
    import cv2

    use_rle = True
except ImportError:
    use_rle = False
  • replace the first lines of method from_coco_annotation_dict in coco.py by the following ones:
    @classmethod
    def from_coco_annotation_dict(cls, annotation_dict: Dict, category_name: Optional[str] = None):
        """
        Creates CocoAnnotation object from category name and COCO formatted
        annotation dict (with fields "bbox", "segmentation", "category_id").

        Args:
            category_name: str
                Category name of the annotation
            annotation_dict: dict
                COCO formatted annotation dict (with fields "bbox", "segmentation", "category_id")
        """

        has_rle_segmentation = annotation_dict.__contains__("segmentation") and not isinstance(annotation_dict["segmentation"], list)

        if use_rle and has_rle_segmentation:
            # convert RLE to polygons: depend on opencv and pycocotools
            binary_mask = mask_utils.decode(annotation_dict["segmentation"])
            contours, _ = cv2.findContours(binary_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
            poly_segmentation = []
            for contour in contours:
                if contour.size >= 2*3:  # Valid polygon has at least 3 points
                    poly_segmentation.append(contour.flatten().tolist())
            annotation_dict["segmentation"] = poly_segmentation
            has_rle_segmentation = False
        else:
            logger.warning(
                f"Segmentation annotation for id {annotation_dict['id']} is skipped since RLE segmentation format is not supported without pycocotools and opencv"
            )

darwinharianto added a commit to darwinharianto/sahi that referenced this pull request Jul 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants