Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gpu memory representation functions #557

Merged
merged 17 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ build-docs:
-f docker/$(DOCKER_FILE) \
-t savant-docs:$(SAVANT_VERSION) .

build-tests:
docker buildx build \
--target tests \
--build-arg DEEPSTREAM_VERSION=$(DEEPSTREAM_VERSION) \
--build-arg USER_UID=`id -u` \
--build-arg USER_GID=`id -g` \
-f docker/$(DOCKER_FILE) \
-t savant-tests:$(SAVANT_VERSION) .

build-opencv: opencv-build-amd64 opencv-build-arm64 opencv-cp-amd64 opencv-cp-arm64

opencv-build-amd64:
Expand Down Expand Up @@ -96,6 +105,14 @@ run-docs:
--name savant-docs \
savant-docs:$(SAVANT_VERSION)

run-tests:
docker run -it --rm \
-v `pwd`/savant:$(PROJECT_PATH)/savant \
-v `pwd`/tests:$(PROJECT_PATH)/tests \
--gpus=all \
--name savant-tests \
savant-tests:$(SAVANT_VERSION)

run-dev:
xhost +local:docker
docker run -it --rm --gpus=all \
Expand Down
11 changes: 11 additions & 0 deletions docker/Dockerfile.deepstream
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,14 @@ WORKDIR $PROJECT_PATH/docs

ENTRYPOINT ["make"]
CMD ["clean", "html"]


# Savant test image
FROM base AS tests
COPY requirements/dev.txt requirements/dev.txt
COPY tests /opt/savant/tests

RUN python -m pip install --no-cache-dir -r requirements/dev.txt
RUN pip3 install torch torchvision torchaudio

ENTRYPOINT ["pytest", "-s", "/opt/savant/tests"]
85 changes: 85 additions & 0 deletions docs/source/advanced_topics/11_memory_representation_function.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
Functions for converting image representation
---------------------------------------------

When working with images, there are many ways to represent them as arrays of points. Working with different models you may encounter representation of an image using OpenCV Mat class, PyTorch tensor or CuPy array.

The Savant framework aims to maximize GPU utilization without unnecessary data copying and conversion. To achieve this, Savant provides functions for converting between different image representations. Data exchange is performed with zero-copying between different views, except for some cases of conversion to GpuMat OpenCV.

Conversion to PyTorch Tensor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: python

def as_pytorch(
img: Union[cv2.cuda.GpuMat, cp.ndarray, np.ndarray],
input_format: Optional[str] = None,
output_format: Optional[str] = None,
device: Optional[str] = None,
):

This function allows you to convert an OpenCV or CuPy array into a PyTorch tensor.

- **img** - image in OpenCV format (``cv2.cuda.GpuMat`` for GPU or ``numpy.ndarray`` for CPU) or CuPy array (``cupy.ndarray``).

- **input_format** - input format of image shape. Can be one of the following values:

- ``channels_first`` - the image is represented as a array of shape (channels, height, width).
- ``channels_last`` - the image is represented as a array of shape (height, width, channels).
- ``None`` - the input format is determined automatically based on the type of input array. If the input array is a GpuMat or CuPy, then the format is channels_last.

- **output_format** - Output format of image shape. Can be one of the following values:

- ``channels_first`` - The image is represented as a array of shape (channels, height, width).
- ``channels_last`` - The image is represented as a array of shape (height, width, channels).
- ``None`` - The output format will be channels_last, since pytorch uses tensors in this format.

- **device** - Device on which the resulting tensor will be located. Can be one of the following values: ```cuda`` or ``cpu``. If the device is not specified, then the tensor will be located on the same device as the input array.


Conversion to OpenCV
^^^^^^^^^^^^^^^^^^^^

.. code-block:: python

def as_opencv(
img,
device: Optional[str] = None,
input_format: Optional[str] = None
) -> Union[cv2.cuda.GpuMat, np.ndarray]:

This function allows you to convert an image from PyTorch tensor or CuPy array to OpenCV format. The function always returns an OpenCV array in the `channels_last` format.

- **img** - image in PyTorch tensor format or CuPy array.
- **input_format** - Input format of image shape. Can be one of the following values:

- ``channels_first`` - The image is represented as a array of shape (channels, height, width).
- ``channels_last`` - The image is represented as a array of shape (height, width, channels).
- ``None`` - The input format will be channels_first for pytorch, since pytorch uses tensors in this format, and channels_last for CuPy.

- **device** - Device on which the resulting image will be located. Can be one of the following values: ``cuda`` or ``cpu``. If the device is not specified, then the image will be located on the same device as the input array.

Conversion to CuPy
^^^^^^^^^^^^^^^^^^

.. code-block:: python

def as_cupy(
img,
input_format: Optional[str] = None,
output_format: Optional[str] = None,
) -> cp.ndarray:

This function allows you to convert an image from PyTorch tensor or OpenCV array to CuPy format. The function always returns an CuPy array on the ``cuda`` device.

- **img** - image in PyTorch tensor format or OpenCV array.
- **input_format** - Input format of image shape. Can be one of the following values:

- ``channels_first`` - The image is represented as a array of shape (channels, height, width).
- ``channels_last`` - The image is represented as a array of shape (height, width, channels).
- ``None`` - The input format will be channels_first for pytorch, since pytorch uses tensors in this format, and channels_last for OpenCV.

- **output_format** - Output format of image shape. Can be one of the following values:

- ``channels_first`` - The image is represented as a array of shape (channels, height, width).
- ``channels_last`` - The image is represented as a array of shape (height, width, channels).
- ``None`` - The output format will be channels_last.
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@

# List of modules that will be excluded from import to prevent import errors to stop
# the build process when some external dependencies cannot be imported during the build.
autodoc_mock_imports = ['cv2', 'pyds', 'pysavantboost']
autodoc_mock_imports = ['cv2', 'pyds', 'pysavantboost', 'cupy']

# -- Options for HTML output -------------------------------------------------

Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ Savant supports processing parallelization; it helps to utilize the available re
advanced_topics/9_open_telemetry
advanced_topics/9_input_json_metadata
advanced_topics/10_client_sdk
advanced_topics/11_memory_representation_function.rst

.. toctree::
:maxdepth: 0
Expand Down
4 changes: 4 additions & 0 deletions requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
numpy~=1.22.4
# cupy
cupy-cuda12x; platform_machine=='x86_64'
cupy-cuda11x; platform_machine=='aarch64'

numba~=0.57
scipy~=1.10

Expand Down
2 changes: 1 addition & 1 deletion requirements/dev.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
black~=22.3.0
unify~=0.5
pytest~=7.1.2
pytest~=7.4.3
isort~=5.12.0
Loading