Repository: open-mmlab/mmdetection

Issue:
[Errno 36] File name too long
When I run the following code
```
python demo/webcam_demo.py configs/cascade_rcnn/cascade_rcnn_r50_fpn_20e_coco.py models/cascade_rcnn_r50_fpn_20e_coco_bbox_mAP-0.41_20200504_175131-e9872a90.pth

```

There is an error:

OSError: [Errno 36] File name too long: '[[[120 132 105]\n  [120 132 105]\n  [119 131 104]\n  ...\n  [ 19  19  17]\n  [ 19  19  17]\n  [ 19  19  17]]\n\n [[120 132 105]\n  [120 132 105]\n  [119 131 104]\n  ...\n  [ 19  19  17]\n  [ 19  20  17]\n  [ 19  20  17]]\n\n [[119 132 105]\n  [119 132 105]\n  [118 131 104]\n  ...\n  [ 20  21  17]\n  [ 20  21  18]\n  [ 20  21  18]]\n\n ...\n\n [[179 180 177]\n  [179 180 177]\n  [179 180 177]\n  ...\n  [182 186 183]\n  [182 187 183]\n  [182 187 183]]\n\n [[179 180 178]\n  [179 180 178]\n  [179 180 178]\n  ...\n  [183 186 183]\n  [183 187 184]\n  [183 187 184]]\n\n [[179 180 178]\n  [179 180 178]\n  [179 180 178]\n  ...\n  [183 186 184]\n  [184 187 185]\n  [184 187 185]]]'


Discussion:
Hi, it is a bug and will be fixed soon.
Duplicate of #3623 

Resolving patch:
diff --git a/mmdet/apis/inference.py b/mmdet/apis/inference.py
--- a/mmdet/apis/inference.py
+++ b/mmdet/apis/inference.py
@@ -2,6 +2,7 @@
 
 import matplotlib.pyplot as plt
 import mmcv
+import numpy as np
 import torch
 from mmcv.ops import RoIAlign, RoIPool
 from mmcv.parallel import collate, scatter
@@ -88,10 +89,18 @@ def inference_detector(model, img):
     """
     cfg = model.cfg
     device = next(model.parameters()).device  # model device
+    # prepare data
+    if isinstance(img, np.ndarray):
+        # directly add img
+        data = dict(img=img)
+        cfg = cfg.copy()
+        # set loading pipeline type
+        cfg.data.test.pipeline[0].type = 'LoadImageFromWebcam'
+    else:
+        # add information into dict
+        data = dict(img_info=dict(filename=img), img_prefix=None)
     # build the data pipeline
     test_pipeline = Compose(cfg.data.test.pipeline)
-    # prepare data
-    data = dict(img_info=dict(filename=img), img_prefix=None)
     data = test_pipeline(data)
     data = collate([data], samples_per_gpu=1)
     if next(model.parameters()).is_cuda:
diff --git a/mmdet/datasets/pipelines/__init__.py b/mmdet/datasets/pipelines/__init__.py
--- a/mmdet/datasets/pipelines/__init__.py
+++ b/mmdet/datasets/pipelines/__init__.py
@@ -3,7 +3,7 @@
 from .formating import (Collect, ImageToTensor, ToDataContainer, ToTensor,
                         Transpose, to_tensor)
 from .instaboost import InstaBoost
-from .loading import (LoadAnnotations, LoadImageFromFile,
+from .loading import (LoadAnnotations, LoadImageFromFile, LoadImageFromWebcam,
                       LoadMultiChannelImageFromFiles, LoadProposals)
 from .test_time_aug import MultiScaleFlipAug
 from .transforms import (Albu, CutOut, Expand, MinIoURandomCrop, Normalize,
@@ -13,8 +13,9 @@
 __all__ = [
     'Compose', 'to_tensor', 'ToTensor', 'ImageToTensor', 'ToDataContainer',
     'Transpose', 'Collect', 'LoadAnnotations', 'LoadImageFromFile',
-    'LoadMultiChannelImageFromFiles', 'LoadProposals', 'MultiScaleFlipAug',
-    'Resize', 'RandomFlip', 'Pad', 'RandomCrop', 'Normalize', 'SegRescale',
-    'MinIoURandomCrop', 'Expand', 'PhotoMetricDistortion', 'Albu',
-    'InstaBoost', 'RandomCenterCropPad', 'AutoAugment', 'CutOut'
+    'LoadImageFromWebcam', 'LoadMultiChannelImageFromFiles', 'LoadProposals',
+    'MultiScaleFlipAug', 'Resize', 'RandomFlip', 'Pad', 'RandomCrop',
+    'Normalize', 'SegRescale', 'MinIoURandomCrop', 'Expand',
+    'PhotoMetricDistortion', 'Albu', 'InstaBoost', 'RandomCenterCropPad',
+    'AutoAugment', 'CutOut'
 ]
diff --git a/mmdet/datasets/pipelines/loading.py b/mmdet/datasets/pipelines/loading.py
--- a/mmdet/datasets/pipelines/loading.py
+++ b/mmdet/datasets/pipelines/loading.py
@@ -77,6 +77,38 @@ def __repr__(self):
         return repr_str
 
 
+@PIPELINES.register_module()
+class LoadImageFromWebcam(LoadImageFromFile):
+    """Load an image from webcam.
+
+    Similar with :obj:`LoadImageFromFile`, but the image read from webcam is in
+    ``results['img']``.
+    """
+
+    def __call__(self, results):
+        """Call functions to add image meta information.
+
+        Args:
+            results (dict): Result dict with Webcam read image in
+                ``results['img']``.
+
+        Returns:
+            dict: The dict contains loaded image and meta information.
+        """
+
+        img = results['img']
+        if self.to_float32:
+            img = img.astype(np.float32)
+
+        results['filename'] = None
+        results['ori_filename'] = None
+        results['img'] = img
+        results['img_shape'] = img.shape
+        results['ori_shape'] = img.shape
+        results['img_fields'] = ['img']
+        return results
+
+
 @PIPELINES.register_module()
 class LoadMultiChannelImageFromFiles(object):
     """Load multi-channel images from a list of separate channel files.


Test patch:
diff --git a/tests/test_data/test_loading.py b/tests/test_data/test_loading.py
--- a/tests/test_data/test_loading.py
+++ b/tests/test_data/test_loading.py
@@ -1,9 +1,10 @@
 import copy
 import os.path as osp
 
+import mmcv
 import numpy as np
 
-from mmdet.datasets.pipelines import (LoadImageFromFile,
+from mmdet.datasets.pipelines import (LoadImageFromFile, LoadImageFromWebcam,
                                       LoadMultiChannelImageFromFiles)
 
 
@@ -75,3 +76,15 @@ def test_load_multi_channel_img(self):
         assert repr(transform) == transform.__class__.__name__ + \
             "(to_float32=False, color_type='unchanged', " + \
             "file_client_args={'backend': 'disk'})"
+
+    def test_load_webcam_img(self):
+        img = mmcv.imread(osp.join(self.data_prefix, 'color.jpg'))
+        results = dict(img=img)
+        transform = LoadImageFromWebcam()
+        results = transform(copy.deepcopy(results))
+        assert results['filename'] is None
+        assert results['ori_filename'] is None
+        assert results['img'].shape == (288, 512, 3)
+        assert results['img'].dtype == np.uint8
+        assert results['img_shape'] == (288, 512, 3)
+        assert results['ori_shape'] == (288, 512, 3)