diff --git a/README_zh-CN.md b/README_zh-CN.md
index 5be0f64fb..dcb6da2b4 100644
--- a/README_zh-CN.md
+++ b/README_zh-CN.md
@@ -19,7 +19,7 @@
-[](https://mmdeploy.readthedocs.io/en/latest/)
+[](https://mmdeploy.readthedocs.io/zh_CN/latest/)
[](https://github.com/open-mmlab/mmdeploy/actions)
[](https://codecov.io/gh/open-mmlab/mmdeploy)
[](https://github.com/open-mmlab/mmdeploy/blob/master/LICENSE)
diff --git a/mmdeploy/mmcv/ops/__init__.py b/mmdeploy/mmcv/ops/__init__.py
index b39f518ea..eb905c7f9 100644
--- a/mmdeploy/mmcv/ops/__init__.py
+++ b/mmdeploy/mmcv/ops/__init__.py
@@ -5,8 +5,10 @@ from .nms import * # noqa: F401,F403
from .nms_rotated import * # noqa: F401,F403
from .roi_align import roi_align_default
from .roi_align_rotated import roi_align_rotated_default
+from .transformer import patch_embed__forward__ncnn
__all__ = [
'roi_align_default', 'modulated_deform_conv_default',
- 'deform_conv_openvino', 'roi_align_rotated_default'
+ 'deform_conv_openvino', 'roi_align_rotated_default',
+ 'patch_embed__forward__ncnn'
]
diff --git a/mmdeploy/mmcv/ops/transformer.py b/mmdeploy/mmcv/ops/transformer.py
new file mode 100644
index 000000000..53f7f550b
--- /dev/null
+++ b/mmdeploy/mmcv/ops/transformer.py
@@ -0,0 +1,32 @@
+# Copyright (c) OpenMMLab. All rights reserved.
+from mmdeploy.core import FUNCTION_REWRITER
+from mmdeploy.utils import Backend
+
+
+@FUNCTION_REWRITER.register_rewriter(
+ func_name='mmcv.cnn.bricks.transformer.PatchEmbed.forward',
+ backend=Backend.NCNN.value)
+def patch_embed__forward__ncnn(ctx, self, x):
+ """Rewrite `forward` of PatchEmbed for ncnn backend.
+
+ Args:
+ x (Tensor): Has shape (B, C, H, W). In most case, C is 3.
+
+ Returns:
+ tuple: Contains merged results and its spatial shape.
+
+ - x (Tensor): Has shape (B, out_h * out_w, embed_dims)
+ - out_size (tuple[int]): Spatial shape of x, arrange as
+ (out_h, out_w).
+ """
+
+ if self.adaptive_padding:
+ x = self.adaptive_padding(x)
+
+ x = self.projection(x)
+ x_shape = x.shape
+ out_size = (x_shape[2], x_shape[3])
+ x = x.reshape((x_shape[0], x_shape[1], -1)).transpose(1, 2)
+ if self.norm is not None:
+ x = self.norm(x)
+ return x, out_size
diff --git a/mmdeploy/utils/utils.py b/mmdeploy/utils/utils.py
index 12cc89f77..25ddca56d 100644
--- a/mmdeploy/utils/utils.py
+++ b/mmdeploy/utils/utils.py
@@ -115,7 +115,7 @@ def get_file_path(prefix, candidates) -> str:
Args:
prefix (str): Prefix of the paths.
- cancidates (str): Candidate paths
+ candidates (str): Candidate paths
Returns:
str: file path or '' if not found
"""
diff --git a/tests/test_mmcv/test_mmcv_ops.py b/tests/test_mmcv/test_mmcv_ops.py
index 7e0142e1f..4d41dc2fd 100644
--- a/tests/test_mmcv/test_mmcv_ops.py
+++ b/tests/test_mmcv/test_mmcv_ops.py
@@ -93,3 +93,24 @@ def test_deform_conv_openvino():
model = onnx.load(onnx_file_path)
assert model.graph.node[1].op_type == 'DeformableConv2D'
assert model.graph.node[1].domain == 'org.openvinotoolkit'
+
+
+def test_patch_embed_ncnn():
+ check_backend(Backend.NCNN)
+
+ from mmcv.cnn.bricks.transformer import PatchEmbed
+
+ input = torch.ones((1, 3, 384, 384))
+ patch_cfg = {
+ 'in_channels': 3,
+ 'input_size': 384,
+ 'embed_dims': 768,
+ 'conv_type': 'Conv2d',
+ 'kernel_size': 32,
+ 'stride': 32
+ }
+ wrapped_model = PatchEmbed(**patch_cfg)
+ wrapped_model.eval()
+ with RewriterContext({}, backend='ncnn'), torch.no_grad():
+ _, shape = wrapped_model(input)
+ assert shape[0] == patch_cfg['input_size'] / patch_cfg['stride']
diff --git a/tools/deploy.py b/tools/deploy.py
index 98e2e4d95..a1eda321e 100644
--- a/tools/deploy.py
+++ b/tools/deploy.py
@@ -220,7 +220,9 @@ def main():
from mmdeploy.apis.ncnn import is_available as is_available_ncnn
if not is_available_ncnn():
- logger.error('ncnn support is not available.')
+ logger.error('ncnn support is not available, please make sure \
+ 1) `onnx2ncnn` existed in `PATH` 2) python import ncnn success'
+ )
exit(1)
import mmdeploy.apis.ncnn as ncnn_api