# Copyright (c) OpenMMLab. All rights reserved. import os.path as osp import random import tempfile from unittest import TestCase, mock import mmcv import mmengine import numpy as np import torch from mmocr.apis.inferencers import MMOCRInferencer class TestMMOCRInferencer(TestCase): def setUp(self): seed = 1 random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) def assert_predictions_equal(self, pred1, pred2): if 'det_polygons' in pred1: self.assertTrue( np.allclose(pred1['det_polygons'], pred2['det_polygons'], 0.1)) if 'det_scores' in pred1: self.assertTrue( np.allclose(pred1['det_scores'], pred2['det_scores'], 0.1)) if 'rec_texts' in pred1: self.assertEqual(pred1['rec_texts'], pred2['rec_texts']) if 'rec_scores' in pred1: self.assertTrue( np.allclose(pred1['rec_scores'], pred2['rec_scores'], 0.1)) if 'kie_labels' in pred1: self.assertEqual(pred1['kie_labels'], pred2['kie_labels']) if 'kie_scores' in pred1: self.assertTrue( np.allclose(pred1['kie_scores'], pred2['kie_scores'], 0.1)) if 'kie_edge_scores' in pred1: self.assertTrue( np.allclose(pred1['kie_edge_scores'], pred2['kie_edge_scores'], 0.1)) if 'kie_edge_labels' in pred1: self.assertEqual(pred1['kie_edge_labels'], pred2['kie_edge_labels']) @mock.patch('mmengine.infer.infer._load_checkpoint') def test_init(self, mock_load): mock_load.side_effect = lambda *x, **y: None MMOCRInferencer(det='dbnet_resnet18_fpnc_1200e_icdar2015') MMOCRInferencer( det='configs/textdet/dbnet/dbnet_resnet18_fpnc_1200e_icdar2015.py', det_weights='https://download.openmmlab.com/mmocr/textdet/dbnet/' 'dbnet_resnet18_fpnc_1200e_icdar2015/' 'dbnet_resnet18_fpnc_1200e_icdar2015_20220825_221614-7c0e94f2.pth') MMOCRInferencer(rec='crnn_mini-vgg_5e_mj') with self.assertRaises(ValueError): MMOCRInferencer(det='dummy') @mock.patch('mmengine.infer.infer._load_checkpoint') def test_det(self, mock_load): mock_load.side_effect = lambda *x, **y: None inferencer = MMOCRInferencer(det='dbnet_resnet18_fpnc_1200e_icdar2015') img_path = 'tests/data/det_toy_dataset/imgs/test/img_1.jpg' res_img_path = inferencer(img_path, return_vis=True) img_paths = [ 'tests/data/det_toy_dataset/imgs/test/img_1.jpg', 'tests/data/det_toy_dataset/imgs/test/img_2.jpg' ] res_img_paths = inferencer(img_paths, return_vis=True) self.assert_predictions_equal(res_img_path['predictions'][0], res_img_paths['predictions'][0]) self.assertTrue( np.allclose(res_img_path['visualization'][0], res_img_paths['visualization'][0])) img_ndarray = mmcv.imread(img_path) res_img_ndarray = inferencer(img_ndarray, return_vis=True) img_ndarrays = [mmcv.imread(p) for p in img_paths] res_img_ndarrays = inferencer(img_ndarrays, return_vis=True) self.assert_predictions_equal(res_img_ndarray['predictions'][0], res_img_ndarrays['predictions'][0]) self.assertTrue( np.allclose(res_img_ndarray['visualization'][0], res_img_ndarrays['visualization'][0])) # cross checking: ndarray <-> path self.assert_predictions_equal(res_img_ndarray['predictions'][0], res_img_path['predictions'][0]) self.assertTrue( np.allclose(res_img_ndarray['visualization'][0], res_img_path['visualization'][0])) # test save_vis and save_pred with tempfile.TemporaryDirectory() as tmp_dir: res = inferencer( img_paths, out_dir=tmp_dir, save_vis=True, save_pred=True) for img_dir in ['img_1.jpg', 'img_2.jpg']: self.assertTrue(osp.exists(osp.join(tmp_dir, 'vis', img_dir))) for i, pred_dir in enumerate(['img_1.json', 'img_2.json']): dumped_res = mmengine.load( osp.join(tmp_dir, 'preds', pred_dir)) self.assert_predictions_equal(res['predictions'][i], dumped_res) @mock.patch('mmengine.infer.infer._load_checkpoint') def test_rec(self, mock_load): mock_load.side_effect = lambda *x, **y: None inferencer = MMOCRInferencer(rec='crnn_mini-vgg_5e_mj') img_path = 'tests/data/rec_toy_dataset/imgs/1036169.jpg' res_img_path = inferencer(img_path, return_vis=True) img_paths = [ 'tests/data/rec_toy_dataset/imgs/1036169.jpg', 'tests/data/rec_toy_dataset/imgs/1058891.jpg' ] res_img_paths = inferencer(img_paths, return_vis=True) self.assert_predictions_equal(res_img_path['predictions'][0], res_img_paths['predictions'][0]) self.assertTrue( np.allclose(res_img_path['visualization'][0], res_img_paths['visualization'][0])) # cross checking: ndarray <-> path img_ndarray = mmcv.imread(img_path) res_img_ndarray = inferencer(img_ndarray, return_vis=True) img_ndarrays = [mmcv.imread(p) for p in img_paths] res_img_ndarrays = inferencer(img_ndarrays, return_vis=True) self.assert_predictions_equal(res_img_ndarray['predictions'][0], res_img_ndarrays['predictions'][0]) self.assertTrue( np.allclose(res_img_ndarray['visualization'][0], res_img_ndarrays['visualization'][0])) self.assert_predictions_equal(res_img_ndarray['predictions'][0], res_img_path['predictions'][0]) self.assertTrue( np.allclose(res_img_ndarray['visualization'][0], res_img_path['visualization'][0])) # test save_vis and save_pred with tempfile.TemporaryDirectory() as tmp_dir: res = inferencer( img_paths, out_dir=tmp_dir, save_vis=True, save_pred=True) for img_dir in ['1036169.jpg', '1058891.jpg']: self.assertTrue(osp.exists(osp.join(tmp_dir, 'vis', img_dir))) for i, pred_dir in enumerate(['1036169.json', '1058891.json']): dumped_res = mmengine.load( osp.join(tmp_dir, 'preds', pred_dir)) self.assert_predictions_equal(res['predictions'][i], dumped_res) @mock.patch('mmengine.infer.infer._load_checkpoint') def test_det_rec(self, mock_load): mock_load.side_effect = lambda *x, **y: None inferencer = MMOCRInferencer( det='dbnet_resnet18_fpnc_1200e_icdar2015', rec='crnn_mini-vgg_5e_mj') img_path = 'tests/data/det_toy_dataset/imgs/test/img_1.jpg' res_img_path = inferencer(img_path, return_vis=True) img_paths = [ 'tests/data/det_toy_dataset/imgs/test/img_1.jpg', 'tests/data/det_toy_dataset/imgs/test/img_2.jpg' ] res_img_paths = inferencer(img_paths, return_vis=True) self.assert_predictions_equal(res_img_path['predictions'][0], res_img_paths['predictions'][0]) self.assertTrue( np.allclose(res_img_path['visualization'][0], res_img_paths['visualization'][0])) img_ndarray = mmcv.imread(img_path) res_img_ndarray = inferencer(img_ndarray, return_vis=True) img_ndarrays = [mmcv.imread(p) for p in img_paths] res_img_ndarrays = inferencer(img_ndarrays, return_vis=True) self.assert_predictions_equal(res_img_ndarray['predictions'][0], res_img_ndarrays['predictions'][0]) self.assertTrue( np.allclose(res_img_ndarray['visualization'][0], res_img_ndarrays['visualization'][0])) # cross checking: ndarray <-> path self.assert_predictions_equal(res_img_ndarray['predictions'][0], res_img_path['predictions'][0]) self.assertTrue( np.allclose(res_img_ndarray['visualization'][0], res_img_path['visualization'][0])) # test save_vis and save_pred with tempfile.TemporaryDirectory() as tmp_dir: res = inferencer( img_paths, out_dir=tmp_dir, save_vis=True, save_pred=True) for img_dir in ['img_1.jpg', 'img_2.jpg']: self.assertTrue(osp.exists(osp.join(tmp_dir, 'vis', img_dir))) for i, pred_dir in enumerate(['img_1.json', 'img_2.json']): dumped_res = mmengine.load( osp.join(tmp_dir, 'preds', pred_dir)) self.assert_predictions_equal(res['predictions'][i], dumped_res) # corner case: when the det model cannot detect any texts inferencer(np.zeros((100, 100, 3)), return_vis=True) @mock.patch('mmengine.infer.infer._load_checkpoint') def test_dec_rec_kie(self, mock_load): mock_load.side_effect = lambda *x, **y: None inferencer = MMOCRInferencer( det='dbnet_resnet18_fpnc_1200e_icdar2015', rec='crnn_mini-vgg_5e_mj', kie='sdmgr_unet16_60e_wildreceipt') img_path = 'tests/data/kie_toy_dataset/wildreceipt/1.jpeg' res_img_path = inferencer(img_path, return_vis=True) img_paths = [ 'tests/data/kie_toy_dataset/wildreceipt/1.jpeg', 'tests/data/kie_toy_dataset/wildreceipt/2.jpeg' ] res_img_paths = inferencer(img_paths, return_vis=True) self.assert_predictions_equal(res_img_path['predictions'][0], res_img_paths['predictions'][0]) self.assertTrue( np.allclose(res_img_path['visualization'][0], res_img_paths['visualization'][0])) img_ndarray = mmcv.imread(img_path) res_img_ndarray = inferencer(img_ndarray, return_vis=True) img_ndarrays = [mmcv.imread(p) for p in img_paths] res_img_ndarrays = inferencer(img_ndarrays, return_vis=True) self.assert_predictions_equal(res_img_ndarray['predictions'][0], res_img_ndarrays['predictions'][0]) self.assertTrue( np.allclose(res_img_ndarray['visualization'][0], res_img_ndarrays['visualization'][0])) # cross checking: ndarray <-> path self.assert_predictions_equal(res_img_ndarray['predictions'][0], res_img_path['predictions'][0]) self.assertTrue( np.allclose(res_img_ndarray['visualization'][0], res_img_path['visualization'][0])) # test save_vis and save_pred with tempfile.TemporaryDirectory() as tmp_dir: res = inferencer( img_paths, out_dir=tmp_dir, save_vis=True, save_pred=True) for img_dir in ['1.jpg', '2.jpg']: self.assertTrue(osp.exists(osp.join(tmp_dir, 'vis', img_dir))) for i, pred_dir in enumerate(['1.json', '2.json']): dumped_res = mmengine.load( osp.join(tmp_dir, 'preds', pred_dir)) self.assert_predictions_equal(res['predictions'][i], dumped_res)