diff --git a/README.md b/README.md index 376305a..870a3e7 100644 --- a/README.md +++ b/README.md @@ -285,6 +285,7 @@ It's important to have a bridge from decord to popular deep learning frameworks - Apache MXNet (Done) - Pytorch (Done) - TensorFlow (Done) +- Paddle (Done) Using bridges for deep learning frameworks are simple, for example, one can set the default tensor output to `mxnet.ndarray`: @@ -297,9 +298,10 @@ print('native output:', type(vr[0]), vr[0].shape) decord.bridge.set_bridge('mxnet') print(type(vr[0], vr[0].shape)) # (240, 426, 3) -# or pytorch and tensorflow(>=2.2.0) +# or pytorch, tensorflow(>=2.2.0) and paddle decord.bridge.set_bridge('torch') decord.bridge.set_bridge('tensorflow') +decord.bridge.set_bridge('paddle') # or back to decord native format decord.bridge.set_bridge('native') ``` diff --git a/python/decord/bridge/__init__.py b/python/decord/bridge/__init__.py index 7684bb1..36b9cbf 100644 --- a/python/decord/bridge/__init__.py +++ b/python/decord/bridge/__init__.py @@ -6,6 +6,7 @@ from .torchdl import to_torch, from_torch from .tf import to_tensorflow, from_tensorflow from .tvm import to_tvm, from_tvm +from .paddle import to_paddle, from_paddle _BRIDGE_TYPES = { 'native': (lambda x: x, lambda x: x), @@ -13,6 +14,7 @@ 'torch': (to_torch, from_torch), 'tensorflow': (to_tensorflow, from_tensorflow), 'tvm': (to_tvm, from_tvm), + 'paddle': (to_paddle, from_paddle), } _CURRENT_BRIDGE = threading.local() @@ -74,3 +76,6 @@ def use_tensorflow(): def use_tvm(): return _BridgeScope('tvm') + +def use_paddle(): + return _BridgeScope('paddle') diff --git a/python/decord/bridge/paddle.py b/python/decord/bridge/paddle.py new file mode 100644 index 0000000..e6c81c6 --- /dev/null +++ b/python/decord/bridge/paddle.py @@ -0,0 +1,34 @@ +"""DECORD Paddle bridge""" +from __future__ import absolute_import + +from .._ffi._ctypes.ndarray import _from_dlpack + +def try_import_paddle(): + """Try import paddle at runtime. + + Returns + ------- + paddle module if found. Raise ImportError otherwise + """ + msg = "paddle is required, for installation guide, please checkout:\n \ + https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/develop/install/pip/linux-pip.html" + try: + return __import__('paddle.utils.dlpack', fromlist=['object']) + except ImportError as e: + if not message: + raise e + raise ImportError(message) + +def to_paddle(decord_arr): + """From decord to paddle. + The tensor will share the memory with the object represented in the dlpack. + Note that each dlpack can only be consumed once.""" + dlpack = try_import_paddle() + return dlpack.from_dlpack(decord_arr.to_dlpack()) + +def from_paddle(tensor): + """From paddle to decord. + The dlpack shares the tensors memory. + Note that each dlpack can only be consumed once.""" + dlpack = try_import_paddle() + return _from_dlpack(dlpack.to_dlpack(tensor)) \ No newline at end of file diff --git a/tests/python/unittests/test_bridges.py b/tests/python/unittests/test_bridges.py index bb18536..99bf2be 100644 --- a/tests/python/unittests/test_bridges.py +++ b/tests/python/unittests/test_bridges.py @@ -59,6 +59,19 @@ def test_tvm_bridge(): except ImportError: print('Skip test tvm bridge as tvm is not found') +def test_paddle_bridge(): + try: + from decord.bridge.paddle import try_import_paddle + import paddle + vr = _get_default_test_video() + with use_paddle(): + frame = vr[0] + assert isinstance(frame, paddle.Tensor), type(frame) + native_frame = bridge_in(frame) + assert isinstance(native_frame, decord.nd.NDArray), type(native_frame) + except ImportError: + print('Skip test paddle bridge as paddle is not found') + def test_threaded_bridge(): # issue #85 from decord import cpu, gpu