Repository: open-mmlab/mmocr

Issue:
Webcam demo script is not working properly
**Checklist**

1. I have searched related issues but cannot get the expected help: Yes
2. The bug has not been fixed in the latest version: Yes

**Describe the bug**

The current model_inference function expects to receive a model and a path to an image as inputs but the webcam demo scripts tries to call it with a model and a numpy array (the return value from cv2.VideoCapture.read()). 

This raises an assertion error due to type mismatch (np.ndarray vs str)

**Reproduction**

1. What command or script did you run?

```none
python demo/webcam_demo.py
```

2. Did you make any modifications on the code or config? Did you understand what you have modified?

No.

3. What dataset did you use?

**Environment**

1. Please run `python mmocr/utils/collect_env.py` to collect necessary environment information and paste it here.

sys.platform: linux
Python: 3.7.10 | packaged by conda-forge | (default, Feb 19 2021, 16:07:37) [GCC 9.3.0]
CUDA available: True
GPU 0: GeForce GTX 1050 Ti
CUDA_HOME: /usr/local/cuda
NVCC: Build cuda_11.1.TC455_06.29190527_0
GCC: gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
PyTorch: 1.5.0
PyTorch compiling details: PyTorch built with:
  - GCC 7.3
  - C++ Version: 201402
  - Intel(R) Math Kernel Library Version 2020.0.4 Product Build 20200917 for Intel(R) 64 architecture applications
  - Intel(R) MKL-DNN v0.21.1 (Git Hash 7d2fd500bc78936d1d648ca713b901012f470dbc)
  - OpenMP 201511 (a.k.a. OpenMP 4.5)
  - NNPACK is enabled
  - CPU capability usage: AVX2
  - CUDA Runtime 10.1
  - NVCC architecture flags: -gencode;arch=compute_37,code=sm_37;-gencode;arch=compute_50,code=sm_50;-gencode;arch=compute_60,code=sm_60;-gencode;arch=compute_61,code=sm_61;-gencode;arch=compute_70,code=sm_70;-gencode;arch=compute_75,code=sm_75;-gencode;arch=compute_37,code=compute_37
  - CuDNN 7.6.3
  - Magma 2.5.2
  - Build settings: BLAS=MKL, BUILD_TYPE=Release, CXX_FLAGS= -Wno-deprecated -fvisibility-inlines-hidden -fopenmp -DNDEBUG -DUSE_FBGEMM -DUSE_QNNPACK -DUSE_PYTORCH_QNNPACK -DUSE_XNNPACK -DUSE_INTERNAL_THREADPOOL_IMPL -O2 -fPIC -Wno-narrowing -Wall -Wextra -Werror=return-type -Wno-missing-field-initializers -Wno-type-limits -Wno-array-bounds -Wno-unknown-pragmas -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-result -Wno-strict-overflow -Wno-strict-aliasing -Wno-error=deprecated-declarations -Wno-stringop-overflow -Wno-error=pedantic -Wno-error=redundant-decls -Wno-error=old-style-cast -fdiagnostics-color=always -faligned-new -Wno-unused-but-set-variable -Wno-maybe-uninitialized -fno-math-errno -fno-trapping-math -Werror=format -Wno-stringop-overflow, PERF_WITH_AVX=1, PERF_WITH_AVX2=1, PERF_WITH_AVX512=1, USE_CUDA=ON, USE_EXCEPTION_PTR=1, USE_GFLAGS=OFF, USE_GLOG=OFF, USE_MKL=ON, USE_MKLDNN=ON, USE_MPI=OFF, USE_NCCL=ON, USE_NNPACK=ON, USE_OPENMP=ON, USE_STATIC_DISPATCH=OFF, 

TorchVision: 0.6.0a0+82fd1c8
OpenCV: 4.5.1
MMCV: 1.2.7
MMCV Compiler: GCC 9.3
MMCV CUDA Compiler: not available
MMOCR: 0.1.0+344cc9a

2. You may add addition that may be helpful for locating the problem, such as
    - How you installed PyTorch: conda

**Error traceback**

```none
Use load_from_local loader
Press "Esc", "q" or "Q" to exit.
Traceback (most recent call last):
  File "demo/webcam_demo.py", line 52, in <module>
    main()
  File "demo/webcam_demo.py", line 41, in main
    result = model_inference(model, img)
  File "/home/sbugallo/Projects/mmocr/mmocr/apis/inference.py", line 18, in model_inference
    assert isinstance(img, str)
AssertionError
```

**Bug fix**

The inference method should accept the following types as input image(s) (str/ndarray or list[str/ndarray] or tuple[str/ndarray]) like in MMDetection


Discussion:

Resolving patch:
diff --git a/mmocr/apis/inference.py b/mmocr/apis/inference.py
--- a/mmocr/apis/inference.py
+++ b/mmocr/apis/inference.py
@@ -1,7 +1,9 @@
+import numpy as np
 import torch
 from mmcv.ops import RoIPool
 from mmcv.parallel import collate, scatter
 
+from mmdet.datasets import replace_ImageToTensor
 from mmdet.datasets.pipelines import Compose
 
 
@@ -10,18 +12,33 @@ def model_inference(model, img):
 
     Args:
         model (nn.Module): The loaded detector.
-        imgs (str): Image files.
+        imgs (str/ndarray): Image files.
 
     Returns:
         result (dict): Detection results.
     """
-    assert isinstance(img, str)
+
+    assert isinstance(img, (str, np.ndarray))
 
     cfg = model.cfg
     device = next(model.parameters()).device  # model device
-    data = dict(img_info=dict(filename=img), img_prefix=None)
-    # build the data pipeline
+
+    if isinstance(img, np.ndarray):
+        cfg = cfg.copy()
+        # set loading pipeline type
+        cfg.data.test.pipeline[0].type = 'LoadImageFromWebcam'
+
+    cfg.data.test.pipeline = replace_ImageToTensor(cfg.data.test.pipeline)
     test_pipeline = Compose(cfg.data.test.pipeline)
+
+    if isinstance(img, np.ndarray):
+        # directly add img
+        data = dict(img=img)
+    else:
+        # add information into dict
+        data = dict(img_info=dict(filename=img), img_prefix=None)
+
+    # build the data pipeline
     data = test_pipeline(data)
     data = collate([data], samples_per_gpu=1)
 


Test patch:
diff --git a/tests/test_apis/test_model_inference.py b/tests/test_apis/test_model_inference.py
--- a/tests/test_apis/test_model_inference.py
+++ b/tests/test_apis/test_model_inference.py
@@ -3,14 +3,24 @@
 import urllib
 
 import pytest
+from mmcv.image import imread
 
 from mmdet.apis import init_detector
 from mmocr.apis.inference import model_inference
 
 
-def test_model_inference():
+@pytest.fixture
+def project_dir():
+    return os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
 
-    project_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+
+@pytest.fixture
+def sample_img_path(project_dir):
+    return os.path.join(project_dir, '../demo/demo_text_recog.jpg')
+
+
+@pytest.fixture
+def sarnet_model(project_dir):
     print(project_dir)
     config_file = os.path.join(
         project_dir,
@@ -38,9 +48,17 @@ def test_model_inference():
         model.cfg.data.test.pipeline = model.cfg.data.test['datasets'][
             0].pipeline
 
-    img = os.path.join(project_dir, '../demo/demo_text_recog.jpg')
+    return model
+
+
+def test_model_inference_image_path(sample_img_path, sarnet_model):
 
     with pytest.raises(AssertionError):
-        model_inference(model, 1)
+        model_inference(sarnet_model, 1)
+
+    model_inference(sarnet_model, sample_img_path)
+
 
-    model_inference(model, img)
+def test_model_inference_numpy_ndarray(sample_img_path, sarnet_model):
+    img = imread(sample_img_path)
+    model_inference(sarnet_model, img)