Repository: voxel51/fiftyone

Issue:
COCOObject from_detection fails when width or height is zero.
from this helloworld code

```
import fiftyone as fo
import fiftyone.zoo as foz
import eta


import fiftyone.utils.openimages as fouo


not_complete = True
while not_complete:
    try:
        dataset = foz.load_zoo_dataset(
            "coco-2017",
            split="train",
            label_types=["segmentations"],
            classes=["person"],
            max_samples=100000,
            dataset_name="cocopeople",
        )
        not_complete = False
    except eta.core.web.WebSessionError:
        pass

dataset.peristent = True

export_dir = "/media/sam/trainer/datasets/cocoperson"
label_field = "ground_truth"  # for example

# session = fo.launch_app()
# session.wait()
# Export the dataset
dataset.export(
    export_dir=export_dir,
    dataset_type=fo.types.COCODetectionDataset,
    label_field=label_field,
)

```

I get this traceback.

seems that a 0 x 0 sized image is in play here.

seems like `from_detection` classmethod of `COCOObject` 

Is not handling zero sized detection cleanly and is passing them down to a function that fails.

```
Traceback (most recent call last):
  File "/media/sam/trainer/gitlab/kognat/rotobot-trainer-docker/openimagefo.py", line 32, in <module>
    dataset.export(
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/fiftyone/core/collections.py", line 5502, in export
    foud.export_samples(
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/fiftyone/utils/data/exporters.py", line 290, in export_samples
    write_dataset(
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/fiftyone/utils/data/exporters.py", line 343, in write_dataset
    _write_image_dataset(
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/fiftyone/utils/data/exporters.py", line 666, in _write_image_dataset
    dataset_exporter.export_sample(
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/fiftyone/utils/coco.py", line 723, in export_sample
    obj = COCOObject.from_detection(
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/fiftyone/utils/coco.py", line 1039, in from_detection
    segmentation = _make_coco_segmentation(
  File "", line 1999, in _make_coco_segmentation
    mask = etai.render_instance_image(dobj.mask, dobj.bounding_box, frame_size)
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/eta/core/image.py", line 982, in render_instance_image
    mask, offset = render_instance_mask(mask, bounding_box, frame_size=(w, h))
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/eta/core/image.py", line 955, in render_instance_mask
    mask = resize(mask, width=width, height=height)
  File "/home/sam/miniconda3/envs/bigdata/lib/python3.9/site-packages/eta/core/image.py", line 702, in resize
    return cv2.resize(img, (width, height), *args, **kwargs)
cv2.error: OpenCV(4.4.0) /tmp/pip-req-build-svum8tk7/opencv/modules/imgproc/src/resize.cpp:3929: error: (-215:Assertion failed) !ssize.empty() in function 'resize'
```


Discussion:
Hi @kognat-docs 👋 

Yeah looks like some error handling for things like trivial/missing segmentation masks might be needed in `fiftyone.utils.coco`.

fwiw- I tried on some samples from the `validation` split and didn't encounter any bad data

```py
import fiftyone as fo
import fiftyone.zoo as foz

# Load some person segmentations from COCO-2017 dataset
dataset = foz.load_zoo_dataset(
    "coco-2017",
    split="validation",
    label_types=["segmentations"],
    classes=["person"],
    max_samples=10,
)

# Export in COCO format
dataset.export(
    export_dir="/tmp/coco",
    dataset_type=fo.types.COCODetectionDataset,
)
```
So the error frequency is low?

this will fix it

```
def _make_coco_segmentation(detection, frame_size, iscrowd, tolerance):
    if detection.mask is None:
        return None
    if 0 in frame_size:
        return None

    dobj = detection.to_detected_object()
    if 0 in dobj.mask.shape:
       return None
    if dobj.bounding_box.width() < 2 :
       return None
    if dobj.bounding_box.height() < 2:
       return None
    mask = etai.render_instance_image(dobj.mask, dobj.bounding_box, frame_size)

    if iscrowd:
        return _mask_to_rle(mask)

    return _mask_to_polygons(mask, tolerance)
```

Resolving patch:
diff --git a/fiftyone/utils/coco.py b/fiftyone/utils/coco.py
--- a/fiftyone/utils/coco.py
+++ b/fiftyone/utils/coco.py
@@ -2048,7 +2048,15 @@ def _make_coco_segmentation(detection, frame_size, iscrowd, tolerance):
         return None
 
     dobj = detection.to_detected_object()
-    mask = etai.render_instance_image(dobj.mask, dobj.bounding_box, frame_size)
+
+    try:
+        mask = etai.render_instance_image(
+            dobj.mask, dobj.bounding_box, frame_size
+        )
+    except:
+        # Either mask or bounding box is too small to render
+        width, height = frame_size
+        mask = np.zeros((height, width), dtype=bool)
 
     if iscrowd:
         return _mask_to_rle(mask)


Test patch: