Compare commits

..

No commits in common. "master" and "v0.11.0" have entirely different histories.

60 changed files with 208 additions and 1241 deletions

View File

@ -39,7 +39,7 @@ concurrency:
jobs:
ut-torch180:
# The type of runner that the job will run on
runs-on: [self-hosted]
runs-on: [unittest-t4]
steps:
- name: Checkout
uses: actions/checkout@v2
@ -64,8 +64,8 @@ jobs:
# pip install -r requirements.txt
#run test
export CUDA_VISIBLE_DEVICES=7
source ~/anaconda3/etc/profile.d/conda.sh
conda activate easycv_torch1.8.0
source ~/workspace/anaconda2/etc/profile.d/conda.sh
conda activate easycv_torch1.8.0_py37
# pip install pai-easycv
pip uninstall -y pai-easycv
@ -75,16 +75,13 @@ jobs:
# move source code, ensure import easycv from site-package
mv ./easycv ./easycv_src
PYTHONPATH=. python tests/run.py --skip_dir tests/test_toolkit/modelscope
conda activate easycv_torch1.8.0_py37
PYTHONPATH=. python tests/run.py --test_dir tests/test_toolkit/modelscope
PYTHONPATH=. python tests/run.py
# blade test env will be updated! we do not support test with trt_efficient_nms
ut-torch181-blade:
# The type of runner that the job will run on
runs-on: [self-hosted]
runs-on: [unittest-t4]
steps:
- name: Checkout
uses: actions/checkout@v2
@ -110,7 +107,7 @@ jobs:
# pip install -r requirements.txt
#run test
export CUDA_VISIBLE_DEVICES=6
source ~/anaconda3/etc/profile.d/conda.sh
source ~/workspace/anaconda2/etc/profile.d/conda.sh
conda activate torch1.8.1_blade
PYTHONPATH=. python tests/test_predictors/test_detector_blade.py
PYTHONPATH=. python tests/test_apis/test_export_blade.py

View File

@ -248,7 +248,7 @@ Please refer to the following model zoo for more details.
## Data Hub
EasyCV have collected dataset info for different scenarios, making it easy for users to finetune or evaluate models in EasyCV model zoo.
EasyCV have collected dataset info for different senarios, making it easy for users to finetune or evaluate models in EasyCV model zoo.
Please refer to [data_hub.md](docs/source/data_hub.md).

View File

@ -153,7 +153,7 @@ eval_pipelines = [
data=data['val'],
dist_eval=True,
evaluators=[
dict(type='ClsEvaluator', topk=(1, ), class_list=class_list)
dict(type='ClsEvaluator', topk=(1, 5), class_list=class_list)
],
)
]

View File

@ -4,31 +4,16 @@ num_classes = 1000
# model settings
model = dict(
type='Classification',
backbone=dict(type='Inception3', num_classes=1000),
head=[
dict(
type='ClsHead',
with_fc=False,
in_channels=2048,
loss_config=dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
num_classes=num_classes,
input_feature_index=[1],
backbone=dict(type='Inception3'),
head=dict(
type='ClsHead',
with_avg_pool=True,
in_channels=2048,
loss_config=dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
dict(
type='ClsHead',
with_fc=False,
in_channels=768,
loss_config=dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
num_classes=num_classes,
input_feature_index=[0],
)
])
num_classes=num_classes))
class_list = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13',
@ -211,5 +196,3 @@ log_config = dict(
interval=10,
hooks=[dict(type='TextLoggerHook'),
dict(type='TensorboardLoggerHook')])
export = dict(export_type='raw', export_neck=True)

View File

@ -1,33 +0,0 @@
_base_ = 'configs/classification/imagenet/inception/inceptionv3_b32x8_100e.py'
num_classes = 1000
# model settings
model = dict(
type='Classification',
backbone=dict(type='Inception4', num_classes=num_classes),
head=[
dict(
type='ClsHead',
with_fc=False,
in_channels=1536,
loss_config=dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
num_classes=num_classes,
input_feature_index=[1],
),
dict(
type='ClsHead',
with_fc=False,
in_channels=768,
loss_config=dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
num_classes=num_classes,
input_feature_index=[0],
)
])
img_norm_cfg = dict(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])

View File

@ -1,46 +0,0 @@
# A config with the optimization settings from https://arxiv.org/pdf/1602.07261
# May run with 20 GPUs
_base_ = 'configs/classification/imagenet/inception/inceptionv3_b32x8_100e.py'
num_classes = 1000
# model settings
model = dict(
type='Classification',
backbone=dict(type='Inception4', num_classes=num_classes),
head=[
dict(
type='ClsHead',
with_fc=False,
in_channels=1536,
loss_config=dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
num_classes=num_classes,
input_feature_index=[1],
),
dict(
type='ClsHead',
with_fc=False,
in_channels=768,
loss_config=dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
num_classes=num_classes,
input_feature_index=[0],
)
])
img_norm_cfg = dict(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
# optimizer
optimizer = dict(
type='RMSprop', lr=0.045, momentum=0.9, weight_decay=0.9, eps=1.0)
# learning policy
lr_config = dict(policy='exp', gamma=0.96954) # gamma**2 ~ 0.94
checkpoint_config = dict(interval=10)
# runtime settings
total_epochs = 200

View File

@ -13,8 +13,7 @@ model = dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
num_classes=num_classes),
pretrained=True)
num_classes=num_classes))
# optimizer
optimizer = dict(type='SGD', lr=0.1, momentum=0.9, weight_decay=0.0001)
@ -26,4 +25,4 @@ checkpoint_config = dict(interval=5)
# runtime settings
total_epochs = 100
checkpoint_sync_export = True
export = dict(export_type='raw', export_neck=True)
export = dict(export_neck=True)

View File

@ -6,6 +6,3 @@ model = dict(
depth=50,
out_indices=[4], # 0: conv-1, x: stage-x
norm_cfg=dict(type='BN')))
checkpoint_sync_export = True
export = dict(export_type='raw', export_neck=True)

View File

@ -19,8 +19,7 @@ model = dict(
type='CrossEntropyLossWithLabelSmooth',
label_smooth=0,
),
num_classes=num_classes),
pretrained=True)
num_classes=num_classes))
# optimizer
optimizer = dict(type='SGD', lr=0.1, momentum=0.9, weight_decay=0.0001)
@ -31,4 +30,3 @@ checkpoint_config = dict(interval=10)
# runtime settings
total_epochs = 100
export = dict(export_type='raw', export_neck=True)

View File

@ -49,14 +49,14 @@ img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
dict(type='MMMosaic', img_scale=tuple(img_scale), pad_val=114.0),
dict(type='MMMosaic', img_scale='${img_scale}', pad_val=114.0),
dict(
type='MMRandomAffine',
scaling_ratio_range=scale_ratio,
border=[img_scale[0] // 2, img_scale[1] // 2]),
scaling_ratio_range='${scale_ratio}',
border=['-${img_scale}[0] // 2', '-${img_scale}[1] // 2']),
dict(
type='MMMixUp', # s m x l; tiny nano will detele
img_scale=tuple(img_scale),
img_scale='${img_scale}',
ratio_range=(0.8, 1.6),
pad_val=114.0),
dict(
@ -70,43 +70,45 @@ train_pipeline = [
dict(type='MMPad', pad_to_square=True, pad_val=(114.0, 114.0, 114.0)),
dict(
type='MMNormalize',
mean=img_norm_cfg['mean'],
std=img_norm_cfg['std'],
to_rgb=img_norm_cfg['to_rgb']),
mean='${img_norm_cfg.mean}',
std='${img_norm_cfg.std}',
to_rgb='${img_norm_cfg.to_rgb}'),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]
test_pipeline = [
dict(type='MMResize', img_scale=img_scale, keep_ratio=True),
dict(type='MMResize', img_scale='${img_scale}', keep_ratio=True),
dict(type='MMPad', pad_to_square=True, pad_val=(114.0, 114.0, 114.0)),
dict(
type='MMNormalize',
mean=img_norm_cfg['mean'],
std=img_norm_cfg['std'],
to_rgb=img_norm_cfg['to_rgb']),
mean='${img_norm_cfg.mean}',
std='${img_norm_cfg.std}',
to_rgb='${img_norm_cfg.to_rgb}'),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img'])
]
train_path = 'data/coco/train2017.manifest'
val_path = 'data/coco/val2017.manifest'
train_dataset = dict(
type='DetImagesMixDataset',
data_source=dict(type='DetSourcePAI', path=train_path, classes=CLASSES),
pipeline=train_pipeline,
dynamic_scale=tuple(img_scale))
val_dataset = dict(
type='DetImagesMixDataset',
imgs_per_gpu=2,
data_source=dict(type='DetSourcePAI', path=val_path, classes=CLASSES),
pipeline=test_pipeline,
dynamic_scale=None,
label_padding=False)
data = dict(
imgs_per_gpu=16, workers_per_gpu=4, train=train_dataset, val=val_dataset)
imgs_per_gpu=16,
workers_per_gpu=4,
train=dict(
type='DetImagesMixDataset',
data_source=dict(
type='DetSourcePAI',
path='data/coco/train2017.manifest',
classes='${CLASSES}'),
pipeline='${train_pipeline}',
dynamic_scale='${img_scale}'),
val=dict(
type='DetImagesMixDataset',
imgs_per_gpu=2,
data_source=dict(
type='DetSourcePAI',
path='data/coco/val2017.manifest',
classes='${CLASSES}'),
pipeline='${test_pipeline}',
dynamic_scale=None,
label_padding=False))
# additional hooks
interval = 10
@ -118,14 +120,14 @@ custom_hooks = [
priority=48),
dict(
type='SyncRandomSizeHook',
ratio_range=random_size,
img_scale=img_scale,
interval=interval,
ratio_range='${random_size}',
img_scale='${img_scale}',
interval='${interval}',
priority=48),
dict(
type='SyncNormHook',
num_last_epochs=15,
interval=interval,
interval='${interval}',
priority=48)
]
@ -133,23 +135,23 @@ custom_hooks = [
vis_num = 20
score_thr = 0.5
eval_config = dict(
interval=interval,
interval='${interval}',
gpu_collect=False,
visualization_config=dict(
vis_num=vis_num,
score_thr=score_thr,
vis_num='${vis_num}',
score_thr='${score_thr}',
) # show by TensorboardLoggerHookV2
)
eval_pipelines = [
dict(
mode='test',
data=val_dataset,
data='${data.val}',
evaluators=[dict(type='CocoDetectionEvaluator', classes=CLASSES)],
)
]
checkpoint_config = dict(interval=interval)
checkpoint_config = dict(interval='${interval}')
# optimizer
# basic_lr_per_img = 0.01 / 64.0
optimizer = dict(

View File

@ -102,7 +102,6 @@ eval_config = dict(interval=1, gpu_collect=False)
eval_pipelines = [
dict(
mode='test',
data=data['val'],
evaluators=[
dict(type='CocoDetectionEvaluator', classes=CLASSES),
],

View File

@ -92,13 +92,13 @@
### Verification
Simple verification
Simple verification
```python
from easycv.apis import *
```
```python
from easycv.apis import *
```
You can also verify your installation using following quick-start examples
You can also verify your installation using following quick-start examples
## Examples

View File

@ -1,9 +1,4 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
# flake8: noqa
# isort:skip_file
import os
os.environ['SETUPTOOLS_USE_DISTUTILS'] = 'stdlib'
from .version import __version__, short_version
__all__ = ['__version__', 'short_version']

View File

@ -157,52 +157,6 @@ def _export_jit_and_blade(model, cfg, filename, dummy_inputs, fp16=False):
torch.jit.save(blade_model, ofile)
def _export_onnx_cls(model, model_config, cfg, filename, meta):
support_backbones = {
'ResNet': {
'depth': [50]
},
'MobileNetV2': {},
'Inception3': {},
'Inception4': {},
'ResNeXt': {
'depth': [50]
}
}
if model_config['backbone'].get('type', None) not in support_backbones:
tmp = ' '.join(support_backbones.keys())
info_str = f'Only support export onnx model for {tmp} now!'
raise ValueError(info_str)
configs = support_backbones[model_config['backbone'].get('type')]
for k, v in configs.items():
if v[0].__class__(model_config['backbone'].get(k, None)) not in v:
raise ValueError(
f"Unsupport config for {model_config['backbone'].get('type')}")
# save json config for test_pipline and class
with io.open(
filename +
'.config.json' if filename.endswith('onnx') else filename +
'.onnx.config.json', 'w') as ofile:
json.dump(meta, ofile)
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model.eval()
model.to(device)
img_size = int(cfg.image_size2)
x_input = torch.randn((1, 3, img_size, img_size)).to(device)
torch.onnx.export(
model,
(x_input, 'onnx'),
filename if filename.endswith('onnx') else filename + '.onnx',
export_params=True,
opset_version=12,
do_constant_folding=True,
input_names=['input'],
output_names=['output'],
)
def _export_cls(model, cfg, filename):
""" export cls (cls & metric learning)model and preprocess config
@ -216,7 +170,6 @@ def _export_cls(model, cfg, filename):
else:
export_cfg = dict(export_neck=False)
export_type = export_cfg.get('export_type', 'raw')
export_neck = export_cfg.get('export_neck', True)
label_map_path = cfg.get('label_map_path', None)
class_list = None
@ -279,14 +232,9 @@ def _export_cls(model, cfg, filename):
if export_neck and (k.startswith('neck') or k.startswith('head')):
state_dict[k] = v
if export_type == 'raw':
checkpoint = dict(state_dict=state_dict, meta=meta, author='EasyCV')
with io.open(filename, 'wb') as ofile:
torch.save(checkpoint, ofile)
elif export_type == 'onnx':
_export_onnx_cls(model, model_config, cfg, filename, config)
else:
raise ValueError('Only support export onnx/raw model!')
checkpoint = dict(state_dict=state_dict, meta=meta, author='EasyCV')
with io.open(filename, 'wb') as ofile:
torch.save(checkpoint, ofile)
def _export_yolox(model, cfg, filename):
@ -299,10 +247,10 @@ def _export_yolox(model, cfg, filename):
if hasattr(cfg, 'export'):
export_type = getattr(cfg.export, 'export_type', 'raw')
default_export_type_list = ['raw', 'jit', 'blade', 'onnx']
default_export_type_list = ['raw', 'jit', 'blade']
if export_type not in default_export_type_list:
logging.warning(
'YOLOX-PAI only supports the export type as [raw,jit,blade,onnx], otherwise we use raw as default'
'YOLOX-PAI only supports the export type as [raw,jit,blade], otherwise we use raw as default'
)
export_type = 'raw'
@ -328,7 +276,7 @@ def _export_yolox(model, cfg, filename):
len(img_scale) == 2
), 'Export YoloX predictor config contains img_scale must be (int, int) tuple!'
input = 255 * torch.rand((batch_size, 3) + tuple(img_scale))
input = 255 * torch.rand((batch_size, 3) + img_scale)
# assert use_trt_efficientnms only happens when static_opt=True
if static_opt is not True:
@ -407,31 +355,6 @@ def _export_yolox(model, cfg, filename):
json.dump(config, ofile)
if export_type == 'onnx':
with io.open(
filename + '.config.json' if filename.endswith('onnx')
else filename + '.onnx.config.json', 'w') as ofile:
config = dict(
model=cfg.model,
export=cfg.export,
test_pipeline=cfg.test_pipeline,
classes=cfg.CLASSES)
json.dump(config, ofile)
torch.onnx.export(
model,
input.to(device),
filename if filename.endswith('onnx') else filename +
'.onnx',
export_params=True,
opset_version=12,
do_constant_folding=True,
input_names=['input'],
output_names=['output'],
)
if export_type == 'jit':
with io.open(filename + '.jit', 'wb') as ofile:
torch.jit.save(yolox_trace, ofile)
@ -727,12 +650,6 @@ def _export_pose_topdown(model, cfg, filename, fp16=False, dummy_inputs=None):
model.to(device)
if hasattr(cfg, 'export') and getattr(cfg.export, 'type', 'raw') == 'raw':
from mmcv.utils.path import is_filepath
if hasattr(cfg, 'dataset_info') and is_filepath(cfg.dataset_info):
dataset_info_cfg = Config.fromfile(cfg.dataset_info)
cfg.dataset_info = dataset_info_cfg._cfg_dict['dataset_info']
return _export_common(model, cfg, filename)
def _dummy_inputs(cfg):

View File

@ -146,14 +146,10 @@ class ClsEvaluator(Evaluator):
matrix = confusion_matrix(
valid_true, valid_pred, labels=self.class_list)
# print_log(
# 'recall:{}\nprecision:{}\nattend:{}\nTP:{}\nFN:{}\nFP:{}\nTN:{}\nrecall/mean:{}\nprecision/mean:{}\nF1/mean:{}\nconfusion_matrix:{}\n'
# .format(recall, precision, attend, tp, fn, fp, tn,
# recall_mean, precision_mean, f1_mean, matrix))
eval_res[key] = \
'recall:{}\nprecision:{}\nattend:{}\nTP:{}\nFN:{}\nFP:{}\nTN:{}\nrecall/mean:{}\nprecision/mean:{}\nF1/mean:{}\nconfusion_matrix:{}\n'\
.format(recall, precision, attend, tp, fn, fp, tn, recall_mean, precision_mean, f1_mean, matrix.tolist())
print_log(
'recall:{}\nprecision:{}\nattend:{}\nTP:{}\nFN:{}\nFP:{}\nTN:{}\nrecall/mean:{}\nprecision/mean:{}\nF1/mean:{}\nconfusion_matrix:{}\n'
.format(recall, precision, attend, tp, fn, fp, tn,
recall_mean, precision_mean, f1_mean, matrix))
return eval_res

View File

@ -467,8 +467,8 @@ class COCOeval:
fps = np.logical_and(
np.logical_not(dtm), np.logical_not(dtIg))
tp_sum = np.cumsum(tps, axis=1).astype(dtype=np.float32)
fp_sum = np.cumsum(fps, axis=1).astype(dtype=np.float32)
tp_sum = np.cumsum(tps, axis=1).astype(dtype=np.float)
fp_sum = np.cumsum(fps, axis=1).astype(dtype=np.float)
for t, (tp, fp) in enumerate(zip(tp_sum, fp_sum)):
tp = np.array(tp)
fp = np.array(fp)

View File

@ -252,7 +252,7 @@ class FaceKeypointsDataAugumentation:
skin_factor_list = [0.6, 0.8, 1.0, 1.2, 1.4]
skin_factor = np.random.choice(skin_factor_list)
img_ycrcb_raw[:, :, 0:1] = np.clip(
img_ycrcb_raw[:, :, 0:1].astype(np.float32) * skin_factor, 0,
img_ycrcb_raw[:, :, 0:1].astype(np.float) * skin_factor, 0,
255).astype(np.uint8)
img = cv2.cvtColor(img_ycrcb_raw, cv2.COLOR_YCR_CB2BGR)

View File

@ -246,7 +246,7 @@ class DistributedSampler(_DistributedSampler):
l, size_per_label, replace=(len(l) <= size_per_label)))
indices = np.array(indices)
np.random.shuffle(indices)
indices = indices[:N].astype(np.int64).tolist()
indices = indices[:N].astype(np.int).tolist()
# add extra samples to make it evenly divisible
assert len(indices) <= self.total_size, \
@ -438,7 +438,7 @@ class DistributedGivenIterationSampler(Sampler):
l, size_per_label, replace=(len(l) <= size_per_label)))
indices = np.array(indices)
np.random.shuffle(indices)
indices = indices[:N].astype(np.int64)
indices = indices[:N].astype(np.int)
# repeat
all_size = self.total_size * self.world_size
indices = indices[:all_size]

View File

@ -110,16 +110,16 @@ class SegSourceCityscapes(SegSourceRaw):
'')[:-len(self.img_suffix[0])]
find_label_path = False
for label_format in self.label_suffix:
label_path = os.path.join(self.label_root,
lable_path = os.path.join(self.label_root,
img_name + label_format)
if io.exists(label_path):
if io.exists(lable_path):
find_label_path = True
self.label_files.append(label_path)
self.label_files.append(lable_path)
break
if not find_label_path:
logging.warning(
'Not find label file %s for img: %s, skip the sample!' %
(label_path, img_path))
(lable_path, img_path))
self.img_files.remove(img_path)
assert len(self.img_files) == len(self.label_files)

View File

@ -1,5 +1,5 @@
# Copyright (c) OpenMMLab and Alibaba. All rights reserved.
from collections.abc import Sequence
from collections import Sequence
import mmcv
import numpy as np

View File

@ -161,7 +161,7 @@ class SampleFrames:
ratio = (num_frames - ori_clip_len + 1.0) / self.num_clips
clip_offsets = np.around(np.arange(self.num_clips) * ratio)
else:
clip_offsets = np.zeros((self.num_clips, ), dtype=np.int64)
clip_offsets = np.zeros((self.num_clips, ), dtype=np.int)
return clip_offsets
@ -180,11 +180,11 @@ class SampleFrames:
avg_interval = (num_frames - ori_clip_len + 1) / float(self.num_clips)
if num_frames > ori_clip_len - 1:
base_offsets = np.arange(self.num_clips) * avg_interval
clip_offsets = (base_offsets + avg_interval / 2.0).astype(np.int64)
clip_offsets = (base_offsets + avg_interval / 2.0).astype(np.int)
if self.twice_sample:
clip_offsets = np.concatenate([clip_offsets, base_offsets])
else:
clip_offsets = np.zeros((self.num_clips, ), dtype=np.int64)
clip_offsets = np.zeros((self.num_clips, ), dtype=np.int)
return clip_offsets
def _sample_clips(self, num_frames):
@ -259,7 +259,7 @@ class SampleFrames:
start_index = results['start_index']
frame_inds = np.concatenate(frame_inds) + start_index
results['frame_inds'] = frame_inds.astype(np.int64)
results['frame_inds'] = frame_inds.astype(np.int)
results['clip_len'] = self.clip_len
results['frame_interval'] = self.frame_interval
results['num_clips'] = self.num_clips

View File

@ -34,7 +34,7 @@ class PaddingWithLoop:
inds = np.arange(start, start + self.clip_len)
inds = np.mod(inds, num_frames)
results['frame_inds'] = inds.astype(np.int64)
results['frame_inds'] = inds.astype(np.int)
results['clip_len'] = self.clip_len
results['frame_interval'] = None
results['num_clips'] = self.num_clips

View File

@ -1,4 +1,4 @@
from .file_io import IO
from .utils import get_oss_config, is_oss_path
from .utils import is_oss_path
io = IO()

View File

@ -10,7 +10,6 @@ from .face_keypoint_backbone import FaceKeypointBackbone
from .genet import PlainNet
from .hrnet import HRNet
from .inceptionv3 import Inception3
from .inceptionv4 import Inception4
from .lighthrnet import LiteHRNet
from .mae_vit_transformer import *
from .mit import MixVisionTransformer

View File

@ -1,21 +1,15 @@
# Copyright (c) 2022 Snap Inc. All rights reserved.
import itertools
import os
from distutils.version import LooseVersion
import timm
import torch
import torch.nn as nn
from timm.models.layers import DropPath, trunc_normal_
from timm.models.layers.helpers import to_2tuple
from ..modelzoo import efficientformer as model_urls
from ..registry import BACKBONES
if LooseVersion(timm.__version__) <= LooseVersion('0.8.2'):
from timm.models.layers.helpers import to_2tuple
else:
from timm.layers.helpers import to_2tuple
class Attention(torch.nn.Module):

View File

@ -2,6 +2,9 @@
r""" This model is taken from the official PyTorch model zoo.
- torchvision.models.inception.py on 31th Aug, 2019
"""
from collections import namedtuple
import torch
import torch.nn as nn
import torch.nn.functional as F
@ -13,6 +16,8 @@ from ..registry import BACKBONES
__all__ = ['Inception3']
_InceptionOutputs = namedtuple('InceptionOutputs', ['logits', 'aux_logits'])
@BACKBONES.register_module
class Inception3(nn.Module):
@ -108,7 +113,6 @@ class Inception3(nn.Module):
# N x 768 x 17 x 17
x = self.Mixed_6e(x)
# N x 768 x 17 x 17
aux = None
if self.training and self.aux_logits:
aux = self.AuxLogits(x)
# N x 768 x 17 x 17
@ -128,7 +132,10 @@ class Inception3(nn.Module):
if hasattr(self, 'fc'):
x = self.fc(x)
return [aux, x]
# N x 1000 (num_classes)
if self.training and self.aux_logits and hasattr(self, 'fc'):
return [_InceptionOutputs(x, aux)]
return [x]
class InceptionA(nn.Module):

View File

@ -1,393 +0,0 @@
from __future__ import absolute_import, division, print_function
from collections import namedtuple
import torch
import torch.nn as nn
import torch.nn.functional as F
from mmcv.cnn import constant_init, kaiming_init
from torch.nn.modules.batchnorm import _BatchNorm
from ..modelzoo import inceptionv4 as model_urls
from ..registry import BACKBONES
__all__ = ['Inception4']
class BasicConv2d(nn.Module):
def __init__(self,
in_planes,
out_planes,
kernel_size,
stride=1,
padding=0):
super(BasicConv2d, self).__init__()
self.conv = nn.Conv2d(
in_planes,
out_planes,
kernel_size=kernel_size,
stride=stride,
padding=padding,
bias=False) # verify bias false
self.bn = nn.BatchNorm2d(
out_planes,
eps=0.001, # value found in tensorflow
momentum=0.1, # default pytorch value
affine=True)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
x = self.conv(x)
x = self.bn(x)
x = self.relu(x)
return x
class Mixed_3a(nn.Module):
def __init__(self):
super(Mixed_3a, self).__init__()
self.maxpool = nn.MaxPool2d(3, stride=2)
self.conv = BasicConv2d(64, 96, kernel_size=3, stride=2)
def forward(self, x):
x0 = self.maxpool(x)
x1 = self.conv(x)
out = torch.cat((x0, x1), 1)
return out
class Mixed_4a(nn.Module):
def __init__(self):
super(Mixed_4a, self).__init__()
self.branch0 = nn.Sequential(
BasicConv2d(160, 64, kernel_size=1, stride=1),
BasicConv2d(64, 96, kernel_size=3, stride=1))
self.branch1 = nn.Sequential(
BasicConv2d(160, 64, kernel_size=1, stride=1),
BasicConv2d(64, 64, kernel_size=(1, 7), stride=1, padding=(0, 3)),
BasicConv2d(64, 64, kernel_size=(7, 1), stride=1, padding=(3, 0)),
BasicConv2d(64, 96, kernel_size=(3, 3), stride=1))
def forward(self, x):
x0 = self.branch0(x)
x1 = self.branch1(x)
out = torch.cat((x0, x1), 1)
return out
class Mixed_5a(nn.Module):
def __init__(self):
super(Mixed_5a, self).__init__()
self.conv = BasicConv2d(192, 192, kernel_size=3, stride=2)
self.maxpool = nn.MaxPool2d(3, stride=2)
def forward(self, x):
x0 = self.conv(x)
x1 = self.maxpool(x)
out = torch.cat((x0, x1), 1)
return out
class Inception_A(nn.Module):
def __init__(self):
super(Inception_A, self).__init__()
self.branch0 = BasicConv2d(384, 96, kernel_size=1, stride=1)
self.branch1 = nn.Sequential(
BasicConv2d(384, 64, kernel_size=1, stride=1),
BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1))
self.branch2 = nn.Sequential(
BasicConv2d(384, 64, kernel_size=1, stride=1),
BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1),
BasicConv2d(96, 96, kernel_size=3, stride=1, padding=1))
self.branch3 = nn.Sequential(
nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
BasicConv2d(384, 96, kernel_size=1, stride=1))
def forward(self, x):
x0 = self.branch0(x)
x1 = self.branch1(x)
x2 = self.branch2(x)
x3 = self.branch3(x)
out = torch.cat((x0, x1, x2, x3), 1)
return out
class Reduction_A(nn.Module):
def __init__(self):
super(Reduction_A, self).__init__()
self.branch0 = BasicConv2d(384, 384, kernel_size=3, stride=2)
self.branch1 = nn.Sequential(
BasicConv2d(384, 192, kernel_size=1, stride=1),
BasicConv2d(192, 224, kernel_size=3, stride=1, padding=1),
BasicConv2d(224, 256, kernel_size=3, stride=2))
self.branch2 = nn.MaxPool2d(3, stride=2)
def forward(self, x):
x0 = self.branch0(x)
x1 = self.branch1(x)
x2 = self.branch2(x)
out = torch.cat((x0, x1, x2), 1)
return out
class Inception_B(nn.Module):
def __init__(self):
super(Inception_B, self).__init__()
self.branch0 = BasicConv2d(1024, 384, kernel_size=1, stride=1)
self.branch1 = nn.Sequential(
BasicConv2d(1024, 192, kernel_size=1, stride=1),
BasicConv2d(
192, 224, kernel_size=(1, 7), stride=1, padding=(0, 3)),
BasicConv2d(
224, 256, kernel_size=(7, 1), stride=1, padding=(3, 0)))
self.branch2 = nn.Sequential(
BasicConv2d(1024, 192, kernel_size=1, stride=1),
BasicConv2d(
192, 192, kernel_size=(7, 1), stride=1, padding=(3, 0)),
BasicConv2d(
192, 224, kernel_size=(1, 7), stride=1, padding=(0, 3)),
BasicConv2d(
224, 224, kernel_size=(7, 1), stride=1, padding=(3, 0)),
BasicConv2d(
224, 256, kernel_size=(1, 7), stride=1, padding=(0, 3)))
self.branch3 = nn.Sequential(
nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
BasicConv2d(1024, 128, kernel_size=1, stride=1))
def forward(self, x):
x0 = self.branch0(x)
x1 = self.branch1(x)
x2 = self.branch2(x)
x3 = self.branch3(x)
out = torch.cat((x0, x1, x2, x3), 1)
return out
class Reduction_B(nn.Module):
def __init__(self):
super(Reduction_B, self).__init__()
self.branch0 = nn.Sequential(
BasicConv2d(1024, 192, kernel_size=1, stride=1),
BasicConv2d(192, 192, kernel_size=3, stride=2))
self.branch1 = nn.Sequential(
BasicConv2d(1024, 256, kernel_size=1, stride=1),
BasicConv2d(
256, 256, kernel_size=(1, 7), stride=1, padding=(0, 3)),
BasicConv2d(
256, 320, kernel_size=(7, 1), stride=1, padding=(3, 0)),
BasicConv2d(320, 320, kernel_size=3, stride=2))
self.branch2 = nn.MaxPool2d(3, stride=2)
def forward(self, x):
x0 = self.branch0(x)
x1 = self.branch1(x)
x2 = self.branch2(x)
out = torch.cat((x0, x1, x2), 1)
return out
class Inception_C(nn.Module):
def __init__(self):
super(Inception_C, self).__init__()
self.branch0 = BasicConv2d(1536, 256, kernel_size=1, stride=1)
self.branch1_0 = BasicConv2d(1536, 384, kernel_size=1, stride=1)
self.branch1_1a = BasicConv2d(
384, 256, kernel_size=(1, 3), stride=1, padding=(0, 1))
self.branch1_1b = BasicConv2d(
384, 256, kernel_size=(3, 1), stride=1, padding=(1, 0))
self.branch2_0 = BasicConv2d(1536, 384, kernel_size=1, stride=1)
self.branch2_1 = BasicConv2d(
384, 448, kernel_size=(3, 1), stride=1, padding=(1, 0))
self.branch2_2 = BasicConv2d(
448, 512, kernel_size=(1, 3), stride=1, padding=(0, 1))
self.branch2_3a = BasicConv2d(
512, 256, kernel_size=(1, 3), stride=1, padding=(0, 1))
self.branch2_3b = BasicConv2d(
512, 256, kernel_size=(3, 1), stride=1, padding=(1, 0))
self.branch3 = nn.Sequential(
nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False),
BasicConv2d(1536, 256, kernel_size=1, stride=1))
def forward(self, x):
x0 = self.branch0(x)
x1_0 = self.branch1_0(x)
x1_1a = self.branch1_1a(x1_0)
x1_1b = self.branch1_1b(x1_0)
x1 = torch.cat((x1_1a, x1_1b), 1)
x2_0 = self.branch2_0(x)
x2_1 = self.branch2_1(x2_0)
x2_2 = self.branch2_2(x2_1)
x2_3a = self.branch2_3a(x2_2)
x2_3b = self.branch2_3b(x2_2)
x2 = torch.cat((x2_3a, x2_3b), 1)
x3 = self.branch3(x)
out = torch.cat((x0, x1, x2, x3), 1)
return out
class InceptionAux(nn.Module):
def __init__(self, in_channels, num_classes):
super(InceptionAux, self).__init__()
self.conv0 = BasicConv2d(in_channels, 128, kernel_size=1)
self.conv1 = BasicConv2d(128, 768, kernel_size=5)
self.conv1.stddev = 0.01
self.fc = nn.Linear(768, num_classes)
self.fc.stddev = 0.001
def forward(self, x):
# N x 768 x 17 x 17
x = F.avg_pool2d(x, kernel_size=5, stride=3)
# N x 768 x 5 x 5
x = self.conv0(x)
# N x 128 x 5 x 5
x = self.conv1(x)
# N x 768 x 1 x 1
# Adaptive average pooling
x = F.adaptive_avg_pool2d(x, (1, 1))
# N x 768 x 1 x 1
x = torch.flatten(x, 1)
# N x 768
x = self.fc(x)
# N x 1000
return x
# class BasicConv2d(nn.Module):
# def __init__(self, in_channels, out_channels, **kwargs):
# super(BasicConv2d, self).__init__()
# self.conv = nn.Conv2d(in_channels, out_channels, bias=False, **kwargs)
# self.bn = nn.BatchNorm2d(out_channels, eps=0.001)
# def forward(self, x):
# x = self.conv(x)
# x = self.bn(x)
# return F.relu(x, inplace=True)
@BACKBONES.register_module
class Inception4(nn.Module):
"""InceptionV4 backbone.
Args:
num_classes (int): The num_classes of InceptionV4. An extra fc will be used if
"""
def __init__(self,
num_classes: int = 0,
p_dropout=0.2,
aux_logits: bool = True):
super(Inception4, self).__init__()
self.aux_logits = aux_logits
# Modules
self.features = nn.Sequential(
BasicConv2d(3, 32, kernel_size=3, stride=2),
BasicConv2d(32, 32, kernel_size=3, stride=1),
BasicConv2d(32, 64, kernel_size=3, stride=1, padding=1),
Mixed_3a(),
Mixed_4a(),
Mixed_5a(),
Inception_A(),
Inception_A(),
Inception_A(),
Inception_A(),
Reduction_A(), # Mixed_6a
Inception_B(),
Inception_B(),
Inception_B(),
Inception_B(),
Inception_B(),
Inception_B(),
Inception_B(), # Mixed_6h 1024 x 17 x 17
Reduction_B(), # Mixed_7a
Inception_C(),
Inception_C(),
Inception_C())
if aux_logits:
self.AuxLogits = InceptionAux(1024, num_classes)
self.dropout = nn.Dropout(p_dropout)
self.last_linear = None
if num_classes > 0:
self.last_linear = nn.Linear(1536, num_classes)
self.default_pretrained_model_path = model_urls[
self.__class__.__name__]
@property
def fc(self):
return self.last_linear
def init_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
for m in self.modules():
if isinstance(m, nn.Conv2d):
kaiming_init(m, mode='fan_in', nonlinearity='relu')
elif isinstance(m, (_BatchNorm, nn.GroupNorm)):
constant_init(m, 1)
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
def logits(self, features):
x = F.adaptive_avg_pool2d(features, output_size=(1, 1))
# x = F.avg_pool2d(features, kernel_size=adaptiveAvgPoolWidth)
x = x.view(x.size(0), -1) # B x 1536
x = self.fc(x)
# B x num_classes
return x
def forward(self, input: torch.Tensor):
"""_summary_
Args:
input (torch.Tensor): A RGB image tensor with shape B x C x H x W
Returns:
torch.Tensor: A feature tensor or a logit tensor when num_classes is 0 (default)
"""
if self.training and self.aux_logits:
x = self.features[:-4](input)
aux = self.AuxLogits(x)
x = self.features[-4:](x)
else:
x = self.features(input)
aux = None
if self.fc is not None:
x = self.logits(x)
return [aux, x]

View File

@ -151,21 +151,6 @@ class Classification(BaseModel):
x = self.backbone(img)
return x
@torch.jit.unused
def forward_onnx(self, img: torch.Tensor) -> Dict[str, torch.Tensor]:
"""
forward_onnx means generate prob from image only support one neck + one head
"""
x = self.forward_backbone(img) # tuple
# if self.neck_num > 0:
if hasattr(self, 'neck_0'):
x = self.neck_0([i for i in x])
out = self.head_0(x)[0].cpu()
out = self.activate_fn(out)
return out
@torch.jit.unused
def forward_train(self, img, gt_labels) -> Dict[str, torch.Tensor]:
"""
@ -305,9 +290,6 @@ class Classification(BaseModel):
return self.forward_test_label(img, gt_labels)
else:
return self.forward_test(img)
elif mode == 'onnx':
return self.forward_onnx(img)
elif mode == 'extract':
rd = self.forward_feature(img)
rv = {}

View File

@ -52,22 +52,6 @@ class YOLOX(BaseModel):
assert model_type in self.param_map, f'invalid model_type for yolox {model_type}, valid ones are {list(self.param_map.keys())}'
if num_classes is not None:
# adapt to previous export model (before easycv0.6.0)
logging.warning(
'Warning: You are now attend to use an old YOLOX model before easycv0.6.0 with key num_classes'
)
head = dict(
type='YOLOXHead',
model_type=model_type,
num_classes=num_classes,
)
# the change of backbone/neck/head only support model_type as 's'
if model_type != 's':
head_type = head.get('type', None)
assert backbone == 'CSPDarknet' and neck_type == 'yolo' and neck_mode == 'all' and head_type == 'YOLOXHead', 'We only support the architecture modification for YOLOX-S.'
self.pretrained = pretrained
in_channels = [256, 512, 1024]
@ -84,14 +68,19 @@ class YOLOX(BaseModel):
asff_channel=asff_channel,
use_att=use_att)
if num_classes is not None:
# adapt to previous export model (before easycv0.6.0)
logging.warning(
'Warning: You are now attend to use an old YOLOX model before easycv0.6.0 with key num_classes'
)
head = dict(
type='YOLOXHead',
model_type=model_type,
num_classes=num_classes,
)
if head is not None:
# head is None for YOLOX-edge to define a special head
# set and check model type in head as the same of yolox
head_model_type = head.get('model_type', None)
if head_model_type is None:
head['model_type'] = model_type
else:
assert model_type == head_model_type, 'Please provide the same model_type of YOLOX in config.'
self.head = build_head(head)
self.num_classes = self.head.num_classes

View File

@ -79,12 +79,6 @@ inceptionv3 = {
'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/pretrained_models/easycv/inceptionv3/inception_v3.pth',
}
inceptionv4 = {
# Inception v4 ported from http://data.lip6.fr/cadene/pretrainedmodels/inceptionv4-8e4777a0.pth
'Inception4':
'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/pretrained_models/easycv/inceptionv4/inception_v4.pth',
}
genet = {
'PlainNetnormal':
'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/pretrained_models/easycv/genet/GENet_normal.pth',

View File

@ -135,10 +135,10 @@ class DBPostProcess(object):
'''
h, w = bitmap.shape[:2]
box = _box.copy()
xmin = np.clip(np.floor(box[:, 0].min()).astype(np.int32), 0, w - 1)
xmax = np.clip(np.ceil(box[:, 0].max()).astype(np.int32), 0, w - 1)
ymin = np.clip(np.floor(box[:, 1].min()).astype(np.int32), 0, h - 1)
ymax = np.clip(np.ceil(box[:, 1].max()).astype(np.int32), 0, h - 1)
xmin = np.clip(np.floor(box[:, 0].min()).astype(np.int), 0, w - 1)
xmax = np.clip(np.ceil(box[:, 0].max()).astype(np.int), 0, w - 1)
ymin = np.clip(np.floor(box[:, 1].min()).astype(np.int), 0, h - 1)
ymax = np.clip(np.ceil(box[:, 1].max()).astype(np.int), 0, h - 1)
mask = np.zeros((ymax - ymin + 1, xmax - xmin + 1), dtype=np.uint8)
box[:, 0] = box[:, 0] - xmin

View File

@ -47,7 +47,7 @@ def get_1d_sincos_pos_embed_from_grid(embed_dim, pos):
out: (M, D)
"""
assert embed_dim % 2 == 0
omega = np.arange(embed_dim // 2, dtype=np.float32)
omega = np.arange(embed_dim // 2, dtype=np.float)
omega /= embed_dim / 2.
omega = 1. / 10000**omega # (D/2,)

View File

@ -1,7 +1,5 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
import glob
import math
import os
import numpy as np
import torch
@ -9,18 +7,11 @@ from PIL import Image
from easycv.file import io
from easycv.framework.errors import ValueError
from easycv.utils.checkpoint import load_checkpoint
from easycv.utils.misc import deprecated
from .base import InputProcessor, OutputProcessor, Predictor, PredictorV2
from .builder import PREDICTORS
# onnx specific
def onnx_to_numpy(tensor):
return tensor.detach().cpu().numpy(
) if tensor.requires_grad else tensor.cpu().numpy()
class ClsInputProcessor(InputProcessor):
"""Process inputs for classification models.
@ -155,20 +146,6 @@ class ClassificationPredictor(PredictorV2):
self.pil_input = pil_input
self.label_map_path = label_map_path
if model_path.endswith('onnx'):
self.model_type = 'onnx'
pwd_model = os.path.dirname(model_path)
raw_model = glob.glob(
os.path.join(pwd_model, '*.onnx.config.json'))
if len(raw_model) != 0:
config_file = raw_model[0]
else:
assert len(
raw_model
) == 0, 'Please have a file with the .onnx.config.json extension in your directory'
else:
self.model_type = 'raw'
if self.pil_input:
mode = 'RGB'
super(ClassificationPredictor, self).__init__(
@ -209,41 +186,6 @@ class ClassificationPredictor(PredictorV2):
return ClsOutputProcessor(topk=self.topk, label_map=self.label_map)
def prepare_model(self):
"""Build model from config file by default.
If the model is not loaded from a configuration file, e.g. torch jit model, you need to reimplement it.
"""
if self.model_type == 'raw':
model = self._build_model()
model.to(self.device)
model.eval()
load_checkpoint(model, self.model_path, map_location='cpu')
return model
else:
import onnxruntime
if onnxruntime.get_device() == 'GPU':
onnx_model = onnxruntime.InferenceSession(
self.model_path, providers=['CUDAExecutionProvider'])
else:
onnx_model = onnxruntime.InferenceSession(self.model_path)
return onnx_model
def model_forward(self, inputs):
"""Model forward.
If you need refactor model forward, you need to reimplement it.
"""
with torch.no_grad():
if self.model_type == 'raw':
outputs = self.model(**inputs, mode='test')
else:
outputs = self.model.run(None, {
self.model.get_inputs()[0].name:
onnx_to_numpy(inputs['img'])
})[0]
outputs = dict(prob=torch.from_numpy(outputs))
return outputs
try:
from easy_vision.python.inference.predictor import PredictorInterface

View File

@ -23,12 +23,6 @@ except Exception:
from .interface import PredictorInterface
# 将张量转化为ndarray格式
def onnx_to_numpy(tensor):
return tensor.detach().cpu().numpy(
) if tensor.requires_grad else tensor.cpu().numpy()
class DetInputProcessor(InputProcessor):
def build_processor(self):
@ -355,11 +349,9 @@ class YoloXPredictor(DetectionPredictor):
self.model_type = 'jit'
elif model_path.endswith('blade'):
self.model_type = 'blade'
elif model_path.endswith('onnx'):
self.model_type = 'onnx'
else:
self.model_type = 'raw'
assert self.model_type in ['raw', 'jit', 'blade', 'onnx']
assert self.model_type in ['raw', 'jit', 'blade']
if self.model_type == 'blade' or self.use_trt_efficientnms:
import torch_blade
@ -389,16 +381,8 @@ class YoloXPredictor(DetectionPredictor):
def _build_model(self):
if self.model_type != 'raw':
if self.model_type != 'onnx':
with io.open(self.model_path, 'rb') as infile:
model = torch.jit.load(infile, self.device)
else:
import onnxruntime
if onnxruntime.get_device() == 'GPU':
model = onnxruntime.InferenceSession(
self.model_path, providers=['CUDAExecutionProvider'])
else:
model = onnxruntime.InferenceSession(self.model_path)
with io.open(self.model_path, 'rb') as infile:
model = torch.jit.load(infile, self.device)
else:
from easycv.utils.misc import reparameterize_models
model = super()._build_model()
@ -410,9 +394,8 @@ class YoloXPredictor(DetectionPredictor):
If the model is not loaded from a configuration file, e.g. torch jit model, you need to reimplement it.
"""
model = self._build_model()
if self.model_type != 'onnx':
model.to(self.device)
model.eval()
model.to(self.device)
model.eval()
if self.model_type == 'raw':
load_checkpoint(model, self.model_path, map_location='cpu')
return model
@ -423,15 +406,7 @@ class YoloXPredictor(DetectionPredictor):
"""
if self.model_type != 'raw':
with torch.no_grad():
if self.model_type != 'onnx':
outputs = self.model(inputs['img'])
else:
outputs = self.model.run(
None, {
self.model.get_inputs()[0].name:
onnx_to_numpy(inputs['img'])
})[0]
outputs = torch.from_numpy(outputs)
outputs = self.model(inputs['img'])
outputs = {'results': outputs} # convert to dict format
else:
outputs = super().model_forward(inputs)

View File

@ -19,8 +19,6 @@ from easycv.utils.config_tools import mmcv_config_fromfile
from easycv.utils.misc import deprecated
from .base import InputProcessor, OutputProcessor, PredictorV2
np.set_printoptions(suppress=True)
def _box2cs(image_size, box):
"""This encodes bbox(x,y,w,h) into (center, scale)
@ -224,12 +222,11 @@ class PoseTopDownInputProcessor(InputProcessor):
bboxes = bboxes[valid_idx]
person_results = [person_results[i] for i in valid_idx]
results = []
output_person_info = []
for person_result in person_results:
box = person_result['bbox'] # x,y,x,y,s
boxc = [box[0], box[1], box[2] - box[0],
box[3] - box[1]] # x,y,w,h
center, scale = _box2cs(self.cfg.data_cfg['image_size'], boxc)
box = person_result['bbox'] # x,y,x,y
box = [box[0], box[1], box[2] - box[0], box[3] - box[1]] # x,y,w,h
center, scale = _box2cs(self.cfg.data_cfg['image_size'], box)
data = {
'image_id':
0,
@ -267,10 +264,11 @@ class PoseTopDownInputProcessor(InputProcessor):
output['img_fields'],
}
box_id += 1
data_processor = self.processor(data)
data_processor['bbox'] = box
results.append(data_processor)
output_person_info.append(data)
results = []
for output in output_person_info:
results.append(self.processor(output))
return results
def __call__(self, inputs):
@ -298,7 +296,12 @@ class PoseTopDownOutputProcessor(OutputProcessor):
def __call__(self, inputs):
output = {}
output['keypoints'] = inputs['preds']
output['bbox'] = np.array(inputs['boxes']) # x1, y1, x2, y2 score
output['bbox'] = inputs['boxes'] # c1, c2, s1, s2, area, core
for i, bbox in enumerate(output['bbox']):
center, scale = bbox[:2], bbox[2:4]
output['bbox'][i][:4] = bbox_cs2xyxy(center, scale)
output['bbox'] = output['bbox'][:, [0, 1, 2, 3, 5]]
return output
@ -400,7 +403,6 @@ class PoseTopDownPredictor(PredictorV2):
return model
def model_forward(self, inputs, return_heatmap=False):
boxes = inputs['bbox'].cpu().numpy()
if self.model_type == 'raw':
with torch.no_grad():
result = self.model(
@ -421,7 +423,6 @@ class PoseTopDownPredictor(PredictorV2):
result = decode_heatmap(output_heatmap, img_metas,
self.cfg.model.test_cfg)
result['boxes'] = np.array(boxes)
return result
def get_input_processor(self):

View File

@ -156,7 +156,7 @@ class Mask2formerOutputProcessor(OutputProcessor):
ids = ids[legal_indices]
labels = np.array([id % 1000 for id in ids], dtype=np.int64)
segms = (pan_results[None] == ids[:, None, None])
masks = [it.astype(np.int32) for it in segms]
masks = [it.astype(np.int) for it in segms]
labels_txt = np.array(self.classes)[labels].tolist()
output['masks'] = masks

View File

@ -38,7 +38,7 @@ class STrack(BaseTrack):
def __init__(self, tlwh, score):
# wait activate
self._tlwh = np.asarray(tlwh, dtype=np.float32)
self._tlwh = np.asarray(tlwh, dtype=np.float)
self.kalman_filter = None
self.mean, self.covariance = None, None
self.is_activated = False

View File

@ -86,15 +86,15 @@ def ious(atlbrs, btlbrs):
:rtype ious np.ndarray
"""
ious = np.zeros((len(atlbrs), len(btlbrs)), dtype=np.float32)
ious = np.zeros((len(atlbrs), len(btlbrs)), dtype=np.float)
if ious.size == 0:
return ious
from cython_bbox import bbox_overlaps as bbox_ious
ious = bbox_ious(
np.ascontiguousarray(atlbrs, dtype=np.float32),
np.ascontiguousarray(btlbrs, dtype=np.float32))
np.ascontiguousarray(atlbrs, dtype=np.float),
np.ascontiguousarray(btlbrs, dtype=np.float))
return ious
@ -151,15 +151,15 @@ def embedding_distance(tracks, detections, metric='cosine'):
:return: cost_matrix np.ndarray
"""
cost_matrix = np.zeros((len(tracks), len(detections)), dtype=np.float32)
cost_matrix = np.zeros((len(tracks), len(detections)), dtype=np.float)
if cost_matrix.size == 0:
return cost_matrix
det_features = np.asarray([track.curr_feat for track in detections],
dtype=np.float32)
dtype=np.float)
#for i, track in enumerate(tracks):
#cost_matrix[i, :] = np.maximum(0.0, cdist(track.smooth_feat.reshape(1,-1), det_features, metric))
track_features = np.asarray([track.smooth_feat for track in tracks],
dtype=np.float32)
dtype=np.float)
cost_matrix = np.maximum(0.0, cdist(track_features, det_features,
metric)) # Nomalized features
return cost_matrix

View File

@ -1 +1,5 @@
import os
from . import models, msdatasets, pipelines, trainers
os.environ['SETUPTOOLS_USE_DISTUTILS'] = 'stdlib'

View File

@ -48,15 +48,9 @@ class EasyCVDetectionPipeline(EasyCVPipeline):
labels = []
boxes = []
for output in outputs:
scores_list = output['detection_scores'] if output[
'detection_scores'] is not None else []
classes_list = output['detection_classes'] if output[
'detection_classes'] is not None else []
boxes_list = output['detection_boxes'] if output[
'detection_boxes'] is not None else []
for score, label, box in zip(scores_list, classes_list,
boxes_list):
for score, label, box in zip(output['detection_scores'],
output['detection_classes'],
output['detection_boxes']):
scores.append(score)
labels.append(self.cfg.CLASSES[label])
boxes.append([b for b in box])

View File

@ -36,7 +36,7 @@ class EasyCVSegmentationPipeline(EasyCVPipeline):
legal_indices = ids != len(self.predict_op.CLASSES) # for VOID label
ids = ids[legal_indices]
segms = (semantic_result[None] == ids[:, None, None])
masks = [it.astype(np.int32) for it in segms]
masks = [it.astype(np.int) for it in segms]
labels_txt = np.array(self.predict_op.CLASSES)[ids].tolist()
results = {

View File

@ -515,10 +515,6 @@ CONFIG_TEMPLATE_ZOO = {
'configs/classification/imagenet/swint/imagenet_swin_tiny_patch4_window7_224_jpg.py',
'CLASSIFICATION_M0BILENET':
'configs/classification/imagenet/mobilenet/mobilenetv2.py',
'CLASSIFICATION_INCEPTIONV4':
'configs/classification/imagenet/inception/inceptionv4_b32x8_100e.py',
'CLASSIFICATION_INCEPTIONV3':
'configs/classification/imagenet/inception/inceptionv3_b32x8_100e.py',
# metric learning
'METRICLEARNING':

View File

@ -2,5 +2,5 @@
# GENERATED VERSION FILE
# TIME: Thu Nov 5 14:17:50 2020
__version__ = '0.11.7'
short_version = '0.11.7'
__version__ = '0.11.0'
short_version = '0.11.0'

View File

@ -13,7 +13,6 @@ lmdb
numba
numpy
nuscenes-devkit
onnxruntime
opencv-python
oss2
packaging
@ -24,9 +23,8 @@ pycocotools
pytorch_metric_learning>=0.9.89
rapidfuzz
scikit-image
scikit-learn
seaborn
shapely==1.8.4
sklearn
tensorboard
thop
timm==0.5.4

View File

@ -8,26 +8,15 @@ import unittest
from fnmatch import fnmatch
def get_skip_file(skip_dir, pattern=None):
def gather_test_cases(test_dir, pattern, list_tests):
case_list = []
if skip_dir:
for path in skip_dir:
for dirpath, dirnames, filenames in os.walk(path):
for file in filenames:
if fnmatch(file, pattern):
case_list.append(file)
return case_list
def gather_test_cases(test_dir, pattern, list_tests, skip_dir):
case_list = []
skip_list = get_skip_file(skip_dir, pattern)
for dirpath, dirnames, filenames in os.walk(test_dir):
for file in filenames:
if fnmatch(file, pattern) and file not in skip_list:
if fnmatch(file, pattern):
case_list.append(file)
test_suite = unittest.TestSuite()
for case in case_list:
test_case = unittest.defaultTestLoader.discover(
start_dir=test_dir, pattern=case)
@ -45,8 +34,7 @@ def gather_test_cases(test_dir, pattern, list_tests, skip_dir):
def main(args):
runner = unittest.TextTestRunner()
test_suite = gather_test_cases(
os.path.abspath(args.test_dir), args.pattern, args.list_tests,
args.skip_dir)
os.path.abspath(args.test_dir), args.pattern, args.list_tests)
if not args.list_tests:
result = runner.run(test_suite)
if len(result.failures) > 0 or len(result.errors) > 0:
@ -61,7 +49,5 @@ if __name__ == '__main__':
'--pattern', default='test_*.py', help='test file pattern')
parser.add_argument(
'--test_dir', default='tests', help='directory to be tested')
parser.add_argument(
'--skip_dir', nargs='+', required=False, help='it`s not run testcase')
args = parser.parse_args()
main(args)

View File

@ -116,7 +116,6 @@ class ModelExportTest(unittest.TestCase):
cfg = mmcv_config_fromfile(config_file)
cfg_options = {
'model.backbone.norm_cfg.type': 'SyncBN',
'export.export_type': 'raw'
}
if cfg_options is not None:
cfg.merge_from_dict(cfg_options)
@ -211,27 +210,6 @@ class ModelExportTest(unittest.TestCase):
self.assertTrue(os.path.exists(filename + '.jit'))
def test_export_resnet_onnx(self):
ckpt_path = PRETRAINED_MODEL_RESNET50
easycv_dir = os.path.dirname(easycv.__file__)
if os.path.exists(os.path.join(easycv_dir, 'configs')):
config_dir = os.path.join(easycv_dir, 'configs')
else:
config_dir = os.path.join(os.path.dirname(easycv_dir), 'configs')
config_file = os.path.join(
config_dir,
'classification/imagenet/resnet/imagenet_resnet50_jpg.py')
with tempfile.TemporaryDirectory() as tmpdir:
cfg = mmcv_config_fromfile(config_file)
cfg.export.export_type = 'onnx'
filename = os.path.join(tmpdir, 'imagenet_resnet50')
export(cfg, ckpt_path, filename)
self.assertTrue(os.path.exists(filename + '.onnx'))
if __name__ == '__main__':
unittest.main()

View File

@ -89,8 +89,8 @@ class CocoToolsTest(unittest.TestCase):
def testExportGroundtruthToCOCO(self):
image_ids = ['first', 'second']
groundtruth_boxes = [
np.array([[100, 100, 200, 200]], np.float32),
np.array([[50, 50, 100, 100]], np.float32)
np.array([[100, 100, 200, 200]], np.float),
np.array([[50, 50, 100, 100]], np.float)
]
groundtruth_classes = [
np.array([1], np.int32),
@ -126,12 +126,12 @@ class CocoToolsTest(unittest.TestCase):
def testExportDetectionsToCOCO(self):
image_ids = ['first', 'second']
detections_boxes = [
np.array([[100, 100, 200, 200]], np.float32),
np.array([[50, 50, 100, 100]], np.float32)
np.array([[100, 100, 200, 200]], np.float),
np.array([[50, 50, 100, 100]], np.float)
]
detections_scores = [
np.array([.8], np.float32),
np.array([.7], np.float32)
np.array([.8], np.float),
np.array([.7], np.float)
]
detections_classes = [np.array([1], np.int32), np.array([1], np.int32)]
categories = [{
@ -152,17 +152,7 @@ class CocoToolsTest(unittest.TestCase):
detections_classes,
categories,
output_path=output_path)
self.assertEqual(len(result), len(detections_boxes))
self.assertEqual(len(detections_boxes), len(detections_boxes))
score_list = []
for i in range(len(detections_boxes)):
score = self._detections_list[i].pop('score')
score_list.append(score)
self.assertAlmostEqual(result[i].pop('score'), score)
self.assertDictEqual(result[i], self._detections_list[i])
self.assertListEqual(result, self._detections_list)
with io.open(output_path, 'r') as f:
written_result = f.read()
# The json output should have floats written to 4 digits of precision.
@ -170,10 +160,7 @@ class CocoToolsTest(unittest.TestCase):
re.MULTILINE)
self.assertTrue(matcher.findall(written_result))
written_result = json.loads(written_result)
for i in range(len(result)):
self.assertAlmostEqual(written_result[i].pop('score'),
score_list[i])
self.assertDictEqual(result[i], written_result[i])
self.assertAlmostEqual(result, written_result)
def testExportSegmentsToCOCO(self):
image_ids = ['first', 'second']
@ -189,10 +176,7 @@ class CocoToolsTest(unittest.TestCase):
for i, detection_mask in enumerate(detection_masks):
detection_masks[i] = detection_mask[:, :, :, None]
detection_scores = [
np.array([.8], np.float32),
np.array([.7], np.float32)
]
detection_scores = [np.array([.8], np.float), np.array([.7], np.float)]
detection_classes = [np.array([1], np.int32), np.array([1], np.int32)]
categories = [{
@ -218,12 +202,7 @@ class CocoToolsTest(unittest.TestCase):
written_result = json.loads(written_result)
mask_load = mask.decode([written_result[0]['segmentation']])
self.assertTrue(np.allclose(mask_load, detection_masks[0]))
self.assertEqual(len(result), len(detection_masks))
self.assertEqual(len(written_result), len(detection_masks))
for i in range(len(detection_masks)):
self.assertAlmostEqual(result[i].pop('score'),
written_result[i].pop('score'))
self.assertDictEqual(result[i], written_result[i])
self.assertAlmostEqual(result, written_result)
def testExportKeypointsToCOCO(self):
image_ids = ['first', 'second']
@ -237,8 +216,8 @@ class CocoToolsTest(unittest.TestCase):
]
detection_scores = [
np.array([.8, 0.2], np.float32),
np.array([.7, 0.3], np.float32)
np.array([.8, 0.2], np.float),
np.array([.7, 0.3], np.float)
]
detection_classes = [
np.array([1, 1], np.int32),
@ -269,12 +248,7 @@ class CocoToolsTest(unittest.TestCase):
with io.open(output_path, 'r') as f:
written_result = f.read()
written_result = json.loads(written_result)
self.assertEqual(len(result), 4)
self.assertEqual(len(written_result), 4)
for i in range(4):
self.assertAlmostEqual(result[i].pop('score'),
written_result[i].pop('score'))
self.assertDictEqual(result[i], written_result[i])
self.assertAlmostEqual(result, written_result)
def testSingleImageDetectionBoxesExport(self):
boxes = np.array([[0, 0, 1, 1], [0, 0, .5, .5], [.5, .5, 1, 1]],

View File

@ -1,63 +0,0 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
import copy
import random
import unittest
import numpy as np
import torch
from easycv.models import modelzoo
from easycv.models.backbones import Inception4
class InceptionV3Test(unittest.TestCase):
def setUp(self):
print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
def test_inceptionv3_withfc(self):
with torch.no_grad():
# input data
batch_size = random.randint(10, 30)
a = torch.rand(batch_size, 3, 299, 299).to('cuda')
num_classes = random.randint(10, 1000)
net = Inception4(
aux_logits=True, num_classes=num_classes).to('cuda')
net.init_weights()
net.train()
self.assertTrue(len(list(net(a)[-1].shape)) == 2)
self.assertTrue(len(list(net(a)[0].shape)) == 2)
self.assertTrue(net(a)[-1].size(1) == num_classes)
self.assertTrue(net(a)[-1].size(0) == batch_size)
self.assertTrue(net(a)[0].size(1) == num_classes)
self.assertTrue(net(a)[0].size(0) == batch_size)
def test_inceptionv3_withoutfc(self):
with torch.no_grad():
# input data
batch_size = random.randint(10, 30)
a = torch.rand(batch_size, 3, 299, 299).to('cuda')
net = Inception4(aux_logits=True, num_classes=0).to('cuda')
net.init_weights()
net.eval()
self.assertTrue(net(a)[-1].size(1) == 1536)
self.assertTrue(net(a)[-1].size(0) == batch_size)
def test_inceptionv3_load_modelzoo(self):
with torch.no_grad():
net = Inception4(aux_logits=True, num_classes=1000).to('cuda')
original_weight = net.features[0].conv.weight
original_weight = copy.deepcopy(original_weight.cpu().data.numpy())
net.init_weights()
load_weight = net.features[0].conv.weight.cpu().data.numpy()
self.assertFalse(np.allclose(original_weight, load_weight))
if __name__ == '__main__':
unittest.main()

View File

@ -40,9 +40,9 @@ class YOLOXTest(unittest.TestCase):
}
output = model(imgs, mode='train', **kwargs)
self.assertEqual(output['img_h'].cpu().numpy(),
np.array(640, dtype=np.float32))
np.array(640, dtype=np.float))
self.assertEqual(output['img_w'].cpu().numpy(),
np.array(640, dtype=np.float32))
np.array(640, dtype=np.float))
self.assertEqual(output['total_loss'].shape, torch.Size([]))
self.assertEqual(output['iou_l'].shape, torch.Size([]))
self.assertEqual(output['conf_l'].shape, torch.Size([]))

View File

@ -45,9 +45,9 @@ class YOLOXEDGETest(unittest.TestCase):
}
output = model(imgs, mode='train', **kwargs)
self.assertEqual(output['img_h'].cpu().numpy(),
np.array(640, dtype=np.float32))
np.array(640, dtype=np.float))
self.assertEqual(output['img_w'].cpu().numpy(),
np.array(640, dtype=np.float32))
np.array(640, dtype=np.float))
self.assertEqual(output['total_loss'].shape, torch.Size([]))
self.assertEqual(output['iou_l'].shape, torch.Size([]))
self.assertEqual(output['conf_l'].shape, torch.Size([]))

View File

@ -11,8 +11,7 @@ import torch
from easycv.predictors.classifier import ClassificationPredictor
from easycv.utils.test_util import clean_up, get_tmp_dir
from tests.ut_config import (PRETRAINED_MODEL_RESNET50_WITHOUTHEAD,
IMAGENET_LABEL_TXT, TEST_IMAGES_DIR,
PRETRAINED_MODEL_RESNET50_ONNX_WITHOUTHEAD)
IMAGENET_LABEL_TXT, TEST_IMAGES_DIR)
class ClassificationPredictorTest(unittest.TestCase):
@ -34,17 +33,6 @@ class ClassificationPredictorTest(unittest.TestCase):
self.assertListEqual(results['class_name'], ['"Persian cat",'])
self.assertEqual(len(results['class_probs']), 1000)
def test_onnx_single(self):
checkpoint = PRETRAINED_MODEL_RESNET50_ONNX_WITHOUTHEAD
predict_op = ClassificationPredictor(model_path=checkpoint)
img_path = os.path.join(TEST_IMAGES_DIR, 'catb.jpg')
results = predict_op([img_path])[0]
self.assertListEqual(results['class'], [578])
self.assertListEqual(results['class_name'], ['gown'])
self.assertEqual(len(results['class_probs']), 1000)
def test_batch(self):
checkpoint = PRETRAINED_MODEL_RESNET50_WITHOUTHEAD
config_file = 'configs/classification/imagenet/resnet/imagenet_resnet50_jpg.py'

View File

@ -54,10 +54,10 @@ class PoseTopDownPredictorTest(unittest.TestCase):
assert_array_almost_equal(
result0['bbox'],
np.array([[438.9, 59., 604.8, 511.2, 0.9],
[10.5, 179.6, 101.8, 297.7, 0.9],
[229.6, 114.4, 307.8, 231.4, 0.6],
[229.4, 114.7, 308.5, 296.7, 0.6]],
np.array([[352.3085, 59.00325, 691.4247, 511.15814, 1.],
[10.511196, 177.74883, 101.824326, 299.49966, 1.],
[224.82036, 114.439865, 312.51306, 231.36348, 1.],
[200.71407, 114.716736, 337.17535, 296.6651, 1.]],
dtype=np.float32),
decimal=1)
vis_result = predictor.show_result(img1, result0)
@ -92,10 +92,10 @@ class PoseTopDownPredictorTest(unittest.TestCase):
assert_array_almost_equal(
result1['bbox'][:4],
np.array([[470.6, 214.7, 549.9, 412.1, 0.9],
[71.6, 91., 136.7, 251.4, 0.9],
[159.7, 100.4, 221.9, 269.4, 0.9],
[219.4, 117.3, 281.9, 278.8, 0.9]],
np.array([[436.23096, 214.72766, 584.26013, 412.09985, 1.],
[43.990044, 91.04126, 164.28406, 251.43329, 1.],
[127.44148, 100.38604, 254.219, 269.42273, 1.],
[190.08075, 117.31801, 311.22394, 278.8423, 1.]],
dtype=np.float32),
decimal=1)
vis_result = predictor.show_result(img2, result1)

View File

@ -8,11 +8,13 @@ from modelscope.outputs import OutputKeys
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
from modelscope.utils.cv.image_utils import panoptic_seg_masks_to_image
from modelscope.utils.demo_utils import DemoCompatibilityCheck
from modelscope.utils.test_utils import test_level
from tests.ut_config import BASE_LOCAL_PATH
class EasyCVPanopticSegmentationPipelineTest(unittest.TestCase):
class EasyCVPanopticSegmentationPipelineTest(unittest.TestCase,
DemoCompatibilityCheck):
img_path = os.path.join(
BASE_LOCAL_PATH, 'data/test_images/image_semantic_segmentation.jpg')
@ -30,6 +32,10 @@ class EasyCVPanopticSegmentationPipelineTest(unittest.TestCase):
cv2.imwrite(tmp_save_path, draw_img)
print('print ' + self.model_id + ' success')
@unittest.skipUnless(test_level() >= 0, 'skip test in current test level')
def test_demo_compatibility(self):
self.compatibility_check()
if __name__ == '__main__':
unittest.main()

View File

@ -9,12 +9,14 @@ from modelscope.outputs import OutputKeys
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
from modelscope.utils.cv.image_utils import semantic_seg_masks_to_image
from modelscope.utils.demo_utils import DemoCompatibilityCheck
from modelscope.utils.test_utils import test_level
from PIL import Image
from tests.ut_config import BASE_LOCAL_PATH
class EasyCVSegmentationPipelineTest(unittest.TestCase):
class EasyCVSegmentationPipelineTest(unittest.TestCase,
DemoCompatibilityCheck):
img_path = os.path.join(BASE_LOCAL_PATH,
'data/test_images/image_segmentation.jpg')
@ -80,6 +82,10 @@ class EasyCVSegmentationPipelineTest(unittest.TestCase):
model_id = 'damo/cv_segformer-b5_image_semantic-segmentation_coco-stuff164k'
self._internal_test_(model_id)
@unittest.skipUnless(test_level() >= 0, 'skip test in current test level')
def test_demo_compatibility(self):
self.compatibility_check()
if __name__ == '__main__':
unittest.main()

View File

@ -40,7 +40,6 @@ class EasyCVTrainerTestDetectionDino(unittest.TestCase):
train_dataset=train_dataset,
eval_dataset=eval_dataset,
work_dir=tmp_dir,
use_fp16=True,
cfg_options=cfg_options)
trainer = build_trainer(trainer_name, kwargs)

View File

@ -98,9 +98,7 @@ class ClassificationTrainTest(unittest.TestCase):
(tmp_cfg_file, work_dir, args_str)
logging.info('run command: %s' % cmd)
# run_in_subprocess(cmd) # 管道缓冲区被写满后面的写入请求都hang住了
import subprocess
subprocess.call(cmd, shell=True)
run_in_subprocess(cmd)
output_files = io.listdir(work_dir)
self.assertIn('epoch_1.pth', output_files)

View File

@ -1,138 +0,0 @@
# Copyright (c) Alibaba, Inc. and its affiliates.
import logging
import os
import sys
import unittest
import numpy as np
import onnxruntime
import torch
from easycv.models import build_model
from easycv.utils.checkpoint import load_checkpoint
from easycv.utils.config_tools import mmcv_config_fromfile, rebuild_config
from easycv.utils.test_util import run_in_subprocess
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
logging.basicConfig(level=logging.INFO)
WORK_DIRECTORY = 'work_dir3'
BASIC_EXPORT_CONFIGS = {
'config_file': None,
'checkpoint': 'dummy',
'output_filename': f'{WORK_DIRECTORY}/test_out.pth',
'user_config_params': ['--export.export_type', 'onnx']
}
def build_cmd(export_configs, MODEL_TYPE) -> str:
base_cmd = 'python tools/export.py'
base_cmd += f" {export_configs['config_file']}"
base_cmd += f" {export_configs['checkpoint']}"
base_cmd += f" {export_configs['output_filename']}"
base_cmd += f' --model_type {MODEL_TYPE}'
user_params = ' '.join(export_configs['user_config_params'])
base_cmd += f' --user_config_params {user_params}'
return base_cmd
class ExportTest(unittest.TestCase):
"""In this unittest, we test the onnx export functionality of
some classification/detection models.
"""
def setUp(self):
print(('Testing %s.%s' % (type(self).__name__, self._testMethodName)))
os.makedirs(WORK_DIRECTORY, exist_ok=True)
def tearDown(self):
super().tearDown()
def run_test(self,
CONFIG_FILE,
MODEL_TYPE,
img_size: int = 224,
**override_configs):
configs = BASIC_EXPORT_CONFIGS.copy()
configs['config_file'] = CONFIG_FILE
configs.update(override_configs)
cmd = build_cmd(configs, MODEL_TYPE)
logging.info(f'Export with commands: {cmd}')
run_in_subprocess(cmd)
cfg = mmcv_config_fromfile(configs['config_file'])
cfg = rebuild_config(cfg, configs['user_config_params'])
if hasattr(cfg.model, 'pretrained'):
cfg.model.pretrained = False
torch_model = build_model(cfg.model).eval()
if 'checkpoint' in override_configs:
load_checkpoint(
torch_model,
override_configs['checkpoint'],
strict=False,
logger=logging.getLogger())
session = onnxruntime.InferenceSession(configs['output_filename'] +
'.onnx')
input_tensor = torch.randn((1, 3, img_size, img_size))
torch_output = torch_model(input_tensor, mode='test')['prob']
onnx_output = session.run(
[session.get_outputs()[0].name],
{session.get_inputs()[0].name: np.array(input_tensor)})
if isinstance(onnx_output, list):
onnx_output = onnx_output[0]
onnx_output = torch.tensor(onnx_output)
is_same_shape = torch_output.shape == onnx_output.shape
self.assertTrue(
is_same_shape,
f'The shapes of the two outputs are mismatch, got {torch_output.shape} and {onnx_output.shape}'
)
is_allclose = torch.allclose(torch_output, onnx_output)
torch_out_minmax = f'{float(torch_output.min())}~{float(torch_output.max())}'
onnx_out_minmax = f'{float(onnx_output.min())}~{float(onnx_output.max())}'
info_msg = f'got avg: {float(torch_output.mean())} and {float(onnx_output.mean())},'
info_msg += f' and range: {torch_out_minmax} and {onnx_out_minmax}'
self.assertTrue(
is_allclose,
f'The values between the two outputs are mismatch, {info_msg}')
def test_inceptionv3(self):
CONFIG_FILE = 'configs/classification/imagenet/inception/inceptionv3_b32x8_100e.py'
self.run_test(CONFIG_FILE, 'CLASSIFICATION_INCEPTIONV3', 299)
def test_inceptionv4(self):
CONFIG_FILE = 'configs/classification/imagenet/inception/inceptionv4_b32x8_100e.py'
self.run_test(CONFIG_FILE, 'CLASSIFICATION_INCEPTIONV4', 299)
def test_resnext50(self):
CONFIG_FILE = 'configs/classification/imagenet/resnext/imagenet_resnext50-32x4d_jpg.py'
self.run_test(
CONFIG_FILE,
'CLASSIFICATION_RESNEXT',
checkpoint=
'https://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/EasyCV/modelzoo/classification/resnext/resnext50-32x4d/epoch_100.pth'
)
def test_mobilenetv2(self):
CONFIG_FILE = 'configs/classification/imagenet/mobilenet/mobilenetv2.py'
self.run_test(
CONFIG_FILE,
'CLASSIFICATION_M0BILENET',
checkpoint=
'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/pretrained_models/easycv/mobilenetv2/mobilenet_v2.pth'
)
if __name__ == '__main__':
unittest.main()

View File

@ -13,7 +13,7 @@ from mmcv import Config
from tests.ut_config import (PRETRAINED_MODEL_SEGFORMER,
PRETRAINED_MODEL_YOLOXS_EXPORT, TEST_IMAGES_DIR)
from easycv.file import get_oss_config, io
from easycv.file import io
from easycv.utils.test_util import run_in_subprocess
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
@ -75,32 +75,6 @@ class PredictTest(unittest.TestCase):
model_path = PRETRAINED_MODEL_YOLOXS_EXPORT
self._base_predict(model_type, model_path, dist=True)
def test_predict_oss_path(self):
model_type = 'YoloXPredictor'
model_path = PRETRAINED_MODEL_YOLOXS_EXPORT
os.environ['OSS_CONFIG_FILE'] = '~/.ossutilconfig.unittest'
oss_config = get_oss_config()
ak_id = oss_config['ak_id']
ak_secret = oss_config['ak_secret']
hosts = oss_config['hosts']
hosts = ','.join(_ for _ in hosts)
buckets = oss_config['buckets']
buckets = ','.join(_ for _ in buckets)
input_file = 'oss://pai-vision-data-hz/unittest/local_backup/easycv_nfs/data/test_images/http_image_list.txt'
output_file = tempfile.NamedTemporaryFile('w').name
cmd = f'PYTHONPATH=. python tools/predict.py \
--input_file {input_file} \
--output_file {output_file} \
--model_type {model_type} \
--model_path {model_path} \
--oss_io_config ak_id={ak_id} ak_secret={ak_secret} hosts={hosts} buckets={buckets}'
logging.info('run command: %s' % cmd)
run_in_subprocess(cmd)
io.remove(output_file)
if __name__ == '__main__':
unittest.main()

View File

@ -179,9 +179,6 @@ PRETRAINED_MODEL_RESNET50 = os.path.join(
PRETRAINED_MODEL_RESNET50_WITHOUTHEAD = os.path.join(
BASE_LOCAL_PATH,
'pretrained_models/classification/resnet/resnet50_withhead.pth')
PRETRAINED_MODEL_RESNET50_ONNX_WITHOUTHEAD = os.path.join(
BASE_LOCAL_PATH,
'pretrained_models/classification/resnet/imagenet_resnet50.onnx')
PRETRAINED_MODEL_FACEID = os.path.join(BASE_LOCAL_PATH,
'pretrained_models/faceid')
PRETRAINED_MODEL_YOLOXS_EXPORT = os.path.join(

View File

@ -10,9 +10,8 @@ import logging
import os
import threading
import traceback
import torch
from mmcv import DictAction
from easycv.file import io
try:
import easy_predict
@ -116,12 +115,6 @@ def define_args():
type=str,
choices=[None, 'pytorch'],
help='if assigned pytorch, should be used in gpu environment')
parser.add_argument(
'--oss_io_config',
nargs='+',
action=DictAction,
help='designer needs a oss of config to access the data')
args = parser.parse_args()
if 'LOCAL_RANK' not in os.environ:
os.environ['LOCAL_RANK'] = str(args.local_rank)
@ -262,7 +255,7 @@ def create_default_predictor_kwargs(model_dir):
if config_path:
return {'model_path': model_path, 'config_file': config_path}
else:
return {'model_path': model_path, 'config_file': None}
return {'model_path': model_path}
def create_predictor_kwargs(model_type, model_dir):
@ -295,7 +288,7 @@ def replace_oss_with_local_path(ori_file, dst_file, bucket_prefix,
local_prefix):
bucket_prefix = bucket_prefix.rstrip('/') + '/'
local_prefix = local_prefix.rstrip('/') + '/'
with io.open(ori_file, 'r') as infile:
with open(ori_file, 'r') as infile:
with open(dst_file, 'w') as ofile:
for l in infile:
if l.startswith('oss://'):
@ -308,26 +301,9 @@ def build_and_run_file_io(args):
rank, world_size = get_dist_info()
worker_id = rank
# check oss_config and init oss io
if args.oss_io_config is not None:
io.access_oss(**args.oss_io_config)
# acquire the temporary save path
if args.output_file:
io.makedirs(os.path.dirname(args.output_file))
input_oss_file_new_host = os.path.join(
os.path.dirname(args.output_file),
os.path.basename(args.input_file + '.tmp%d' % worker_id))
replace_oss_with_local_path(args.input_file, input_oss_file_new_host,
args.oss_prefix, args.local_prefix)
else:
io.makedirs(args.output_dir)
input_oss_file_new_host = os.path.join(
args.output_dir,
os.path.basename(args.input_file + '.tmp%d' % worker_id))
replace_oss_with_local_path(args.input_file, input_oss_file_new_host,
args.oss_prefix, args.local_prefix)
input_oss_file_new_host = args.input_file + '.tmp%d' % worker_id
replace_oss_with_local_path(args.input_file, input_oss_file_new_host,
args.oss_prefix, args.local_prefix)
args.input_file = input_oss_file_new_host
num_worker = world_size
print(f'worker num {num_worker}')