diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 185ef70bd..ae8f44bda 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -48,7 +48,7 @@ jobs:
run: |
sudo apt update -y && sudo apt install -y --no-install-recommends \
python3 python3-pip python3-dev python3-distutils doxygen && sudo rm -rf /var/lib/apt/lists/* \
- && python3 -m pip install sphinx-rtd-theme sphinx breathe exhale recommonmark graphviz \
+ && python3 -m pip install sphinx-rtd-theme sphinx breathe recommonmark graphviz \
&& python3 -m pip install numpy==1.24.1 patchelf==0.17.2.1
- if: matrix.language == 'c-cpp'
@@ -92,7 +92,7 @@ jobs:
- if: matrix.language == 'c-cpp' && github.event_name == 'push'
name: Build Docs and Clean up Sphinx Build Directory
run: |
- ./ci/build.sh debug build "-DBUILD_SAMPLES=OFF -DBUILD_TESTS=OFF -DBUILD_DOCS=ON -DBUILD_PYTHON=ON" $*
+ ./ci/build.sh debug build "-DBUILD_SAMPLES=OFF -DBUILD_TESTS=OFF -DBUILD_DOCS=ON -DBUILD_PYTHON=ON -DPYTHON_VERSIONS=3.8" $*
find build/docs/sphinx -name '*.doctree' -delete
find build/docs/sphinx -name '*.map' -delete
find build/docs/sphinx -name '*.pickle' -delete
diff --git a/.gitignore b/.gitignore
index 4b0a6a14c..528b9a558 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@
# ----------------
/build/
/build-*/
+/build_*/
/install/
/cvcuda-installer*/
@@ -47,7 +48,8 @@ ipython_config.py
# Documentation
# -------------
-_exhale_api
+_c_cpp_api
+_cvcuda_api
# Samples
# -------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 841801962..198a070f4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,7 +23,7 @@ endif()
project(cvcuda
LANGUAGES C CXX
- VERSION 0.8.0
+ VERSION 0.9.0
DESCRIPTION "CUDA-accelerated Computer Vision algorithms"
)
diff --git a/README.md b/README.md
index 5a9af904d..fe954e9b7 100644
--- a/README.md
+++ b/README.md
@@ -18,13 +18,13 @@
[](https://opensource.org/licenses/Apache-2.0)
-
+

[](https://developer.nvidia.com/cuda-toolkit-archive)
[](https://gcc.gnu.org/gcc-11/changes.html)
-[](https://www.python.org/)
+[](https://www.python.org/)
[](https://cmake.org/)
CV-CUDA is an open-source project that enables building efficient cloud-scale
@@ -53,13 +53,15 @@ To get a local copy up and running follow these steps.
\** full build, including test module
\*** [samples][CV-CUDA Samples] require driver r535 or later to run and are only officially supported with CUDA 12.
-### Known limitations
+### Known limitations and issues
- For GCC versions lower than 11.0, C++17 support needs to be enabled when compiling CV-CUDA.
- The C++ test module cannot build with gcc<11 (requires specific C++-20 features). With gcc-9 or gcc-10, please build with option `-DBUILD_TESTS=0`
- [CV-CUDA Samples] require driver r535 or later to run and are only officially supported with CUDA 12.
- Only one CUDA version (CUDA 11.x or CUDA 12.x) of CV-CUDA packages (Debian packages, tarballs, Python Wheels) can be installed at a time. Please uninstall all packages from a given CUDA version before installing packages from a different version.
-- Documentation built with older toolchains (doxygen, sphinx, breathe, exhale) may be incomplete. We recommend using Ubuntu 22.04 or later.
+- Documentation built on Ubuntu 20.04 needs an up-to-date version of sphinx (`pip install --upgrade sphinx`) as well as explicitly parsing the system's default python version ` ./ci/build_docs path/to/build -DPYTHON_VERSIONS=""`.
+- Python bindings installed via Debian packages and Python tests fail with Numpy 2.0. We recommend using an older version of Numpy (e.g. 1.26) until we have implemented a fix.
+- The Resize and RandomResizedCrop operators incorrectly interpolate pixel values near the boundary of an image or tensor when using linear and cubic interpolation. This will be fixed in an upcoming release.
### Installation
@@ -87,12 +89,12 @@ Please note that the Python wheels are standalone, they include both the C++/CUD
Install C++/CUDA libraries (cvcuda-lib*) and development headers (cvcuda-dev*) using `apt`:
```shell
-apt install -y ./cvcuda-lib----linux.deb ./cvcuda-dev----linux.deb
+sudo apt install -y ./cvcuda-lib----linux.deb ./cvcuda-dev----linux.deb
```
Install Python bindings (cvcuda-python*) using `apt`:
```shell
-apt install -y ./cvcuda-python----linux.deb
+sudo apt install -y ./cvcuda-python----linux.deb
```
where `` is the desired CUDA version, `` is the desired Python version and `` is the desired architecture.
@@ -122,7 +124,7 @@ Install the dependencies needed to setup up the repository:
On Ubuntu >= 20.04, install the following packages using `apt`:
```shell
-apt install -y git git-lfs
+sudo apt install -y git git-lfs
```
Clone the repository
@@ -145,19 +147,20 @@ Install the dependencies required to build CV-CUDA:
- python3-dev: for python bindings
- libssl-dev: needed by the testsuite (MD5 hashing utilities)
- CUDA toolkit
+- patchelf
On Ubuntu >= 20.04, install the following packages using `apt`:
```shell
-apt install -y g++-11 cmake ninja-build python3-dev libssl-dev
+sudo apt install -y g++-11 cmake ninja-build python3-dev libssl-dev patchelf
```
Any version of the 11.x or 12.x CUDA toolkit should work.
CV-CUDA was tested with 11.7 and 12.2, these versions are thus recommended.
```shell
-apt install -y cuda-11-7
+sudo apt install -y cuda-11-7
# or
-apt install -y cuda-12-2
+sudo apt install -y cuda-12-2
```
Build the project:
@@ -175,18 +178,18 @@ ci/build.sh [release|debug] [output build tree path] [-DBUILD_TESTS=1|0] [-DPYTH
#### 3. Build Documentation
-Known limitation: documentation built with older toolchains (doxygen, sphinx, breathe, exhale) may be incomplete. We recommend using Ubuntu 22.04 or later.
+Known limitation: Documentation built on Ubuntu 20.04 needs an up-to-date version of sphinx (`pip install --upgrade sphinx`) as well as explicitly parsing the system's default python version ` ./ci/build_docs path/to/build -DPYTHON_VERSIONS=""`.
Install the dependencies required to build the documentation:
- doxygen: parse header files for reference documentation
- python3, python3-pip: to install some python packages needed
-- sphinx, breathe, exhale, recommonmark, graphiviz: to render the documentation
+- sphinx, breathe, recommonmark, graphiviz: to render the documentation
- sphinx-rtd-theme: documentation theme used
On Ubuntu, install the following packages using `apt` and `pip`:
```shell
-apt install -y doxygen graphviz python3 python3-pip sphinx
-python3 -m pip install breathe exhale recommonmark graphviz sphinx-rtd-theme
+sudo apt install -y doxygen graphviz python3 python3-pip sphinx
+python3 -m pip install breathe recommonmark graphviz sphinx-rtd-theme
```
Build the documentation:
@@ -204,11 +207,12 @@ For instructions on how to build samples from source and run them, see the [Samp
Install the dependencies required for running the tests:
- python3, python3-pip: to run python bindings tests
- torch: dependencies needed by python bindings tests
+- numpy: known limitation: Python tests fail with numpy 2.0. We recommend using an older version (eg 1.26) until we have implemented a fix.
On Ubuntu >= 20.04, install the following packages using `apt` and `pip`:
```shell
-apt install -y python3 python3-pip
-python3 -m pip install pytest torch
+sudo apt install -y python3 python3-pip
+python3 -m pip install pytest torch numpy==1.26
```
The tests are in `/bin`. You can run the script below to run all tests at once. Here's an example when build tree is created in `build-rel`:
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index 5ad6c8902..5ad4f5973 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -38,39 +38,44 @@ file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR})
list(GET PYTHON_VERSIONS -1 VER)
add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE}
- COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT}
- MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN}
- COMMENT "Generating doxygen xml"
- DEPENDS cvcuda_python${VER})
+ COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT}
+ MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN}
+ COMMENT "Generating doxygen xml"
+ DEPENDS cvcuda_python${VER})
add_custom_target(cvcuda_doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE})
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/sphinx)
-set(EXHALE_SOURCE ${SPHINX_SOURCE}/_exhale_api)
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/sphinx)
set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html)
-set(SPHINX_GROUP_INDEX_FILE ${SPHINX_BUILD}/groupindex.html)
+set(C_CPP_API_RST ${SPHINX_SOURCE}/_c_cpp_api)
+set(PY_CVCUDA_API_RST ${SPHINX_SOURCE}/_python_api/_cvcuda_api)
+
+# Start from clean directory for rst files, otherwise build could be affected due to old files
+file(REMOVE_RECURSE ${C_CPP_API_RST}/*)
+file(REMOVE_RECURSE ${PY_CVCUDA_API_RST}/*)
# Generate rst files for groups from doxygen index.xml
-add_custom_target(cvcuda_groups ALL
- COMMAND python3 ${SPHINX_SOURCE}/generate_groups.py ${EXHALE_SOURCE} ${DOXYGEN_OUTPUT_DIR}/xml
- DEPENDS ${DOXYGEN_INDEX_FILE})
+add_custom_target(cvcuda_groups ALL python3 ${SPHINX_SOURCE}/generate_groups.py ${C_CPP_API_RST} ${DOXYGEN_OUTPUT_DIR}/xml
+ DEPENDS cvcuda_doxygen)
+
+# Generate rst files for python documentation
+add_custom_target(cvcuda_python_docs ALL python3 ${SPHINX_SOURCE}/gen_py_doc_rsts.py ${PY_CVCUDA_API_RST} ${CMAKE_SOURCE_DIR}
+ DEPENDS cvcuda_python${VER})
# Generate Sphinx
add_custom_command(OUTPUT ${SPHINX_INDEX_FILE}
- COMMAND
- ${CMAKE_COMMAND} -E env "SPHINX_PYTHON_SRC=${CMAKE_BINARY_DIR}/lib/python" "DOXYGEN_STRIP_PATH=${CMAKE_CURRENT_SOURCE_DIR}/../src"
- ${SPHINX_EXECUTABLE} -j auto -b html
- # Tell Breathe where to find the Doxygen output
- -Dbreathe_projects.cvcuda=${DOXYGEN_OUTPUT_DIR}/xml
- ${SPHINX_SOURCE} ${SPHINX_BUILD}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- DEPENDS
- ${SPHINX_SOURCE}/index.rst
- ${DOXYGEN_INDEX_FILE}
- cvcuda_groups
- MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py
- COMMENT "Generating documentation with Sphinx")
+ COMMAND ${CMAKE_COMMAND} -E env "SPHINX_PYTHON_SRC=${CMAKE_BINARY_DIR}/lib/python"
+ ${SPHINX_EXECUTABLE} -j auto -b html
+ # Tell Breathe where to find the Doxygen's xml output. Needed to have c/cpp documentation.
+ -Dbreathe_projects.cvcuda=${DOXYGEN_OUTPUT_DIR}/xml
+ ${SPHINX_SOURCE} ${SPHINX_BUILD}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${SPHINX_SOURCE}/index.rst
+ cvcuda_doxygen
+ cvcuda_groups
+ MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py
+ COMMENT "Generating documentation with Sphinx")
add_custom_target(cvcuda_sphinx ALL DEPENDS ${SPHINX_INDEX_FILE})
diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in
index 471474de2..5c9873453 100644
--- a/docs/Doxyfile.in
+++ b/docs/Doxyfile.in
@@ -748,14 +748,14 @@ QUIET = NO
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
-WARNINGS = YES
+WARNINGS = NO
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
-WARN_IF_UNDOCUMENTED = YES
+WARN_IF_UNDOCUMENTED = NO
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
@@ -763,7 +763,7 @@ WARN_IF_UNDOCUMENTED = YES
# markup commands wrongly.
# The default value is: YES.
-WARN_IF_DOC_ERROR = YES
+WARN_IF_DOC_ERROR = NO
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
@@ -2419,7 +2419,7 @@ PLANTUML_INCLUDE_PATH =
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_GRAPH_MAX_NODES = 50
+DOT_GRAPH_MAX_NODES = 128
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
diff --git a/docs/sphinx/_python_api/nvcv/cache.rst b/docs/sphinx/_python_api/nvcv/cache.rst
new file mode 100644
index 000000000..ee48d9df9
--- /dev/null
+++ b/docs/sphinx/_python_api/nvcv/cache.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+Cache
+=====
+
+.. automodule:: nvcv
+ :noindex:
+ :members: cache_size, clear_cache
diff --git a/docs/sphinx/_python_api/nvcv/colorspec.rst b/docs/sphinx/_python_api/nvcv/colorspec.rst
new file mode 100644
index 000000000..7344dac50
--- /dev/null
+++ b/docs/sphinx/_python_api/nvcv/colorspec.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+Color Models
+============
+
+.. automodule:: nvcv
+ :noindex:
+ :members: ColorSpec
diff --git a/docs/sphinx/_python_api/nvcv/format.rst b/docs/sphinx/_python_api/nvcv/format.rst
new file mode 100644
index 000000000..d51f8fd21
--- /dev/null
+++ b/docs/sphinx/_python_api/nvcv/format.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+Image Formats
+=============
+
+.. automodule:: nvcv
+ :noindex:
+ :members: Format
diff --git a/docs/sphinx/_python_api/nvcv/image.rst b/docs/sphinx/_python_api/nvcv/image.rst
new file mode 100644
index 000000000..cd5f3dfa7
--- /dev/null
+++ b/docs/sphinx/_python_api/nvcv/image.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+Image
+=====
+
+.. automodule:: nvcv
+ :noindex:
+ :members: Image, as_image
diff --git a/docs/sphinx/_python_api/nvcv/imagebatch.rst b/docs/sphinx/_python_api/nvcv/imagebatch.rst
new file mode 100644
index 000000000..17054ce96
--- /dev/null
+++ b/docs/sphinx/_python_api/nvcv/imagebatch.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+ImageBatchVarShape
+==================
+
+.. automodule:: nvcv
+ :noindex:
+ :members: ImageBatchVarShape, as_images
diff --git a/docs/sphinx/_python_api/nvcv/recti.rst b/docs/sphinx/_python_api/nvcv/recti.rst
new file mode 100644
index 000000000..e170207e0
--- /dev/null
+++ b/docs/sphinx/_python_api/nvcv/recti.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+RectI
+=====
+
+.. automodule:: nvcv
+ :noindex:
+ :members: RectI
diff --git a/docs/sphinx/_python_api/nvcv/tensor.rst b/docs/sphinx/_python_api/nvcv/tensor.rst
new file mode 100644
index 000000000..fdd3f4915
--- /dev/null
+++ b/docs/sphinx/_python_api/nvcv/tensor.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+Tensor
+======
+
+.. automodule:: nvcv
+ :noindex:
+ :members: Tensor, as_tensor, reshape
diff --git a/docs/sphinx/_python_api/nvcv/tensorbatch.rst b/docs/sphinx/_python_api/nvcv/tensorbatch.rst
new file mode 100644
index 000000000..636442dc5
--- /dev/null
+++ b/docs/sphinx/_python_api/nvcv/tensorbatch.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+TensorBatch
+===========
+
+.. automodule:: nvcv
+ :noindex:
+ :members: TensorBatch, as_tensors
diff --git a/docs/sphinx/_python_api/template.rst b/docs/sphinx/_python_api/template.rst
new file mode 100644
index 000000000..5ca35a3bc
--- /dev/null
+++ b/docs/sphinx/_python_api/template.rst
@@ -0,0 +1,22 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+@OperatorName@
+@=@
+
+.. automodule:: @Module@
+ :noindex:
+ :members: @MemberFunctions@
diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py
index f7fac8e63..9ab82fd6a 100644
--- a/docs/sphinx/conf.py
+++ b/docs/sphinx/conf.py
@@ -26,12 +26,13 @@
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
-
-# -- Project information -----------------------------------------------------
import os
-import sphinx_rtd_theme
import sys
+import sphinx_rtd_theme
+
+# -- Project information -----------------------------------------------------
+
project = "CV-CUDA"
copyright = "2022-2024, NVIDIA."
author = "NVIDIA"
@@ -41,7 +42,6 @@
# set python docstring source path
lib_path = os.getenv("SPHINX_PYTHON_SRC", default=".")
sys.path.insert(0, os.path.abspath(lib_path))
-doxygen_strip_path = os.getenv("DOXYGEN_STRIP_PATH", default=".")
# -- General configuration ---------------------------------------------------
@@ -58,13 +58,18 @@
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "docs/manuals/py/**"]
-# source_parsers = { '.md': 'recommonmark.parser.CommonMarkParser',}
-
extensions = ["recommonmark"]
-
source_suffix = {".rst": "restructuredtext", ".md": "markdown"}
+# Tell sphinx what the primary language being documented is.
+primary_domain = "cpp"
+
+# Tell sphinx what the pygments highlight language should be.
+highlight_language = "cpp"
+
+autodoc_inherit_docstrings = False
+
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
@@ -91,7 +96,6 @@
"titles_only": False,
}
-
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
@@ -114,19 +118,6 @@ def setup(app):
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
-# -- Options for breathe --------------------------------------------------
-
-# Enable the breathe extension
-extensions.append("breathe")
-extensions.append("exhale")
-extensions.append("sphinx.ext.autodoc")
-extensions.append("sphinx.ext.viewcode")
-extensions.append("sphinx.ext.napoleon")
-
-# Set up the default project for breathe extension
-breathe_default_project = "cvcuda"
-
-
# -- Options for sphinx_rtd_theme -----------------------------------------
# Enable the sphinx_rtd_theme extension
@@ -135,63 +126,22 @@ def setup(app):
# Enable the sphinx.ext.todo extension
extensions.append("sphinx.ext.todo")
-# -- Extension configuration -------------------------------------------------
+# -- Extensions --------------------------------------------------
-doxygen_config = """
-EXCLUDE_PATTERNS = *.md *.txt
-ENABLE_PREPROCESSING = YES
-WARN_IF_UNDOCUMENTED = NO
-USE_M
-"""
-
-doxygen_conf_extra = """
-INLINE_SIMPLE_STRUCTS = YES
-TYPEDEF_HIDES_STRUCT = YES
-EXPAND_ONLY_PREDEF = YES
-"""
-
-doxygen_predefined = [
- "NVCV_PUBLIC=",
- "NVCV_API_VERSION_IS(x,y)=0",
- "NVCV_API_VERSION_AT_LEAST(x,y)=1",
- "NVCV_API_VERSION_AT_MOST(x,y)=0",
-]
+# Enable extensions
+extensions.append("breathe")
+extensions.append("sphinx.ext.autodoc")
+extensions.append("sphinx.ext.viewcode")
+extensions.append("sphinx.ext.napoleon")
-doxygen_input_config = """
-"""
-
-doxygen_config = (
- doxygen_input_config
- + """
-EXCLUDE_PATTERNS = *.md *.txt
-ENABLE_PREPROCESSING = YES
-WARN_IF_UNDOCUMENTED = NO
-USE_M
-"""
-)
-
-# Setup the exhale extension
-exhale_args = {
- # These arguments are required
- "containmentFolder": "_exhale_api",
- "rootFileName": "cvcuda_api.rst",
- # Heavily encouraged optional argument (see docs)
- "rootFileTitle": "Library API",
- # Suggested optional arguments
- "createTreeView": True,
- # TIP: if using the sphinx-bootstrap-theme, you need
- # "treeViewIsBootstrap": True,
- "exhaleExecutesDoxygen": False,
- "fullToctreeMaxDepth": 1,
- "minifyTreeView": False,
- "contentsDirectives": False,
- "doxygenStripFromPath": doxygen_strip_path,
+# -- Extension configuration -------------------------------------------------
+# Set up the default project for breathe extension
+breathe_default_project = "cvcuda"
+breathe_doxygen_config_options = {
+ "QUIET": "NO",
+ "WARNINGS": "NO",
+ "WARN_IF_UNDOCUMENTED": "NO",
+ "WARN_IF_DOC_ERROR": "NO",
+ "WARN_NO_PARAMDOC": "NO",
+ "WARN_AS_ERROR": "NO",
}
-
-# Tell sphinx what the primary language being documented is.
-primary_domain = "cpp"
-
-# Tell sphinx what the pygments highlight language should be.
-highlight_language = "cpp"
-
-autodoc_inherit_docstrings = False
diff --git a/docs/sphinx/gen_py_doc_rsts.py b/docs/sphinx/gen_py_doc_rsts.py
new file mode 100644
index 000000000..b48eccba3
--- /dev/null
+++ b/docs/sphinx/gen_py_doc_rsts.py
@@ -0,0 +1,229 @@
+# SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import re
+import sys
+from typing import List, Tuple
+
+
+def exports_enum(s: str) -> bool:
+ return s.lstrip().startswith("py::enum_<")
+
+
+def get_name_of_enum(s: str) -> str:
+ """Name of enum is first string in line"""
+ return re.findall('"([^"]*)"', s)[0]
+
+
+def exports_class(s: str) -> bool:
+ return s.lstrip().startswith("py::class_<")
+
+
+def get_name_of_class_if_documented(s: str) -> Tuple[bool, str]:
+ """
+ If a class has only one strings in line, it has no documentation to be exported.
+ If it has more than one string, it has doc and first string is the title of the class
+ """
+ found_strings = re.findall('"([^"]*)"', s) # get all strings
+ if len(found_strings) > 1:
+ return True, found_strings[0]
+ else:
+ return False, ""
+
+
+def exports_def(s: str) -> bool:
+ return s.lstrip().startswith("m.def(")
+
+
+def get_name_of_def(s: str) -> str:
+ """Name of def is first string in line"""
+ return re.findall('"([^"]*)"', s)[0]
+
+
+def has_exports(file_path, export_calls):
+ for call in export_calls:
+ if call in open(file_path).read():
+ export_calls.remove(call)
+ return True
+ return False
+
+
+def create_rst_text(template_file: str, name: str, module: str, members: str) -> str:
+ with open(template_file, "r") as f:
+ rst_text = f.read()
+ rst_text = rst_text.replace("@OperatorName@", name)
+ rst_text = rst_text.replace("@=@", "=" * len(name))
+ rst_text = rst_text.replace("@Module@", module)
+ rst_text = rst_text.replace("@MemberFunctions@", members)
+ return rst_text
+
+
+def create_cvcuda_operator_rst_files(
+ cvcuda_path: str, outdir: str, python_cvcuda_root: str, export_calls: List[str]
+) -> None:
+ # search for template rst file
+ template_rst_file_path = os.path.join(
+ cvcuda_path, "docs", "sphinx", "_python_api", "template.rst"
+ )
+ if not os.path.isfile(template_rst_file_path):
+ raise FileNotFoundError(f"File {template_rst_file_path} not found")
+
+ # iterate through all files
+ for i in sorted(os.listdir(python_cvcuda_root)):
+ op_file_path = os.path.join(python_cvcuda_root, i)
+ # Only work on .cpp files that export operators
+ if (
+ os.path.isfile(op_file_path)
+ and i.endswith(".cpp")
+ and i != "Main.cpp"
+ and has_exports(op_file_path, export_calls)
+ ):
+
+ # Get operator name form .cpp file: remove prefix "Op" and file type
+ operator_name = os.path.splitext(i)[0]
+ operator_name = operator_name[len("Op") :] # noqa: E203
+
+ # Look for functions to add to documentation
+ # search for all lines that start with "m.def(" (stripping leading white spaces)
+ # then pick first string of that line, this is the name of the python function to be exported
+ exports = set()
+ with open(op_file_path, "r") as fp:
+ for line in fp:
+ if exports_def(line):
+ exports.add(get_name_of_def(line))
+ if len(exports) == 0:
+ raise RuntimeError(f"No exports found in file {op_file_path}")
+ exports_str = ", ".join(exports)
+
+ # Create text to put into rst file - starting from a template
+ rst_text = create_rst_text(
+ template_rst_file_path, operator_name, "cvcuda", exports_str
+ )
+
+ # Write rst file: outdir/_op_.rst
+ outfile = os.path.join(outdir, f"_op_{operator_name.lower()}.rst")
+ with open(outfile, "w") as f:
+ f.write(rst_text)
+ return
+
+
+def create_cvcuda_non_operator_rst_files(
+ cvcuda_path: str, outdir: str, python_cvcuda_root: str, export_calls: List[str]
+) -> None:
+ # search for template rst file
+ template_rst_file_path = os.path.join(
+ cvcuda_path, "docs", "sphinx", "_python_api", "template.rst"
+ )
+ if not os.path.isfile(template_rst_file_path):
+ raise FileNotFoundError(f"File {template_rst_file_path} not found")
+
+ for i in sorted(os.listdir(python_cvcuda_root)):
+ nonop_file_path = os.path.join(python_cvcuda_root, i)
+ # Only work on .cpp files that something different than operators
+ if (
+ os.path.isfile(nonop_file_path)
+ and i.endswith(".cpp")
+ and i != "Main.cpp"
+ and has_exports(nonop_file_path, export_calls)
+ ):
+ # Look for functions to add to documentation
+ # Search for all lines that start with "py::enum_<" or "py::class_<"
+ with open(nonop_file_path, "r") as fp:
+ for line in fp:
+ if exports_enum(line):
+ export = get_name_of_enum(line)
+ elif exports_class(line):
+ has_doc, name = get_name_of_class_if_documented(line)
+ if has_doc:
+ export = name
+ else:
+ continue
+ else:
+ continue
+
+ # Create text to put into rst file - starting from a template
+ rst_text = create_rst_text(
+ template_rst_file_path, export, "cvcuda", export
+ )
+
+ # Write rst file: outdir/_aux_.rst
+ outfile = os.path.join(outdir, f"_aux_{export.lower()}.rst")
+ with open(outfile, "w") as f:
+ f.write(rst_text)
+ return
+
+
+def export_found(s: str) -> bool:
+ return s.lstrip().startswith("Export")
+
+
+def get_export_fun_name(s: str) -> str:
+ return s.lstrip().split("(", 1)[0]
+
+
+def exporting_nonops(s: str) -> bool:
+ """Everything after that command exports auxiliary operator entities
+ (non-operators)"""
+ return s.lstrip().startswith("// doctag: Non-Operators")
+
+
+def exporting_ops(s: str) -> bool:
+ """Everything after that command exports operators"""
+ return s.lstrip().startswith("// doctag: Operators")
+
+
+def get_exported_cvcuda(path_to_main: str):
+ export_nonop = [] # list for non operators
+ export_op = [] # list for operators
+ exports = None
+ with open(path_to_main, "r") as fp:
+ for line in fp:
+ if export_found(line):
+ # remove everything after first "("
+ name = get_export_fun_name(line)
+ try:
+ exports.append(name)
+ except AttributeError:
+ print(
+ "No comment '// doctag: Non-Operators' or '// doctag: Operators' was found in "
+ f"{path_to_main} prior to 'Export*(m);'-routines."
+ )
+ sys.exit()
+ elif exporting_nonops(line):
+ exports = export_nonop
+ elif exporting_ops(line):
+ exports = export_op
+ assert len(export_nonop) > 0 and len(export_op) > 0
+ return export_nonop, export_op
+
+
+def generate_py_doc_rsts_cvcuda(cvcuda_path: str, outdir: str):
+ python_cvcuda_root = os.path.join(cvcuda_path, "python", "mod_cvcuda")
+ export_nonop, export_op = get_exported_cvcuda(
+ os.path.join(python_cvcuda_root, "Main.cpp")
+ )
+ create_cvcuda_operator_rst_files(cvcuda_path, outdir, python_cvcuda_root, export_op)
+ create_cvcuda_non_operator_rst_files(
+ cvcuda_path, outdir, python_cvcuda_root, export_nonop
+ )
+ return
+
+
+if __name__ == "__main__":
+ outdir = sys.argv[1] # path/to/cvcuda/docs/sphinx/_python_api/_cvcuda_api
+ cvcuda_path = sys.argv[2] # path/to/cvcuda
+ os.makedirs(outdir, exist_ok=True)
+ generate_py_doc_rsts_cvcuda(cvcuda_path, outdir)
diff --git a/docs/sphinx/generate_groups.py b/docs/sphinx/generate_groups.py
index b269c0492..8ab19ba2b 100644
--- a/docs/sphinx/generate_groups.py
+++ b/docs/sphinx/generate_groups.py
@@ -13,15 +13,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from pathlib import Path
-import xml.etree.ElementTree as ET
import os
import sys
+import xml.etree.ElementTree as ET
+from pathlib import Path
outdir = Path(sys.argv[1])
-if not os.path.exists(outdir):
- os.makedirs(outdir)
+os.makedirs(outdir, exist_ok=True)
xmlRoot = sys.argv[2]
diff --git a/docs/sphinx/index.rst b/docs/sphinx/index.rst
index ceeb3265e..3817f1bfd 100644
--- a/docs/sphinx/index.rst
+++ b/docs/sphinx/index.rst
@@ -17,7 +17,7 @@
.. _cvcuda_doc_system:
CV-CUDA
-============================
+=======
NVIDIA CV-CUDA™ is an open-source project for building cloud-scale `Artificial Intelligence (AI) imaging and Computer Vision (CV) `_ applications. It uses graphics processing unit (GPU) acceleration to help developers build highly efficient pre- and post-processing pipelines. It can improve throughput by more than 10x while lowering cloud computing costs.
@@ -36,7 +36,7 @@ CV-CUDA includes:
CV-CUDA Pre- and Post-Processing Operators
-------------------
+------------------------------------------
CV-CUDA offers a comprehensive collection of Computer Vision and Image Processing operators, listed below.
@@ -47,20 +47,20 @@ CV-CUDA offers a comprehensive collection of Computer Vision and Image Processin
Where Are the Release Notes?
-------------------
+----------------------------
CV-CUDA release notes can be found `here `_.
Where Can I Get Help?
-------------------
+---------------------
An awesome product requires excellent support.
File requests for enhancements and bug reports `here `_.
What Other Computer Vision Products Does NVIDIA Offer?
-------------------
+------------------------------------------------------
NVIDIA offers a number of products for accelerating computer vision and image processing applications. In addition to CV-CUDA, some of the others include:
@@ -73,7 +73,7 @@ If you want to learn more about what computer vision solutions are available, re
Notice
---------------------
+------
The information provided in this specification is believed to be accurate and reliable as of the date provided. However, NVIDIA Corporation (“NVIDIA”) does not give any representations or warranties, expressed or implied, as to the accuracy or completeness of such information. NVIDIA shall have no liability for the consequences or use of such information or for any infringement of patents or other rights of third parties that may result from its use. This publication supersedes and replaces all other specifications for the product that may have been previously supplied.
NVIDIA reserves the right to make corrections, modifications, enhancements, improvements, and other changes to this specification, at any time and/or to discontinue any product or service without notice. Customer should obtain the latest relevant specification before placing orders and should verify that such information is current and complete.
@@ -90,13 +90,13 @@ ALL NVIDIA DESIGN SPECIFICATIONS, REFERENCE BOARDS, FILES, DRAWINGS, DIAGNOSTICS
Trademarks
---------------------
+----------
NVIDIA, the NVIDIA logo, NVIDIA CV-CUDA, and NVIDIA TensorRT are trademarks and/or registered trademarks of NVIDIA Corporation in the U.S. and other countries. Other company and product names may be trademarks of the respective companies with which they are associated.
Copyright
---------------------
+---------
© 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
@@ -117,13 +117,13 @@ Copyright
C Modules
C++ Modules
Python Modules
- Index <_exhale_api/cvcuda_api>
.. toctree::
:caption: Release Notes
:maxdepth: 1
:hidden:
+ v0.9.0-beta
v0.8.0-beta
v0.7.0-beta
v0.6.0-beta
diff --git a/docs/sphinx/installation.rst b/docs/sphinx/installation.rst
index f1969c8ed..c6566a662 100644
--- a/docs/sphinx/installation.rst
+++ b/docs/sphinx/installation.rst
@@ -38,38 +38,38 @@ You can download the CV-CUDA tar, deb or wheel packages from `the asset section
Unzip the cvcuda runtime package: ::
- tar -xvf cvcuda-lib-x.x.x-cuda11-x86_64-linux.tar.xz
+ tar -xvf cvcuda-lib----linux.tar.xz
Unzip the cvcuda developer package: ::
- tar -xvf cvcuda-dev-x.x.x-cuda11-x86_64-linux.tar.xz
+ tar -xvf cvcuda-dev----linux.tar.xz
Unzip the cvcuda python package: ::
- tar -xvf cvcuda-python3.*-x.x.x-cuda11-x86_64-linux.tar.xz
+ tar -xvf cvcuda-python----linux.tar.xz
[Optional] Unzip the tests. ::
- tar -xvf cvcuda-tests-cuda11-x86_64-linux.tar.xz
+ tar -xvf cvcuda-tests----linux.tar.xz
* Debian Installation
Install the runtime library. ::
- dpkg -i cvcuda-lib-x.x.x-cuda11-x86_64-linux.deb
+ sudo apt install -y ./cvcuda-lib----linux.deb
Install the developer library. ::
- dpkg -i cvcuda-dev-x.x.x-cuda11-x86_64-linux.deb
+ sudo apt install -y ./cvcuda-dev----linux.deb
Install the python bindings ::
- dpkg -i cvcuda-python3.*-x.x.x-cuda11-x86_64-linux.deb
+ sudo apt install -y ./cvcuda-python----linux.deb
[Optional] Install the tests. ::
- sudo dpkg -i cvcuda-tests-x.x.x-cuda11-x86_64-linux.deb
+ sudo apt install -y ./cvcuda-tests----linux.deb
* Python Wheel File Installation
diff --git a/docs/sphinx/modules/c_algos.rst b/docs/sphinx/modules/c_algos.rst
index 7cb81e190..81392c4ef 100644
--- a/docs/sphinx/modules/c_algos.rst
+++ b/docs/sphinx/modules/c_algos.rst
@@ -22,4 +22,4 @@ CV-CUDA Algorithms
.. toctree::
:glob:
- ../_exhale_api/group__NVCV__C__ALGORITHM__*
+ ../_c_cpp_api/group__NVCV__C__ALGORITHM__*
diff --git a/docs/sphinx/modules/c_core.rst b/docs/sphinx/modules/c_core.rst
index 09b8e483b..d74af3281 100644
--- a/docs/sphinx/modules/c_core.rst
+++ b/docs/sphinx/modules/c_core.rst
@@ -22,4 +22,4 @@ Core components and related functions.
.. toctree::
:glob:
- ../_exhale_api/group__NVCV__C__CORE__*
+ ../_c_cpp_api/group__NVCV__C__CORE__*
diff --git a/docs/sphinx/modules/c_status.rst b/docs/sphinx/modules/c_status.rst
index 4f06a241d..0696ccab5 100644
--- a/docs/sphinx/modules/c_status.rst
+++ b/docs/sphinx/modules/c_status.rst
@@ -20,4 +20,4 @@ Status
.. toctree::
:glob:
- ../_exhale_api/group__NVCV__C__API_STATUS*
+ ../_c_cpp_api/group__NVCV__C__API_STATUS*
diff --git a/docs/sphinx/modules/c_utils.rst b/docs/sphinx/modules/c_utils.rst
index 3a1bee3dd..07d51cefb 100644
--- a/docs/sphinx/modules/c_utils.rst
+++ b/docs/sphinx/modules/c_utils.rst
@@ -22,4 +22,4 @@ Utility components for CV-CUDA.
.. toctree::
:glob:
- ../_exhale_api/group__NVCV__C__UTIL_*
+ ../_c_cpp_api/group__NVCV__C__UTIL_*
diff --git a/docs/sphinx/modules/cpp_algos.rst b/docs/sphinx/modules/cpp_algos.rst
index 04aa9a7c0..83255b27d 100644
--- a/docs/sphinx/modules/cpp_algos.rst
+++ b/docs/sphinx/modules/cpp_algos.rst
@@ -22,4 +22,4 @@ CV-CUDA Algorithms
.. toctree::
:glob:
- ../_exhale_api/group__NVCV__C__ALGORITHM__*
+ ../_c_cpp_api/group__NVCV__C__ALGORITHM__*
diff --git a/docs/sphinx/modules/cpp_core.rst b/docs/sphinx/modules/cpp_core.rst
index f716bd0d5..23ea8ce5b 100644
--- a/docs/sphinx/modules/cpp_core.rst
+++ b/docs/sphinx/modules/cpp_core.rst
@@ -22,4 +22,4 @@ Core components and related functions.
.. toctree::
:glob:
- ../_exhale_api/group__NVCV__CPP__CORE_*
+ ../_c_cpp_api/group__NVCV__CPP__CORE_*
diff --git a/docs/sphinx/modules/cpp_cudatools.rst b/docs/sphinx/modules/cpp_cudatools.rst
index 7fadac27a..0d08d11b6 100644
--- a/docs/sphinx/modules/cpp_cudatools.rst
+++ b/docs/sphinx/modules/cpp_cudatools.rst
@@ -22,4 +22,4 @@ CUDA Tools
.. toctree::
:glob:
- ../_exhale_api/group__NVCV__CPP__CUDATOOLS_*
+ ../_c_cpp_api/group__NVCV__CPP__CUDATOOLS_*
diff --git a/docs/sphinx/modules/cpp_modules.rst b/docs/sphinx/modules/cpp_modules.rst
index 9662c2516..7df402929 100644
--- a/docs/sphinx/modules/cpp_modules.rst
+++ b/docs/sphinx/modules/cpp_modules.rst
@@ -15,7 +15,7 @@
# limitations under the License.
C++ API
-=====
+=======
.. toctree::
diff --git a/docs/sphinx/modules/cpp_utils.rst b/docs/sphinx/modules/cpp_utils.rst
index 29d10dddf..fff1ffde8 100644
--- a/docs/sphinx/modules/cpp_utils.rst
+++ b/docs/sphinx/modules/cpp_utils.rst
@@ -22,4 +22,4 @@ Utility components for CV-CUDA.
.. toctree::
:glob:
- ../_exhale_api/group__NVCV__CPP__UTIL_*
+ ../_c_cpp_api/group__NVCV__CPP__UTIL_*
diff --git a/docs/sphinx/modules/python_algos.rst b/docs/sphinx/modules/python_algos.rst
new file mode 100644
index 000000000..50983eacb
--- /dev/null
+++ b/docs/sphinx/modules/python_algos.rst
@@ -0,0 +1,26 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+ALGORITHMS
+==========
+
+Algorithms for the NVIDIA® CV-CUDA library.
+
+.. toctree::
+ :glob:
+
+ ../_python_api/_cvcuda_api/_op_*
+ ../_python_api/_cvcuda_api/_aux_*
diff --git a/docs/sphinx/modules/python_core.rst b/docs/sphinx/modules/python_core.rst
new file mode 100644
index 000000000..98279fe88
--- /dev/null
+++ b/docs/sphinx/modules/python_core.rst
@@ -0,0 +1,31 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+Core
+====
+
+Core components and related functions for the NVIDIA® NVCV library.
+
+.. toctree::
+
+ Cache <../_python_api/nvcv/cache>
+ Color Models <../_python_api/nvcv/colorspec>
+ Image Formats <../_python_api/nvcv/format>
+ Rect <../_python_api/nvcv/recti>
+ Image <../_python_api/nvcv/image>
+ ImageBatchVarShape <../_python_api/nvcv/imagebatch>
+ Tensor <../_python_api/nvcv/tensor>
+ TensorBatchVarShape <../_python_api/nvcv/tensorbatch>
diff --git a/docs/sphinx/modules/python_modules.rst b/docs/sphinx/modules/python_modules.rst
index 4179ac66c..bf20edd91 100644
--- a/docs/sphinx/modules/python_modules.rst
+++ b/docs/sphinx/modules/python_modules.rst
@@ -18,9 +18,8 @@ Python API
==========
.. toctree::
- :caption: Python API
- :maxdepth: 2
- :hidden:
+ :caption: Python API
+ :maxdepth: 3
-.. automodule:: cvcuda
- :members:
+ Core
+ Algorithms
diff --git a/docs/sphinx/prerequisites.rst b/docs/sphinx/prerequisites.rst
index 0aa105faa..540bef62e 100644
--- a/docs/sphinx/prerequisites.rst
+++ b/docs/sphinx/prerequisites.rst
@@ -35,5 +35,5 @@ Python Samples' Dependencies:
* Torchvision
* torchnvjpeg (https://github.com/itsliupeng/torchnvjpeg)
-Refer to the :ref:`Installation` docs for the sample installation guide using *.deb or .tar installers.
+Refer to the :ref:`Installation` docs for the sample installation guide using \*.deb or .tar installers.
Refer to the sample README for instructions to compile samples from the source.
diff --git a/docs/sphinx/relnotes/v0.1.0-prealpha.rst b/docs/sphinx/relnotes/v0.1.0-prealpha.rst
index ddb876c0e..c7b75d22e 100644
--- a/docs/sphinx/relnotes/v0.1.0-prealpha.rst
+++ b/docs/sphinx/relnotes/v0.1.0-prealpha.rst
@@ -17,7 +17,7 @@
.. _v0.1.0-prealpha:
v0.1.0-preAlpha
-========
+===============
CV-CUDA-0.1.0 is the first release of CV-CUDA. This release is for evaluation purposes only.
diff --git a/docs/sphinx/relnotes/v0.2.0-alpha.rst b/docs/sphinx/relnotes/v0.2.0-alpha.rst
index b6ef95ade..d9bef9512 100644
--- a/docs/sphinx/relnotes/v0.2.0-alpha.rst
+++ b/docs/sphinx/relnotes/v0.2.0-alpha.rst
@@ -17,7 +17,7 @@
.. _v0.2.0-alpha:
v0.2.0-alpha
-========
+============
CV-CUDA 0.2.0 is the first open-source release of the project.
@@ -61,7 +61,7 @@ Refer to documentation of the sample applications for dependencies.
Known Issues/Limitations
-------------
+------------------------
* Performance optimization of variable shape versions of the operators will be addressed in the next release.
* Improvements to APIs of some operators are expected in the next release.
* Morphology operator - performance will be optimized in the next release
diff --git a/docs/sphinx/relnotes/v0.2.1-alpha.rst b/docs/sphinx/relnotes/v0.2.1-alpha.rst
index 65d5b8861..4455e9237 100644
--- a/docs/sphinx/relnotes/v0.2.1-alpha.rst
+++ b/docs/sphinx/relnotes/v0.2.1-alpha.rst
@@ -17,7 +17,7 @@
.. _v0.2.1-alpha:
v0.2.1-alpha
-=======
+============
General
-------
diff --git a/docs/sphinx/relnotes/v0.3.0-beta.rst b/docs/sphinx/relnotes/v0.3.0-beta.rst
index 6473da539..5c7d784c9 100644
--- a/docs/sphinx/relnotes/v0.3.0-beta.rst
+++ b/docs/sphinx/relnotes/v0.3.0-beta.rst
@@ -17,7 +17,7 @@
.. _v0.3.0-beta:
v0.3.0-beta
-====
+===========
CV-CUDA 0.3.0 is the next open-source release of the project.
@@ -58,7 +58,7 @@ Refer to documentation of the sample applications for dependencies.
Known Issues/Limitations
-------------
+------------------------
* Open compilation issue with CUDA Toolkit 11.2 + GCC 10.3
diff --git a/docs/sphinx/relnotes/v0.3.1-beta.rst b/docs/sphinx/relnotes/v0.3.1-beta.rst
index c04a3d1f7..24058d6d7 100644
--- a/docs/sphinx/relnotes/v0.3.1-beta.rst
+++ b/docs/sphinx/relnotes/v0.3.1-beta.rst
@@ -17,7 +17,7 @@
.. _v0.3.1-beta:
0.3.1-beta
-======
+==========
The v0.3.1 release provides several bug fixes along with documentation updates and performance improvements.
diff --git a/docs/sphinx/relnotes/v0.4.0-beta.rst b/docs/sphinx/relnotes/v0.4.0-beta.rst
index 0f38b3138..1a0f4eed1 100644
--- a/docs/sphinx/relnotes/v0.4.0-beta.rst
+++ b/docs/sphinx/relnotes/v0.4.0-beta.rst
@@ -17,7 +17,7 @@
.. _v0.4.0-beta:
v0.4.0-beta
-======
+===========
CV-CUDA 0.4.0 is a major release of the library providing multiple new operators, Jetson Orin support, and updated API documentation.
diff --git a/docs/sphinx/relnotes/v0.5.0-beta.rst b/docs/sphinx/relnotes/v0.5.0-beta.rst
index a15c1b98b..57abe2f20 100644
--- a/docs/sphinx/relnotes/v0.5.0-beta.rst
+++ b/docs/sphinx/relnotes/v0.5.0-beta.rst
@@ -17,7 +17,7 @@
.. _v0.5.0-beta:
v0.5.0-beta
-======
+===========
CV-CUDA 0.5.0 is a comprehensive update introducing new security, compliance, and performance enhancements, alongside bug fixes and new features.
diff --git a/docs/sphinx/relnotes/v0.6.0-beta.rst b/docs/sphinx/relnotes/v0.6.0-beta.rst
index c199fb2bd..93731f881 100644
--- a/docs/sphinx/relnotes/v0.6.0-beta.rst
+++ b/docs/sphinx/relnotes/v0.6.0-beta.rst
@@ -17,7 +17,7 @@
.. _v0.6.0-beta:
v0.6.0-beta
-======
+===========
CV-CUDA 0.6.0 is a comprehensive update introducing new packaging and documentation enhancements, along with bug fixes and new features.
diff --git a/docs/sphinx/relnotes/v0.7.0-beta.rst b/docs/sphinx/relnotes/v0.7.0-beta.rst
index 196d236b4..4a155fad2 100644
--- a/docs/sphinx/relnotes/v0.7.0-beta.rst
+++ b/docs/sphinx/relnotes/v0.7.0-beta.rst
@@ -17,7 +17,7 @@
.. _v0.7.0-beta:
v0.7.0-beta
-======
+===========
CV-CUDA v0.7.0 introduces performance and support enhancements, along with bug fixes and new features.
diff --git a/docs/sphinx/relnotes/v0.8.0-beta.rst b/docs/sphinx/relnotes/v0.8.0-beta.rst
index 59e97fab6..4a5c3fb57 100644
--- a/docs/sphinx/relnotes/v0.8.0-beta.rst
+++ b/docs/sphinx/relnotes/v0.8.0-beta.rst
@@ -17,7 +17,7 @@
.. _v0.8.0-beta:
v0.8.0-beta
-======
+===========
Release Highlights
------------------
diff --git a/docs/sphinx/relnotes/v0.9.0-beta.rst b/docs/sphinx/relnotes/v0.9.0-beta.rst
new file mode 100644
index 000000000..dbc18e95c
--- /dev/null
+++ b/docs/sphinx/relnotes/v0.9.0-beta.rst
@@ -0,0 +1,68 @@
+..
+ # SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ # SPDX-License-Identifier: Apache-2.0
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+ # You may obtain a copy of the License at
+ #
+ # http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing, software
+ # distributed under the License is distributed on an "AS IS" BASIS,
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+
+.. _v0.9.0-beta:
+
+v0.9.0-beta
+===========
+
+Release Highlights
+------------------
+
+CV-CUDA v0.9.0 includes the following changes:
+
+* **New Features**:
+
+ * Improved Resize performance (up to 4x for u8 inputs, up to 3x for RGB8)
+ * Improved performance of cubic interpolation, eg in Rotate, WarpAffine and WarpPerspective (up to 2x faster)
+ * Added optional scaling to ResizeCropConvertReformat fused operator
+ * Improved structure of Python documentation and optimized its generation (>5min to <30s) by removing the Exhale index
+ * Added 64bit stride support to various operators
+
+ * limited to 32bit strides to avoid performance regressions: AdaptiveThreshold, AdvCvtColor, AverageBlur, BilateralFilter, BrightnessContrast, ColorTwist, BoxBlur, CenterCrop, ConvertTo, CopyMakeBorder, CustomCrop, GaussianNoise, Gaussian, Flip, HistogramEq, JointBilateralFilter, Laplacian, Morphology, Normalize, RandomResizedCrop, Reformat, Remap, Resize, Rotate, SIFT, WarpAffine, WarpPerspective
+
+* **Bug Fixes**:
+
+ * Added exception handling on CApi in Python: now forward C/C++exceptions to Python
+ * Fixed coordinate rounding bug in Resize operator with nearest neighbor interpolation
+
+Compatibility and Known Limitations
+-----------------------------------
+
+ * Documentation built on Ubuntu 20.04 needs an up-to-date version of sphinx (`pip install --upgrade sphinx`) as well as explicitly parsing the system's default python version `./ci/build_docs path/to/build -DPYTHON_VERSIONS=""`.
+ * Python bindings installed via Debian packages and Python tests fail with Numpy 2.0. We recommend using an older version of Numpy (e.g. 1.26) until we have implemented a fix.
+ * The Resize and RandomResizedCrop operators incorrectly interpolate pixel values near the boundary of an image or tensor when using linear and cubic interpolation. This will be fixed in an upcoming release.
+
+
+See main README on `CV-CUDA GitHub `_.
+
+License
+-------
+
+CV-CUDA is licensed under the `Apache 2.0 `_ license.
+
+Resources
+---------
+
+1. `CV-CUDA GitHub `_
+2. `CV-CUDA Increasing Throughput and Reducing Costs for AI-Based Computer Vision with CV-CUDA `_
+3. `NVIDIA Announces Microsoft, Tencent, Baidu Adopting CV-CUDA for Computer Vision AI `_
+4. `CV-CUDA helps Tencent Cloud audio and video PaaS platform achieve full-process GPU acceleration for video enhancement AI `_
+
+Acknowledgements
+----------------
+
+CV-CUDA is developed jointly by NVIDIA and the ByteDance Machine Learning team.
diff --git a/docs/sphinx/samples/cpp_samples/cropresize.rst b/docs/sphinx/samples/cpp_samples/cropresize.rst
index 671733dae..0e10f8d88 100644
--- a/docs/sphinx/samples/cpp_samples/cropresize.rst
+++ b/docs/sphinx/samples/cpp_samples/cropresize.rst
@@ -62,7 +62,7 @@ The Tensor Buffer is then wrapped to create a Tensor Object for which we will ca
We will use NvJpeg library to decode the images into the required color format and create a buffer on the device.
-.. literalinclude:: ../../../samples/cropandresize/Main.cpp
+.. literalinclude:: ../../../../samples/cropandresize/Main.cpp
:language: cpp
:start-after: Image Loading
:end-before: The input buffer is now ready to be used
diff --git a/docs/sphinx/samples/python_samples/classification/classification_pytorch.rst b/docs/sphinx/samples/python_samples/classification/classification_pytorch.rst
index 1e4128b49..941c3b1e3 100644
--- a/docs/sphinx/samples/python_samples/classification/classification_pytorch.rst
+++ b/docs/sphinx/samples/python_samples/classification/classification_pytorch.rst
@@ -17,7 +17,7 @@
.. _classification_pytorch:
Classification Inference Using PyTorch
-====================
+======================================
The classification sample in CVCUDA uses the ``ResNet50`` deep learning model from the ``torchvision`` library. Since the model does not come with the softmax layer at the end, we are going to add one. The following code snippet shows how the model is setup for inference use case with PyTorch.
diff --git a/docs/sphinx/samples/python_samples/classification/classification_tensorrt.rst b/docs/sphinx/samples/python_samples/classification/classification_tensorrt.rst
index fda595278..afcb4e428 100644
--- a/docs/sphinx/samples/python_samples/classification/classification_tensorrt.rst
+++ b/docs/sphinx/samples/python_samples/classification/classification_tensorrt.rst
@@ -17,7 +17,7 @@
.. _classification_tensorrt:
Classification Inference Using TensorRT
-====================
+=======================================
The classification sample in CVCUDA uses the ``ResNet50`` deep learning model from the ``torchvision`` library. Since the model does not come with the softmax layer at the end, we are going to add one. The following code snippet shows how the model is setup for inference use case with TensorRT.
diff --git a/docs/sphinx/samples/python_samples/classification/postprocessor_cvcuda.rst b/docs/sphinx/samples/python_samples/classification/postprocessor_cvcuda.rst
index 0d136430b..96abd4efc 100644
--- a/docs/sphinx/samples/python_samples/classification/postprocessor_cvcuda.rst
+++ b/docs/sphinx/samples/python_samples/classification/postprocessor_cvcuda.rst
@@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-.. _preprocessor_cvcuda:
+.. _postprocessor_cvcuda_classification:
Classification Post-processing Pipeline
-====================
+=======================================
The classification post processing pipeline is a relatively lightweight one with sorting being the only operation happening in it.
diff --git a/docs/sphinx/samples/python_samples/classification/preprocessor_cvcuda.rst b/docs/sphinx/samples/python_samples/classification/preprocessor_cvcuda.rst
index 480b25cc5..cb75a09f7 100644
--- a/docs/sphinx/samples/python_samples/classification/preprocessor_cvcuda.rst
+++ b/docs/sphinx/samples/python_samples/classification/preprocessor_cvcuda.rst
@@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-.. _preprocessor_cvcuda:
+.. _preprocessor_cvcuda_classification:
Classification Pre-processing Pipeline using CVCUDA
-====================
+===================================================
CVCUDA helps accelerate the pre-processing pipeline of the classification sample tremendously. Easy interoperability with PyTorch tensors also makes it easy to integrate with PyTorch and other data loaders that supports the tensor layout.
diff --git a/docs/sphinx/samples/python_samples/commons/imagebatchdecoder_nvcodec.rst b/docs/sphinx/samples/python_samples/commons/imagebatchdecoder_nvcodec.rst
index edb14806e..0ac56c1bb 100644
--- a/docs/sphinx/samples/python_samples/commons/imagebatchdecoder_nvcodec.rst
+++ b/docs/sphinx/samples/python_samples/commons/imagebatchdecoder_nvcodec.rst
@@ -17,7 +17,7 @@
.. _imagebatchdecoder_nvcodec:
Image Decoding using nvImageCodec
-====================
+=================================
The image batch decoder is responsible for parsing the input expression, reading and decoding image data. The actual decoding is done in batches using the library `nvImageCodec `_. Although used in the semantic segmentation sample, this image decoder is generic enough to be used in other applications. The code associated with this class can be found in the ``samples/common/python/nvcodec_utils.py`` file.
diff --git a/docs/sphinx/samples/python_samples/commons/imagebatchencoder_nvcodec.rst b/docs/sphinx/samples/python_samples/commons/imagebatchencoder_nvcodec.rst
index 3cdb507d7..09261c529 100644
--- a/docs/sphinx/samples/python_samples/commons/imagebatchencoder_nvcodec.rst
+++ b/docs/sphinx/samples/python_samples/commons/imagebatchencoder_nvcodec.rst
@@ -17,7 +17,7 @@
.. _imagebatchencoder_nvcodec:
Image Encoding using nvImageCodec
-====================
+=================================
The image batch encoder is responsible for saving image tensors to the disk as JPG images. The actual encoding is done in batches using the `nvImageCodec `_ library. The image encoder is generic enough to be across the sample applications. The code associated with this class can be found in the ``samples/common/python/nvcodec_utils.py`` file.
diff --git a/docs/sphinx/samples/python_samples/commons/videobatchdecoder_nvcodec.rst b/docs/sphinx/samples/python_samples/commons/videobatchdecoder_nvcodec.rst
index 9219f0aef..1e088ed26 100644
--- a/docs/sphinx/samples/python_samples/commons/videobatchdecoder_nvcodec.rst
+++ b/docs/sphinx/samples/python_samples/commons/videobatchdecoder_nvcodec.rst
@@ -17,7 +17,7 @@
.. _videobatchdecoder_pyvideocodec:
Video Decoding using pyNvVideoCodec
-====================
+===================================
The video batch decoder is responsible for reading an MP4 video as tensors. The actual decoding is done per frame using NVIDIA's PyNvVideoCodec API. The video decoder is generic enough to be used across the sample applications. The code associated with this class can be found in the ``samples/common/python/nvcodec_utils.py`` file.
diff --git a/docs/sphinx/samples/python_samples/commons/videobatchencoder_nvcodec.rst b/docs/sphinx/samples/python_samples/commons/videobatchencoder_nvcodec.rst
index 96a75bf2b..4312e5360 100644
--- a/docs/sphinx/samples/python_samples/commons/videobatchencoder_nvcodec.rst
+++ b/docs/sphinx/samples/python_samples/commons/videobatchencoder_nvcodec.rst
@@ -17,7 +17,7 @@
.. _videobatchencoder_pyvideocodec:
Video Encoding using VpyNvVideoCodecPF
-====================
+======================================
The video batch encoder is responsible for writing tensors as an MP4 video. The actual encoding is done in batches using NVIDIA's pyNvVideoCodec. The video encoder is generic enough to be used across the sample applications. The code associated with this class can be found in the ``samples/common/python/nvcodec_utils.py`` file.
@@ -35,7 +35,7 @@ The first class acts as a wrapper on the second class which allows us to:
VideoBatchEncoderVPF
-------------------
+--------------------
To get started, here is how the class is initialized in its ``__init__`` method. The encoder instance and CVCUDA color conversion tensors both are allocated when needed upon the first use.
diff --git a/docs/sphinx/samples/python_samples/object_detection/objectdetection_tensorflow.rst b/docs/sphinx/samples/python_samples/object_detection/objectdetection_tensorflow.rst
index 07223f3d3..129aebe5f 100644
--- a/docs/sphinx/samples/python_samples/object_detection/objectdetection_tensorflow.rst
+++ b/docs/sphinx/samples/python_samples/object_detection/objectdetection_tensorflow.rst
@@ -17,7 +17,7 @@
.. _objectdetection_tensorflow:
Object Detection Inference Using TensorFlow
-==========================================
+===========================================
The object detection sample in CVCUDA uses the `Peoplenet Model `_ from NGC. The HDF5 model file is downloaded from NGC. We use appropriate GPU device with Keras to load the model.
diff --git a/docs/sphinx/samples/python_samples/object_detection/postprocessor_cvcuda.rst b/docs/sphinx/samples/python_samples/object_detection/postprocessor_cvcuda.rst
index 6491b09e6..59c20333a 100644
--- a/docs/sphinx/samples/python_samples/object_detection/postprocessor_cvcuda.rst
+++ b/docs/sphinx/samples/python_samples/object_detection/postprocessor_cvcuda.rst
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-.. _preprocessor_cvcuda:
+.. _postprocessor_cvcuda_object_detection:
Object Detection Post-processing Pipeline using CVCUDA
======================================================
diff --git a/docs/sphinx/samples/python_samples/object_detection/preprocessor_cvcuda.rst b/docs/sphinx/samples/python_samples/object_detection/preprocessor_cvcuda.rst
index 39863109f..7f39501af 100644
--- a/docs/sphinx/samples/python_samples/object_detection/preprocessor_cvcuda.rst
+++ b/docs/sphinx/samples/python_samples/object_detection/preprocessor_cvcuda.rst
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-.. _preprocessor_cvcuda:
+.. _preprocessor_cvcuda_object_detection:
Object Detection Pre-processing Pipeline using CVCUDA
=====================================================
diff --git a/docs/sphinx/samples/python_samples/segmentation.rst b/docs/sphinx/samples/python_samples/segmentation.rst
index 53cf5b2eb..23a86893f 100644
--- a/docs/sphinx/samples/python_samples/segmentation.rst
+++ b/docs/sphinx/samples/python_samples/segmentation.rst
@@ -17,7 +17,7 @@
.. _segmentation:
Semantic Segmentation
-====================
+=====================
In this example, we use CVCUDA to accelerate the pre and post processing pipelines in the deep learning inference use case involving a semantic segmentation model. The deep learning model can utilize either PyTorch or TensorRT to run the inference. The pre-processing pipeline converts the input into the format required by the input layer of the model whereas the post processing pipeline converts the output produced by the model into a visualization-friendly frame. We use the FCN ResNet101 model (from torchvision) to generate the predictions. This sample can work on a single image or a folder full of images or on a single video. All images have to be in the JPEG format and with the same dimensions unless run under the batch size of one. Video has to be in mp4 format with a fixed frame rate. We use the torchnvjpeg library to read the images and NVIDIA's Video Processing Framework (VPF) to read/write videos.
diff --git a/docs/sphinx/samples/python_samples/segmentation/postprocessor_cvcuda.rst b/docs/sphinx/samples/python_samples/segmentation/postprocessor_cvcuda.rst
index aa29e10c3..02e54d352 100644
--- a/docs/sphinx/samples/python_samples/segmentation/postprocessor_cvcuda.rst
+++ b/docs/sphinx/samples/python_samples/segmentation/postprocessor_cvcuda.rst
@@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-.. _preprocessor_cvcuda:
+.. _postprocessor_cvcuda_segmentation:
Semantic Segmentation Post-processing Pipeline using CVCUDA
-====================
+===========================================================
CVCUDA helps accelerate the post-processing pipeline of the semantic segmentation sample tremendously. Easy interoperability with PyTorch tensors also makes it easy to integrate with PyTorch and other data loaders that supports the tensor layout.
diff --git a/docs/sphinx/samples/python_samples/segmentation/preprocessor_cvcuda.rst b/docs/sphinx/samples/python_samples/segmentation/preprocessor_cvcuda.rst
index 4a1c4412b..cc0649879 100644
--- a/docs/sphinx/samples/python_samples/segmentation/preprocessor_cvcuda.rst
+++ b/docs/sphinx/samples/python_samples/segmentation/preprocessor_cvcuda.rst
@@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-.. _preprocessor_cvcuda:
+.. _preprocessor_cvcuda_segmentation:
Semantic Segmentation Pre-processing Pipeline using CVCUDA
-====================
+==========================================================
CVCUDA helps accelerate the pre-processing pipeline of the semantic segmentation sample tremendously. Easy interoperability with PyTorch tensors also makes it easy to integrate with PyTorch and other data loaders that supports the tensor layout.
diff --git a/docs/sphinx/samples/python_samples/segmentation/segmentation_pytorch.rst b/docs/sphinx/samples/python_samples/segmentation/segmentation_pytorch.rst
index 34b6d5fdd..acf9de781 100644
--- a/docs/sphinx/samples/python_samples/segmentation/segmentation_pytorch.rst
+++ b/docs/sphinx/samples/python_samples/segmentation/segmentation_pytorch.rst
@@ -17,7 +17,7 @@
.. _segmentation_pytorch:
Semantic Segmentation Inference Using PyTorch
-====================
+=============================================
The semantic segmentation sample in CVCUDA uses the ``fcn_resnet101`` deep learning model from the ``torchvision`` library. Since the model does not come with the softmax layer at the end, we are going to add one. The following code snippet shows how the model is setup for inference use case with PyTorch.
diff --git a/docs/sphinx/samples/python_samples/segmentation/segmentation_tensorrt.rst b/docs/sphinx/samples/python_samples/segmentation/segmentation_tensorrt.rst
index 03f995f81..211ff89ef 100644
--- a/docs/sphinx/samples/python_samples/segmentation/segmentation_tensorrt.rst
+++ b/docs/sphinx/samples/python_samples/segmentation/segmentation_tensorrt.rst
@@ -17,7 +17,7 @@
.. _segmentation_tensorrt:
Semantic Segmentation Inference Using TensorRT
-====================
+==============================================
The semantic segmentation sample in CVCUDA uses the ``fcn_resnet101`` deep learning model from the ``torchvision`` library. Since the model does not come with the softmax layer at the end, we are going to add one. The following code snippet shows how the model is setup for inference use case with TensorRT.
diff --git a/docs/sphinx/samples/python_samples/segmentation_triton.rst b/docs/sphinx/samples/python_samples/segmentation_triton.rst
index f03e0dcc2..549edd597 100644
--- a/docs/sphinx/samples/python_samples/segmentation_triton.rst
+++ b/docs/sphinx/samples/python_samples/segmentation_triton.rst
@@ -28,12 +28,15 @@ Refer to the Segmentation sample documentation to understand the details of the
Terminologies
-------------
* Triton Server
+
Manages and deploys model at scale. Refer the Triton documentation to review all the features Triton has to offer.
* Triton model repository
+
Triton model represents a inference workload that needs to be deployed. The triton server loads the model repository when started.
* Triton Client
+
Triton client libraries facilitates communication with Triton using Python or C++ API.
In this example we will demonstrate how to to the Python API to communicate with Triton using GRPC requests.
@@ -63,22 +66,26 @@ Tutorial
The model repository paths needs to conform to a layout specified below:
- /
- /
- /
-
- config.pbtxt
+ .. code-block:: bash
+
+ /
+ /
+ /
+
+ config.pbtxt
For the segmentation sample, we will create a model.py which creates a TritonPythonModel
that runs the preprocess, inference and post process workloads.
We will copy the necessary files and modules from the segmentation sample for preprocess,
inference and postprocess stages and create the following folder structure:
- triton_models/
- fcn_resnet101/
- 1/
- model.py
- config.pbtxt
+ .. code-block:: bash
+
+ triton_models/
+ fcn_resnet101/
+ 1/
+ model.py
+ config.pbtxt
Each model in the model repository must include a model configuration that provides the required
and optional information about the model. Typically, this configuration is provided in a config.pbtxt
diff --git a/python/mod_cvcuda/CMakeLists.txt b/python/mod_cvcuda/CMakeLists.txt
index b533a105d..2ab990d14 100644
--- a/python/mod_cvcuda/CMakeLists.txt
+++ b/python/mod_cvcuda/CMakeLists.txt
@@ -88,6 +88,7 @@ nvcv_python_add_module(
OpInpaint.cpp
CvtColorUtil.cpp
OpFindHomography.cpp
+ NormType.cpp
)
target_link_libraries(cvcuda_module_python
diff --git a/python/mod_cvcuda/Main.cpp b/python/mod_cvcuda/Main.cpp
index f5c26574f..780773ba1 100644
--- a/python/mod_cvcuda/Main.cpp
+++ b/python/mod_cvcuda/Main.cpp
@@ -38,13 +38,6 @@ namespace py = pybind11;
PYBIND11_MODULE(cvcuda, m)
{
- m.doc() = R"pbdoc(
- CV-CUDA Python API reference
- ========================
-
- This is the Python API reference for the NVIDIA® CV-CUDA library.
- )pbdoc";
-
m.attr("__version__") = CVCUDA_VERSION_STRING;
// Import all public names from nvcv
@@ -76,23 +69,25 @@ PYBIND11_MODULE(cvcuda, m)
using namespace cvcudapy;
+ // doctag: Non-Operators
// Operators' auxiliary entities
- ExportInterpolationType(m);
- ExportChannelManipType(m);
+ ExportAdaptiveThresholdType(m);
ExportBorderType(m);
- ExportMorphologyType(m);
- ExportColorConversionCode(m);
- ExportRemapMapValueType(m);
ExportBoxBlur(m);
+ ExportChannelManipType(m);
ExportOSD(m);
- ExportThresholdType(m);
- ExportAdaptiveThresholdType(m);
- ExportSIFTFlagType(m);
+ ExportColorConversionCode(m);
ExportConnectivityType(m);
+ ExportInterpolationType(m);
ExportLabelType(m);
- ExportNormType(m);
ExportPairwiseMatcherType(m);
+ ExportMorphologyType(m);
+ ExportNormType(m);
+ ExportRemapMapValueType(m);
+ ExportSIFTFlagType(m);
+ ExportThresholdType(m);
+ // doctag: Operators
// CV-CUDA Operators
ExportOpResizeCropConvertReformat(m);
ExportOpPairwiseMatcher(m);
diff --git a/python/mod_cvcuda/OpAdaptiveThreshold.cpp b/python/mod_cvcuda/OpAdaptiveThreshold.cpp
index 30801fb5f..503820171 100644
--- a/python/mod_cvcuda/OpAdaptiveThreshold.cpp
+++ b/python/mod_cvcuda/OpAdaptiveThreshold.cpp
@@ -141,7 +141,7 @@ void ExportOpAdaptiveThreshold(py::module &m)
cvcuda.adaptivethreshold_into(dst: nvcv.Tensor, src: nvcv.Tensor, max_value: double, adaptive_method: NVCVAdaptiveThresholdType = < NVCV_ADAPTIVE_TH
RESH_MEAN_C >, threshold_type: NVCVThresholdType = < NVCV_THRESH_BINARY >, block_size: int, c: double, stream: Optional[nvcv.cuda.Stream] = None)
- Executes the adaptive threshold operation on the given cuda stream.
+ Executes the adaptive threshold operation on the given cuda stream.
See also:
Refer to the CV-CUDA C API reference for the Composite operator
@@ -169,6 +169,7 @@ RESH_MEAN_C >, threshold_type: NVCVThresholdType = < NVCV_THRESH_BINARY >, block
"adaptive_method"_a = NVCV_ADAPTIVE_THRESH_MEAN_C, "threshold_type"_a = NVCV_THRESH_BINARY,
"max_block_size"_a, "block_size"_a, "c"_a, py::kw_only(), "stream"_a = nullptr, R"pbdoc(
cvcuda.adaptivethreshold(src: nvcv.ImageBatchVarShape, max_value: nvcv.Tensor, adaptive_method: NVCVAdaptiveThresholdType = < NVCV_ADAPTIVE_THRESH_MEAN_C >, threshold_type: NVCVThresholdType = < NVCV_THRESH_BINARY > , block_size: int, c: double, stream: Optional[nvcv.cuda.Stream] = None) -> nvcv.ImageBatchVarShape
+
Executes the adaptive threshold operation on the given cuda stream.
See also:
diff --git a/python/mod_cvcuda/OpAdvCvtColor.cpp b/python/mod_cvcuda/OpAdvCvtColor.cpp
index c9a4eff2e..d2b3cc04d 100644
--- a/python/mod_cvcuda/OpAdvCvtColor.cpp
+++ b/python/mod_cvcuda/OpAdvCvtColor.cpp
@@ -103,8 +103,8 @@ Tensor AdvCvtColor(Tensor &input, NVCVColorConversionCode code, NVCVColorSpec sp
void ExportOpAdvCvtColor(py::module &m)
{
using namespace pybind11::literals;
-
- m.def("advcvtcolor", &AdvCvtColor, "src"_a, "code"_a, "spec"_a, py::kw_only(), "stream"_a = nullptr, R"pbdoc(
+ m.def("advcvtcolor", &AdvCvtColor, "src"_a, "code"_a, "spec"_a, py::kw_only(), "stream"_a = nullptr,
+ R"pbdoc(
Executes the Adv Cvt Color operation on the given cuda stream.
diff --git a/python/mod_cvcuda/OpResizeCropConvertReformat.cpp b/python/mod_cvcuda/OpResizeCropConvertReformat.cpp
index a99c5072f..3dcb22f34 100644
--- a/python/mod_cvcuda/OpResizeCropConvertReformat.cpp
+++ b/python/mod_cvcuda/OpResizeCropConvertReformat.cpp
@@ -32,7 +32,8 @@ namespace cvcudapy {
namespace {
Tensor ResizeCropConvertReformatInto(Tensor &dst, Tensor &src, const std::tuple resizeDim,
NVCVInterpolationType interp, const std::tuple cropPos,
- const NVCVChannelManip manip, std::optional pstream)
+ const NVCVChannelManip manip, const float scale, const float offset,
+ const bool srcCast, std::optional pstream)
{
if (!pstream)
{
@@ -49,14 +50,15 @@ Tensor ResizeCropConvertReformatInto(Tensor &dst, Tensor &src, const std::tuple<
nvcv::Size2D size_wh{std::get<0>(resizeDim), std::get<1>(resizeDim)};
int2 crop_xy{std::get<0>(cropPos), std::get<1>(cropPos)};
- resize->submit(pstream->cudaHandle(), src, dst, size_wh, interp, crop_xy, manip);
+ resize->submit(pstream->cudaHandle(), src, dst, size_wh, interp, crop_xy, manip, scale, offset, srcCast);
return std::move(dst);
}
Tensor ResizeCropConvertReformat(Tensor &src, const std::tuple resizeDim, NVCVInterpolationType interp,
const NVCVRectI cropRect, const char *layout, nvcv::DataType dataType,
- const NVCVChannelManip manip, std::optional pstream)
+ const NVCVChannelManip manip, const float scale, const float offset,
+ const bool srcCast, std::optional pstream)
{
nvcv::TensorLayout srcLayout = src.layout();
@@ -98,12 +100,13 @@ Tensor ResizeCropConvertReformat(Tensor &src, const std::tuple resizeD
const std::tuple cropPos = std::make_tuple((int)cropRect.x, (int)cropRect.y);
- return ResizeCropConvertReformatInto(dst, src, resizeDim, interp, cropPos, manip, pstream);
+ return ResizeCropConvertReformatInto(dst, src, resizeDim, interp, cropPos, manip, scale, offset, srcCast, pstream);
}
Tensor ResizeCropConvertReformatVarShapeInto(Tensor &dst, ImageBatchVarShape &src, const std::tuple resizeDim,
NVCVInterpolationType interp, const std::tuple cropPos,
- const NVCVChannelManip manip, std::optional pstream)
+ const NVCVChannelManip manip, const float scale, const float offset,
+ const bool srcCast, std::optional pstream)
{
if (!pstream)
{
@@ -120,15 +123,15 @@ Tensor ResizeCropConvertReformatVarShapeInto(Tensor &dst, ImageBatchVarShape &sr
nvcv::Size2D size_wh(std::get<0>(resizeDim), std::get<1>(resizeDim));
int2 crop_xy{std::get<0>(cropPos), std::get<1>(cropPos)};
- resize->submit(pstream->cudaHandle(), src, dst, size_wh, interp, crop_xy, manip);
+ resize->submit(pstream->cudaHandle(), src, dst, size_wh, interp, crop_xy, manip, scale, offset, srcCast);
return std::move(dst);
}
Tensor ResizeCropConvertReformatVarShape(ImageBatchVarShape &src, const std::tuple resizeDim,
NVCVInterpolationType interp, const NVCVRectI cropRect, const char *layout,
- nvcv::DataType dataType, const NVCVChannelManip manip,
- std::optional pstream)
+ nvcv::DataType dataType, const NVCVChannelManip manip, const float scale,
+ const float offset, const bool srcCast, std::optional pstream)
{
const nvcv::ImageFormat srcFrmt = src.uniqueFormat();
if (!srcFrmt)
@@ -188,7 +191,8 @@ Tensor ResizeCropConvertReformatVarShape(ImageBatchVarShape &src, const std::tup
const std::tuple cropPos = std::make_tuple((int)cropRect.x, (int)cropRect.y);
- return ResizeCropConvertReformatVarShapeInto(dst, src, resizeDim, interp, cropPos, manip, pstream);
+ return ResizeCropConvertReformatVarShapeInto(dst, src, resizeDim, interp, cropPos, manip, scale, offset, srcCast,
+ pstream);
}
} // namespace
@@ -202,7 +206,8 @@ void ExportOpResizeCropConvertReformat(py::module &m)
m.def("resize_crop_convert_reformat", &ResizeCropConvertReformat, "src"_a, "resize_dim"_a, "interp"_a,
"crop_rect"_a, py::kw_only(), "layout"_a = "", "data_type"_a = NVCV_DATA_TYPE_NONE,
- "manip"_a = NVCV_CHANNEL_NO_OP, "stream"_a = nullptr, R"pbdoc(
+ "manip"_a = NVCV_CHANNEL_NO_OP, "scale"_a = 1.0, "offset"_a = 0.0, "srcCast"_a = true, "stream"_a = nullptr,
+ R"pbdoc(
cvcuda.resize_crop_convert_reformat(src: nvcv.Tensor,
resize_dim: tuple[int,int],
@@ -212,6 +217,9 @@ void ExportOpResizeCropConvertReformat(py::module &m)
layout: str = "",
data_type: nvcv.Type = 0,
manip: cvcuda.ChannelManip = cvcuda.ChannelManip.NO_OP,
+ scale: float = 1.0,
+ offset: float = 0.0,
+ srcCast: bool = True,
stream: Optional[nvcv.cuda.Stream] = None) -> nvcv.Tensor
Executes the ResizeCropConvertReformat operation on the given cuda stream.
@@ -233,6 +241,15 @@ void ExportOpResizeCropConvertReformat(py::module &m)
indicates output tensor data type copies input.
manip(cvcuda.ChannelManip, optional): Channel manipulation (e.g., shuffle RGB to BGR). NO_OP (default)
indicates output tensor channels are unchanged.
+ scale(float, optional): Scale (i.e., multiply) the output values by this amount. 1.0 (default) results
+ in no scaling of the output values.
+ offset(float, optional): Offset (i.e., add to) the output values by this amount. This is applied after
+ scaling. Let v be a resized and cropped value, then v * scale + offset is final
+ output value. 0.0 (default) results in no offset being added to the output.
+ srcCast(bool, optional): Boolean indicating whether or not the resize interpolation results are re-cast
+ back to the input (or source) data type. Refer to the C API reference for more
+ information. True (default) re-cast resize interpolation results back to the
+ source data type.
stream (nvcv.cuda.Stream, optional): CUDA Stream on which to perform the operation.
Returns:
@@ -244,7 +261,8 @@ void ExportOpResizeCropConvertReformat(py::module &m)
)pbdoc");
m.def("resize_crop_convert_reformat_into", &ResizeCropConvertReformatInto, "dst"_a, "src"_a, "resize_dim"_a,
- "interp"_a, "cropPos"_a, py::kw_only(), "manip"_a = NVCV_CHANNEL_NO_OP, "stream"_a = nullptr, R"pbdoc(
+ "interp"_a, "cropPos"_a, py::kw_only(), "manip"_a = NVCV_CHANNEL_NO_OP, "scale"_a = 1.0, "offset"_a = 0.0,
+ "srcCast"_a = true, "stream"_a = nullptr, R"pbdoc(
cvcuda.resize_crop_convert_reformat_into(dst: nvcv.Tensor,
src: nvcv.Tensor,
@@ -253,6 +271,9 @@ void ExportOpResizeCropConvertReformat(py::module &m)
cropPos: tuple[int,int],
*,
manip: cvcuda.ChannelManip = cvcuda.ChannelManip.NO_OP,
+ scale: float = 1.0,
+ offset: float = 0.0,
+ srcCast: bool = True,
stream: Optional[nvcv.cuda.Stream] = None)
Executes the ResizeCropConvertReformat operation on the given cuda stream.
@@ -274,6 +295,15 @@ void ExportOpResizeCropConvertReformat(py::module &m)
output tensor's width & height.
manip(cvcuda.ChannelManip, optional): Channel manipulation (e.g., shuffle RGB to BGR). NO_OP (default)
indicates output tensor channels are unchanged.
+ scale(float, optional): Scale (i.e., multiply) the output values by this amount. 1.0 (default) results
+ in no scaling of the output values.
+ offset(float, optional): Offset (i.e., add to) the output values by this amount. This is applied after
+ scaling. Let v be a resized and cropped value, then v * scale + offset is final
+ output value. 0.0 (default) results in no offset being added to the output.
+ srcCast(bool, optional): Boolean indicating whether or not the resize interpolation results are re-cast
+ back to the input (or source) data type. Refer to the C API reference for more
+ information. True (default) re-cast resize interpolation results back to the
+ source data type.
stream (nvcv.cuda.Stream, optional): CUDA Stream on which to perform the operation.
Returns:
@@ -286,7 +316,8 @@ void ExportOpResizeCropConvertReformat(py::module &m)
m.def("resize_crop_convert_reformat", &ResizeCropConvertReformatVarShape, "src"_a, "resize_dim"_a, "interp"_a,
"crop_rect"_a, py::kw_only(), "layout"_a = "", "data_type"_a = NVCV_DATA_TYPE_NONE,
- "manip"_a = NVCV_CHANNEL_NO_OP, "stream"_a = nullptr, R"pbdoc(
+ "manip"_a = NVCV_CHANNEL_NO_OP, "scale"_a = 1.0, "offset"_a = 0.0, "srcCast"_a = true, "stream"_a = nullptr,
+ R"pbdoc(
cvcuda.resizeCropConvertReformat(src: nvcv.ImageBatchVarShape,
resize_dim: tuple[int,int],
@@ -296,6 +327,9 @@ void ExportOpResizeCropConvertReformat(py::module &m)
layout: str = "",
data_type: nvcv.Type = 0,
manip: cvcuda.ChannelManip = cvcuda.ChannelManip.NO_OP,
+ scale: float = 1.0,
+ offset: float = 0.0,
+ srcCast: bool = True,
stream: Optional[nvcv.cuda.Stream] = None) -> nvcv.Tensor
Executes the ResizeCropConvertReformat operation on the given cuda stream.
@@ -318,6 +352,15 @@ void ExportOpResizeCropConvertReformat(py::module &m)
indicates output tensor data type copies input.
manip(cvcuda.ChannelManip, optional): Channel manipulation (e.g., shuffle RGB to BGR). NO_OP (default)
indicates output tensor channels are unchanged.
+ scale(float, optional): Scale (i.e., multiply) the output values by this amount. 1.0 (default) results
+ in no scaling of the output values.
+ offset(float, optional): Offset (i.e., add to) the output values by this amount. This is applied after
+ scaling. Let v be a resized and cropped value, then v * scale + offset is final
+ output value. 0.0 (default) results in no offset being added to the output.
+ srcCast(bool, optional): Boolean indicating whether or not the resize interpolation results are re-cast
+ back to the input (or source) data type. Refer to the C API reference for more
+ information. True (default) re-cast resize interpolation results back to the
+ source data type.
stream (nvcv.cuda.Stream, optional): CUDA Stream on which to perform the operation.
Returns:
@@ -329,7 +372,8 @@ void ExportOpResizeCropConvertReformat(py::module &m)
)pbdoc");
m.def("resize_crop_convert_reformat_into", &ResizeCropConvertReformatVarShapeInto, "dst"_a, "src"_a, "resize_dim"_a,
- "interp"_a, "cropPos"_a, py::kw_only(), "manip"_a = NVCV_CHANNEL_NO_OP, "stream"_a = nullptr, R"pbdoc(
+ "interp"_a, "cropPos"_a, py::kw_only(), "manip"_a = NVCV_CHANNEL_NO_OP, "scale"_a = 1.0, "offset"_a = 0.0,
+ "srcCast"_a = true, "stream"_a = nullptr, R"pbdoc(
cvcuda.resize_crop_convert_reformat_into(dst: nvcv.Tensor,
src: nvcv.ImageBatchVarShape,
@@ -338,6 +382,9 @@ void ExportOpResizeCropConvertReformat(py::module &m)
cropPos: tuple[int,int],
*,
manip: cvcuda.ChannelManip = cvcuda.ChannelManip.NO_OP,
+ scale: float = 1.0,
+ offset: float = 0.0,
+ srcCast: bool = True,
stream: Optional[nvcv.cuda.Stream] = None)
Executes the ResizeCropConvertReformat operation on the given cuda stream.
@@ -360,6 +407,15 @@ void ExportOpResizeCropConvertReformat(py::module &m)
the output tensor's width & height.
manip(cvcuda.ChannelManip, optional): Channel manipulation (e.g., shuffle RGB to BGR). NO_OP (default)
indicates output tensor channels are unchanged.
+ scale(float, optional): Scale (i.e., multiply) the output values by this amount. 1.0 (default) results
+ in no scaling of the output values.
+ offset(float, optional): Offset (i.e., add to) the output values by this amount. This is applied after
+ scaling. Let v be a resized and cropped value, then v * scale + offset is final
+ output value. 0.0 (default) results in no offset being added to the output.
+ srcCast(bool, optional): Boolean indicating whether or not the resize interpolation results are re-cast
+ back to the input (or source) data type. Refer to the C API reference for more
+ information. True (default) re-cast resize interpolation results back to the
+ source data type.
stream (nvcv.cuda.Stream, optional): CUDA Stream on which to perform the operation.
Returns:
diff --git a/python/mod_cvcuda/OsdElement.cpp b/python/mod_cvcuda/OsdElement.cpp
index e47730fef..d1b00de37 100644
--- a/python/mod_cvcuda/OsdElement.cpp
+++ b/python/mod_cvcuda/OsdElement.cpp
@@ -97,7 +97,7 @@ void ExportBoxBlur(py::module &m)
using namespace py::literals;
using namespace cvcuda::priv;
- py::class_(m, "BlurBoxI")
+ py::class_(m, "BlurBoxI", "BlurBoxI")
.def(py::init(
[](py::tuple box, int kernelSize)
{
@@ -121,7 +121,7 @@ void ExportOSD(py::module &m)
using namespace py::literals;
using namespace cvcuda::priv;
- py::class_(m, "BndBoxI")
+ py::class_(m, "BndBoxI", "BndBoxI")
.def(py::init(
[](py::tuple box, int thickness, py::tuple borderColor, py::tuple fillColor)
{
@@ -168,7 +168,7 @@ void ExportOSD(py::module &m)
}),
"box"_a, "thickness"_a, "segArray"_a, "segThreshold"_a, "borderColor"_a, "segColor"_a);
- py::class_(m, "Point")
+ py::class_(m, "Point", "Point")
.def(py::init(
[](py::tuple centerPos, int32_t radius, py::tuple color)
{
@@ -183,7 +183,7 @@ void ExportOSD(py::module &m)
.def_readonly("radius", &NVCVPoint::radius, "Point size.")
.def_readonly("color", &NVCVPoint::color, "Point color.");
- py::class_(m, "Line")
+ py::class_(m, "Line", "Line")
.def(py::init(
[](py::tuple pos0, py::tuple pos1, int32_t thickness, py::tuple color, bool interpolation)
{
@@ -218,7 +218,7 @@ void ExportOSD(py::module &m)
}),
"points"_a, "thickness"_a, "isClosed"_a, "borderColor"_a, "fillColor"_a, py::arg("interpolation") = true);
- py::class_(m, "RotatedBox")
+ py::class_(m, "RotatedBox", "RotatedBox")
.def(py::init(
[](py::tuple centerPos, int32_t width, int32_t height, float yaw, int32_t thickness,
py::tuple borderColor, py::tuple bgColor, bool interpolation)
@@ -245,7 +245,7 @@ void ExportOSD(py::module &m)
.def_readonly("bgColor", &NVCVRotatedBox::bgColor, "Circle filled color.")
.def_readonly("interpolation", &NVCVRotatedBox::interpolation, "Default: false.");
- py::class_(m, "Circle")
+ py::class_(m, "Circle", "Circle")
.def(py::init(
[](py::tuple centerPos, int32_t radius, int32_t thickness, py::tuple borderColor, py::tuple bgColor)
{
@@ -264,7 +264,7 @@ void ExportOSD(py::module &m)
.def_readonly("borderColor", &NVCVCircle::borderColor, "Circle border color.")
.def_readonly("bgColor", &NVCVCircle::bgColor, "Circle filled color.");
- py::class_(m, "Arrow")
+ py::class_(m, "Arrow", "Arrow")
.def(py::init(
[](py::tuple pos0, py::tuple pos1, int32_t arrowSize, int32_t thickness, py::tuple color,
bool interpolation)
diff --git a/python/mod_nvcv/Array.cpp b/python/mod_nvcv/Array.cpp
index 5a39e91ef..710ad7bec 100644
--- a/python/mod_nvcv/Array.cpp
+++ b/python/mod_nvcv/Array.cpp
@@ -322,7 +322,7 @@ void Array::Export(py::module &m)
using ResizeArrayLengthPtr = std::shared_ptr (*)(Array &, int64_t DataType);
using ResizeArrayShapePtr = std::shared_ptr (*)(Array &, Shape);
- py::class_, Container>(m, "Array")
+ py::class_, Container>(m, "Array", "Array")
.def(py::init(static_cast(&Array::Create)), "length"_a, "dtype"_a,
"Create a Array object with the given length and data type.")
.def(py::init(static_cast(&Array::Create)), "shape"_a, "dtype"_a,
diff --git a/python/mod_nvcv/CAPI.cpp b/python/mod_nvcv/CAPI.cpp
index b31fc27ec..f573704ab 100644
--- a/python/mod_nvcv/CAPI.cpp
+++ b/python/mod_nvcv/CAPI.cpp
@@ -36,6 +36,19 @@ namespace nvcvpy::priv {
namespace {
+// We need to catch any exceptions and set the appropriate PyError prior to crossing any C API boundry
+#define CATCH_RETURN_DEFAULT(return_value, error_message) \
+ catch (const std::exception &e) \
+ { \
+ PyErr_SetString(PyExc_ValueError, (std::string(error_message) + ": " + e.what()).c_str()); \
+ return return_value; \
+ } \
+ catch (...) \
+ { \
+ PyErr_SetString(PyExc_ValueError, error_message); \
+ return return_value; \
+ }
+
template
std::shared_ptr ToSharedObj(PyObject *obj)
{
@@ -50,34 +63,58 @@ T ToObj(PyObject *obj)
extern "C" PyObject *ImplDataType_ToPython(NVCVDataType p)
{
- py::object obj = py::cast(nvcv::DataType(p));
- return obj.ptr();
+ try
+ {
+ py::object obj = py::cast(nvcv::DataType(p));
+ return obj.ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Casting PyObject from NVCVDataType failed")
}
extern "C" NVCVDataType ImplDataType_FromPython(PyObject *obj)
{
- return ToObj(obj);
+ try
+ {
+ return ToObj(obj);
+ }
+ CATCH_RETURN_DEFAULT(0, "Casting nvcv::DataType from PyObject failed")
}
extern "C" PyObject *ImplImageFormat_ToPython(NVCVImageFormat p)
{
- py::object obj = py::cast(nvcv::ImageFormat(p));
- return obj.ptr();
+ try
+ {
+ py::object obj = py::cast(nvcv::ImageFormat(p));
+ return obj.ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Casting PyObject from NVCVImageFormat failed")
}
extern "C" NVCVImageFormat ImplImageFormat_FromPython(PyObject *obj)
{
- return ToObj(obj);
+ try
+ {
+ return ToObj(obj);
+ }
+ CATCH_RETURN_DEFAULT(0, "Casting nvcv::ImageFormat from PyObject failed")
}
extern "C" NVCVTensorHandle ImplTensor_GetHandle(PyObject *obj)
{
- return ToSharedObj(obj)->impl().handle();
+ try
+ {
+ return ToSharedObj(obj)->impl().handle();
+ }
+ CATCH_RETURN_DEFAULT(0, "Getting Tensor handle from PyObject failed")
}
extern "C" NVCVArrayHandle ImplArray_GetHandle(PyObject *obj)
{
- return ToSharedObj(obj)->impl().handle();
+ try
+ {
+ return ToSharedObj(obj)->impl().handle();
+ }
+ CATCH_RETURN_DEFAULT(0, "Getting Array handle from PyObject failed")
}
LockMode ToLockMode(PyObject *_mode)
@@ -107,180 +144,273 @@ LockMode ToLockMode(PyObject *_mode)
extern "C" void ImplResource_SubmitSync(PyObject *res, PyObject *stream)
{
- ToSharedObj(res)->submitSync(*ToSharedObj(stream));
+ try
+ {
+ ToSharedObj(res)->submitSync(*ToSharedObj(stream));
+ }
+ CATCH_RETURN_DEFAULT(, "Submit sync failed")
}
extern "C" void ImplStream_HoldResources(PyObject *stream, PyObject *resourceList)
{
- py::list resList = ToObj(resourceList);
+ try
+ {
+ py::list resList = ToObj(resourceList);
- LockResources resVector;
+ LockResources resVector;
- for (py::handle h : resList)
- {
- py::tuple t = h.cast();
- if (t.size() != 2)
+ for (py::handle h : resList)
{
- throw std::runtime_error("ResourcePerMode tuple must have two elements");
- }
+ py::tuple t = h.cast();
+ if (t.size() != 2)
+ {
+ throw std::runtime_error("ResourcePerMode tuple must have two elements");
+ }
- auto lockMode = ToLockMode(t[0].ptr());
- auto res = ToSharedObj(t[1].ptr());
+ auto lockMode = ToLockMode(t[0].ptr());
+ auto res = ToSharedObj(t[1].ptr());
- resVector.emplace(lockMode, res);
- }
+ resVector.emplace(lockMode, res);
+ }
- ToSharedObj(stream)->holdResources(std::move(resVector));
+ ToSharedObj(stream)->holdResources(std::move(resVector));
+ }
+ CATCH_RETURN_DEFAULT(, "Hold resources failed")
}
extern "C" PyObject *ImplStream_GetCurrent()
{
- return py::cast(Stream::Current().shared_from_this()).ptr();
+ try
+ {
+ return py::cast(Stream::Current().shared_from_this()).ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Get current stream failed")
}
extern "C" cudaStream_t ImplStream_GetCudaHandle(PyObject *stream)
{
- return ToSharedObj(stream)->handle();
+ try
+ {
+ return ToSharedObj(stream)->handle();
+ }
+ CATCH_RETURN_DEFAULT(0, "Get cuda handle failed")
}
extern "C" PyObject *ImplTensor_Create(int32_t ndim, const int64_t *shape, NVCVDataType dtype, NVCVTensorLayout layout,
int32_t rowalign)
{
- std::optional cxxLayout;
- if (layout != NVCV_TENSOR_NONE)
+ try
{
- cxxLayout = nvcv::TensorLayout(layout);
- }
-
- std::shared_ptr tensor = Tensor::Create(CreateShape(nvcv::TensorShape(shape, ndim, layout)),
- nvcv::DataType{dtype}, std::move(layout), rowalign);
+ std::optional cxxLayout;
+ if (layout != NVCV_TENSOR_NONE)
+ {
+ cxxLayout = nvcv::TensorLayout(layout);
+ }
- return py::cast(std::move(tensor)).release().ptr();
+ std::shared_ptr tensor = Tensor::Create(CreateShape(nvcv::TensorShape(shape, ndim, layout)),
+ nvcv::DataType{dtype}, std::move(layout), rowalign);
+ return py::cast(std::move(tensor)).release().ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Tensor create failed")
}
extern "C" PyObject *ImplArray_Create(int64_t length, NVCVDataType dtype)
{
- std::shared_ptr array = Array::Create(length, nvcv::DataType{dtype});
+ try
+ {
+ std::shared_ptr array = Array::Create(length, nvcv::DataType{dtype});
- return py::cast(std::move(array)).release().ptr();
+ return py::cast(std::move(array)).release().ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Array create failed")
}
extern "C" PyObject *ImplImageBatchVarShape_Create(int32_t capacity)
{
- std::shared_ptr varshape = ImageBatchVarShape::Create(capacity);
- return py::cast(std::move(varshape)).release().ptr();
+ try
+ {
+ std::shared_ptr varshape = ImageBatchVarShape::Create(capacity);
+ return py::cast(std::move(varshape)).release().ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "ImageBatchVarShape create failed")
}
extern "C" NVCVImageBatchHandle ImplImageBatchVarShape_GetHandle(PyObject *varshape)
{
- return ToSharedObj(varshape)->impl().handle();
+ try
+ {
+ return ToSharedObj(varshape)->impl().handle();
+ }
+ CATCH_RETURN_DEFAULT(0, "ImageBatchVarShape get handle failed")
}
extern "C" PyObject *ImplTensor_CreateForImageBatch(int32_t numImages, int32_t width, int32_t height,
NVCVImageFormat fmt, int32_t rowalign)
{
- std::shared_ptr tensor
- = Tensor::CreateForImageBatch(numImages, {width, height}, nvcv::ImageFormat(fmt), rowalign);
- return py::cast(std::move(tensor)).release().ptr();
+ try
+ {
+ std::shared_ptr tensor
+ = Tensor::CreateForImageBatch(numImages, {width, height}, nvcv::ImageFormat(fmt), rowalign);
+ return py::cast(std::move(tensor)).release().ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Tensor for ImageBatch create failed")
}
extern "C" void ImplImageBatchVarShape_PushBack(PyObject *varshape, PyObject *image)
{
- auto pimage = ToSharedObj(image);
- return ToSharedObj(varshape)->pushBack(*pimage);
+ try
+ {
+ auto pimage = ToSharedObj(image);
+ return ToSharedObj(varshape)->pushBack(*pimage);
+ }
+ CATCH_RETURN_DEFAULT(, "ImageBatchVarShape push back failed")
}
extern "C" void ImplImageBatchVarShape_PopBack(PyObject *varshape, int32_t cnt)
{
- return ToSharedObj(varshape)->popBack(cnt);
+ try
+ {
+ return ToSharedObj(varshape)->popBack(cnt);
+ }
+ CATCH_RETURN_DEFAULT(, "ImageBatchVarShape pop back failed")
}
extern "C" void ImplImageBatchVarShape_Clear(PyObject *varshape)
{
- return ToSharedObj(varshape)->clear();
+ try
+ {
+ return ToSharedObj(varshape)->clear();
+ }
+ CATCH_RETURN_DEFAULT(, "ImageBatchVarShape clear failed")
}
extern "C" PyObject *ImplTensorBatch_Create(int32_t capacity)
{
- std::shared_ptr tensorBatch = TensorBatch::Create(capacity);
- return py::cast(std::move(tensorBatch)).release().ptr();
+ try
+ {
+ std::shared_ptr tensorBatch = TensorBatch::Create(capacity);
+ return py::cast(std::move(tensorBatch)).release().ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "TensorBatch create failed")
}
extern "C" NVCVTensorBatchHandle ImplTensorBatch_GetHandle(PyObject *tensorBatch)
{
- return ToSharedObj(tensorBatch)->impl().handle();
+ try
+ {
+ return ToSharedObj(tensorBatch)->impl().handle();
+ }
+ CATCH_RETURN_DEFAULT(0, "TensorBatch get handle failed")
}
extern "C" void ImplTensorBatch_PushBack(PyObject *tensorBatch, PyObject *tensor)
{
- auto ptensor = ToSharedObj(tensor);
- ToSharedObj(tensorBatch)->pushBack(*ptensor);
+ try
+ {
+ auto ptensor = ToSharedObj(tensor);
+ ToSharedObj(tensorBatch)->pushBack(*ptensor);
+ }
+ CATCH_RETURN_DEFAULT(, "TensorBatch push back failed")
}
extern "C" void ImplTensorBatch_PopBack(PyObject *tensorBatch, uint32_t cnt)
{
- ToSharedObj(tensorBatch)->popBack(cnt);
+ try
+ {
+ ToSharedObj(tensorBatch)->popBack(cnt);
+ }
+ CATCH_RETURN_DEFAULT(, "TensorBatch pop back failed")
}
extern "C" void ImplTensorBatch_Clear(PyObject *tensorBatch)
{
- ToSharedObj(tensorBatch)->clear();
+ try
+ {
+ ToSharedObj(tensorBatch)->clear();
+ }
+ CATCH_RETURN_DEFAULT(, "TensorBatch clear failed")
}
extern "C" void ImplCache_Add(ICacheItem *extItem)
{
- auto item = std::make_shared(extItem->shared_from_this());
- Cache::Instance().add(*item);
+ try
+ {
+ auto item = std::make_shared(extItem->shared_from_this());
+ Cache::Instance().add(*item);
+ }
+ CATCH_RETURN_DEFAULT(, "Cache add item failed")
}
extern "C" ICacheItem **ImplCache_Fetch(const IKey *pkey)
{
- NVCV_ASSERT(pkey != nullptr);
+ try
+ {
+ NVCV_ASSERT(pkey != nullptr);
- std::vector> vcont = Cache::Instance().fetch(*pkey);
+ std::vector> vcont = Cache::Instance().fetch(*pkey);
- std::unique_ptr out(new ICacheItem *[vcont.size() + 1]);
- for (size_t i = 0; i < vcont.size(); ++i)
- {
- ExternalCacheItem *extItem = dynamic_cast(vcont[i].get());
- NVCV_ASSERT(extItem != nullptr);
+ std::unique_ptr out(new ICacheItem *[vcont.size() + 1]);
+ for (size_t i = 0; i < vcont.size(); ++i)
+ {
+ ExternalCacheItem *extItem = dynamic_cast(vcont[i].get());
+ NVCV_ASSERT(extItem != nullptr);
- out[i] = extItem->obj.get();
- }
- out[vcont.size()] = nullptr; // end of list
+ out[i] = extItem->obj.get();
+ }
+ out[vcont.size()] = nullptr; // end of list
- return out.release();
+ return out.release();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Cache add fetch failed")
}
extern "C" PyObject *ImplImage_Create(int32_t width, int32_t height, NVCVImageFormat fmt, int32_t rowAlign)
{
- std::shared_ptr img = Image::Create({width, height}, nvcv::ImageFormat{fmt}, rowAlign);
- return py::cast(std::move(img)).release().ptr();
+ try
+ {
+ std::shared_ptr img = Image::Create({width, height}, nvcv::ImageFormat{fmt}, rowAlign);
+ return py::cast(std::move(img)).release().ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Image create failed")
}
extern "C" NVCVImageHandle ImplImage_GetHandle(PyObject *img)
{
- return ToSharedObj(img)->impl().handle();
+ try
+ {
+ return ToSharedObj(img)->impl().handle();
+ }
+ CATCH_RETURN_DEFAULT(0, "Image get handle failed")
}
extern "C" PyObject *ImplContainer_Create(nvcvpy::Container *pcont)
{
- NVCV_ASSERT(pcont != nullptr);
- auto cont = std::make_shared(*pcont);
+ try
+ {
+ NVCV_ASSERT(pcont != nullptr);
+ auto cont = std::make_shared(*pcont);
- py::object ocont = py::cast(cont);
- return ocont.release().ptr();
+ py::object ocont = py::cast(cont);
+ return ocont.release().ptr();
+ }
+ CATCH_RETURN_DEFAULT(nullptr, "Container create failed")
}
extern "C" void ImplCache_RemoveAllNotInUseMatching(const IKey *pkey)
{
- NVCV_ASSERT(pkey != nullptr);
+ try
+ {
+ NVCV_ASSERT(pkey != nullptr);
- Cache::Instance().removeAllNotInUseMatching(*pkey);
+ Cache::Instance().removeAllNotInUseMatching(*pkey);
+ }
+ CATCH_RETURN_DEFAULT(, "Cache cleanup failed when removing all not in use matching")
}
} // namespace
+// Note these functions will set a PyError if an exception is thrown, this must be then checked by calling
+// CheckCAPIError() before returning to Python.
void ExportCAPI(py::module &m)
{
static CAPI capi = {
diff --git a/python/mod_nvcv/DataType.cpp b/python/mod_nvcv/DataType.cpp
index ac1c42908..10baef79e 100644
--- a/python/mod_nvcv/DataType.cpp
+++ b/python/mod_nvcv/DataType.cpp
@@ -221,7 +221,8 @@ py::dtype SelectDType(std::tuple, const nvcv::DataType &dtype)
}
} // namespace
- //
+
+//
std::optional ToNVCVDataType(const py::dtype &dt)
{
diff --git a/python/mod_nvcv/Image.cpp b/python/mod_nvcv/Image.cpp
index 393937306..15ffe6730 100644
--- a/python/mod_nvcv/Image.cpp
+++ b/python/mod_nvcv/Image.cpp
@@ -1069,7 +1069,7 @@ void Image::Export(py::module &m)
{
using namespace py::literals;
- py::class_, Container>(m, "Image")
+ py::class_, Container>(m, "Image", "Image")
.def(py::init(&Image::Create), "size"_a, "format"_a, "rowalign"_a = 0,
"Constructor that takes a size, format and optional row align of the image")
.def(py::init(&Image::CreateHost), "buffer"_a, "format"_a = nvcv::FMT_NONE, "rowalign"_a = 0,
diff --git a/python/mod_nvcv/ImageBatch.cpp b/python/mod_nvcv/ImageBatch.cpp
index c0595b22b..38c838093 100644
--- a/python/mod_nvcv/ImageBatch.cpp
+++ b/python/mod_nvcv/ImageBatch.cpp
@@ -189,7 +189,8 @@ void ImageBatchVarShape::Export(py::module &m)
{
using namespace py::literals;
- py::class_, Container>(m, "ImageBatchVarShape")
+ py::class_, Container>(m, "ImageBatchVarShape",
+ "Batch of Images.")
.def(py::init(&ImageBatchVarShape::Create), "capacity"_a,
"Create a new ImageBatchVarShape object with the specified capacity.")
.def_property_readonly("uniqueformat", &ImageBatchVarShape::uniqueFormat,
diff --git a/python/mod_nvcv/Main.cpp b/python/mod_nvcv/Main.cpp
index 372f02a24..18d0a4485 100644
--- a/python/mod_nvcv/Main.cpp
+++ b/python/mod_nvcv/Main.cpp
@@ -37,13 +37,6 @@ namespace py = pybind11;
PYBIND11_MODULE(nvcv, m)
{
- m.doc() = R"pbdoc(
- NVCV Python API reference
- ========================
-
- This is the Python API reference for the NVIDIA® NVCV library.
- )pbdoc";
-
m.attr("__version__") = NVCV_VERSION_STRING;
using namespace nvcvpy::priv;
@@ -59,10 +52,10 @@ PYBIND11_MODULE(nvcv, m)
ExternalBuffer::Export(m);
// Supporting objects
+ ExportColorSpec(m);
ExportImageFormat(m);
ExportDataType(m);
ExportRect(m);
- ExportColorSpec(m);
// Objects
Tensor::Export(m);
diff --git a/python/mod_nvcv/Rect.cpp b/python/mod_nvcv/Rect.cpp
index 3d38f64e5..01e6bc003 100644
--- a/python/mod_nvcv/Rect.cpp
+++ b/python/mod_nvcv/Rect.cpp
@@ -31,7 +31,7 @@ void ExportRect(py::module &m)
{
using namespace py::literals;
- py::class_(m, "RectI")
+ py::class_(m, "RectI", "RectI")
.def(py::init([]() { return NVCVRectI{}; }), "Default constructor")
.def(py::init(
[](int x, int y, int w, int h)
diff --git a/python/mod_nvcv/Tensor.cpp b/python/mod_nvcv/Tensor.cpp
index ea21d08af..99d01cc57 100644
--- a/python/mod_nvcv/Tensor.cpp
+++ b/python/mod_nvcv/Tensor.cpp
@@ -390,7 +390,7 @@ void Tensor::Export(py::module &m)
py::implicitly_convertible();
- py::class_, Container>(m, "Tensor")
+ py::class_, Container>(m, "Tensor", "Tensor")
.def(py::init(&Tensor::CreateForImageBatch), "nimages"_a, "imgsize"_a, "format"_a, "rowalign"_a = 0,
"Create a Tensor object for an ImageBatch.")
.def(py::init(&Tensor::Create), "shape"_a, "dtype"_a, "layout"_a = std::nullopt, "rowalign"_a = 0,
diff --git a/python/mod_nvcv/TensorBatch.cpp b/python/mod_nvcv/TensorBatch.cpp
index 99d514970..2e838c735 100644
--- a/python/mod_nvcv/TensorBatch.cpp
+++ b/python/mod_nvcv/TensorBatch.cpp
@@ -229,8 +229,7 @@ void TensorBatch::Export(py::module &m)
"The capacity of the container must be specified upfront in the batch initialization.\n"
"The tensors in the batch may differ in shapes but they must have "
"a uniform dimensionality, data type and layout.")
- .def(py::init(&TensorBatch::Create),
- "capacity"_a
+ .def(py::init(&TensorBatch::Create), "capacity"_a,
"Create a new TensorBatch object with the specified capacity.")
.def_property_readonly("layout", &TensorBatch::layout,
"Layout of the tensors in the tensor batch."
diff --git a/python/mod_nvcv/include/nvcv/python/Array.hpp b/python/mod_nvcv/include/nvcv/python/Array.hpp
index 5d3d2bcfe..e80a6a5e8 100644
--- a/python/mod_nvcv/include/nvcv/python/Array.hpp
+++ b/python/mod_nvcv/include/nvcv/python/Array.hpp
@@ -23,6 +23,7 @@
#include "Resource.hpp"
#include "Shape.hpp"
+#include
#include
#include
#include
@@ -41,9 +42,9 @@ class Array
static Array Create(int64_t length, nvcv::DataType dtype)
{
PyObject *oarray = capi().Array_Create(length, dtype);
-
+ CheckCAPIError();
+ NVCV_ASSERT(oarray == nullptr);
py::object pyarray = py::reinterpret_steal(oarray);
-
return Array(pyarray);
}
@@ -59,7 +60,7 @@ class Array
explicit Array(py::object obj)
: Resource(obj)
- , nvcv::Array(FromHandle(capi().Array_GetHandle(this->ptr()), true))
+ , nvcv::Array(FromHandle(CheckCAPIError(capi().Array_GetHandle(this->ptr())), true))
{
}
};
diff --git a/python/mod_nvcv/include/nvcv/python/CAPI.hpp b/python/mod_nvcv/include/nvcv/python/CAPI.hpp
index 664ed87b5..612d6583f 100644
--- a/python/mod_nvcv/include/nvcv/python/CAPI.hpp
+++ b/python/mod_nvcv/include/nvcv/python/CAPI.hpp
@@ -98,6 +98,26 @@ inline const CAPI &capi()
return *capi;
}
+/* Check for an error inside the CAPI, since exceptions cannot cross the C api
+ * boundary, this must be called to make sure en exception was not converted to
+ * a PyErr
+ */
+inline void CheckCAPIError()
+{
+ if (PyErr_Occurred())
+ {
+ // Propagate the exception to Python
+ throw pybind11::error_already_set();
+ }
+};
+
+template
+decltype(auto) CheckCAPIError(T &&arg)
+{
+ CheckCAPIError();
+ return std::forward(arg);
+}
+
} // namespace nvcvpy
#endif // NVCV_PYTHON_CAPI_HPP
diff --git a/python/mod_nvcv/include/nvcv/python/Cache.hpp b/python/mod_nvcv/include/nvcv/python/Cache.hpp
index 66aec85c2..8ef8017e2 100644
--- a/python/mod_nvcv/include/nvcv/python/Cache.hpp
+++ b/python/mod_nvcv/include/nvcv/python/Cache.hpp
@@ -72,6 +72,7 @@ class Cache
static void add(ICacheItem &item)
{
capi().Cache_Add(&item);
+ CheckCAPIError();
}
static std::vector> fetch(const IKey &key)
@@ -80,6 +81,7 @@ class Cache
{
capi().Cache_Fetch(&key)
};
+ CheckCAPIError();
std::vector> out;
for (int i = 0; list[i]; ++i)
@@ -92,6 +94,7 @@ class Cache
static void removeAllNotInUseMatching(const IKey &key)
{
capi().Cache_RemoveAllNotInUseMatching(&key);
+ CheckCAPIError();
}
};
diff --git a/python/mod_nvcv/include/nvcv/python/Container.hpp b/python/mod_nvcv/include/nvcv/python/Container.hpp
index fc0eb0a98..b774420d1 100644
--- a/python/mod_nvcv/include/nvcv/python/Container.hpp
+++ b/python/mod_nvcv/include/nvcv/python/Container.hpp
@@ -22,6 +22,7 @@
#include "Cache.hpp"
#include "Resource.hpp"
+#include
#include
namespace nvcvpy {
@@ -39,8 +40,12 @@ class Container
}
explicit Container()
- : Resource(py::reinterpret_steal(capi().Container_Create(this)))
{
+ PyObject *raw_obj = capi().Container_Create(this);
+ CheckCAPIError();
+ NVCV_ASSERT(raw_obj != nullptr);
+ py::object temp = py::reinterpret_steal(raw_obj);
+ new (static_cast(this)) Resource(temp);
}
};
diff --git a/python/mod_nvcv/include/nvcv/python/DataType.hpp b/python/mod_nvcv/include/nvcv/python/DataType.hpp
index 2f79674f8..c7d6bca62 100644
--- a/python/mod_nvcv/include/nvcv/python/DataType.hpp
+++ b/python/mod_nvcv/include/nvcv/python/DataType.hpp
@@ -34,13 +34,16 @@ struct type_caster
bool load(handle src, bool)
{
NVCVDataType p = cvpy::capi().DataType_FromPython(src.ptr());
- value = nvcv::DataType(p);
+ cvpy::CheckCAPIError();
+ value = nvcv::DataType(p);
return true;
}
static handle cast(nvcv::DataType type, return_value_policy /* policy */, handle /*parent */)
{
- return cvpy::capi().DataType_ToPython(static_cast(type));
+ handle out = cvpy::capi().DataType_ToPython(static_cast(type));
+ cvpy::CheckCAPIError();
+ return out;
}
};
diff --git a/python/mod_nvcv/include/nvcv/python/Image.hpp b/python/mod_nvcv/include/nvcv/python/Image.hpp
index b56463e0a..58b15dc30 100644
--- a/python/mod_nvcv/include/nvcv/python/Image.hpp
+++ b/python/mod_nvcv/include/nvcv/python/Image.hpp
@@ -21,6 +21,7 @@
#include "CAPI.hpp"
#include "Resource.hpp"
+#include
#include
#include
#include
@@ -48,7 +49,8 @@ class Image
static Image Create(nvcv::Size2D size, nvcv::ImageFormat fmt, int rowAlign = 0)
{
PyObject *oimg = capi().Image_Create(size.w, size.h, static_cast(fmt), rowAlign);
-
+ CheckCAPIError();
+ NVCV_ASSERT(oimg != nullptr);
py::object pyimg = py::reinterpret_steal(oimg);
return Image(pyimg);
@@ -62,7 +64,7 @@ class Image
explicit Image(py::object obj)
: Resource(obj)
- , nvcv::Image(FromHandle(capi().Image_GetHandle(this->ptr()), true))
+ , nvcv::Image(FromHandle(CheckCAPIError(capi().Image_GetHandle(this->ptr())), true))
{
}
};
diff --git a/python/mod_nvcv/include/nvcv/python/ImageBatchVarShape.hpp b/python/mod_nvcv/include/nvcv/python/ImageBatchVarShape.hpp
index 86f8ec06d..24bf0d2f0 100644
--- a/python/mod_nvcv/include/nvcv/python/ImageBatchVarShape.hpp
+++ b/python/mod_nvcv/include/nvcv/python/ImageBatchVarShape.hpp
@@ -21,6 +21,7 @@
#include "CAPI.hpp"
#include "Resource.hpp"
+#include
#include
#include
@@ -38,7 +39,8 @@ class ImageBatchVarShape
static ImageBatchVarShape Create(int capacity)
{
PyObject *ovarshape = capi().ImageBatchVarShape_Create(capacity);
-
+ CheckCAPIError();
+ NVCV_ASSERT(ovarshape != nullptr);
py::object pyvarshape = py::reinterpret_steal(ovarshape);
return ImageBatchVarShape(pyvarshape);
@@ -55,16 +57,19 @@ class ImageBatchVarShape
void pushBack(Image img)
{
capi().ImageBatchVarShape_PushBack(this->ptr(), img.ptr());
+ CheckCAPIError();
}
void popBack(int cnt)
{
capi().ImageBatchVarShape_PopBack(this->ptr(), cnt);
+ CheckCAPIError();
}
void clear()
{
capi().ImageBatchVarShape_Clear(this->ptr());
+ CheckCAPIError();
}
// By default we use the varshape interface.
@@ -81,7 +86,7 @@ class ImageBatchVarShape
explicit ImageBatchVarShape(py::object obj)
: Resource(obj)
- , nvcv::ImageBatchVarShape(FromHandle(capi().ImageBatchVarShape_GetHandle(this->ptr()), true))
+ , nvcv::ImageBatchVarShape(FromHandle(CheckCAPIError(capi().ImageBatchVarShape_GetHandle(this->ptr())), true))
{
}
};
diff --git a/python/mod_nvcv/include/nvcv/python/ImageFormat.hpp b/python/mod_nvcv/include/nvcv/python/ImageFormat.hpp
index 43ff55b37..366f5a011 100644
--- a/python/mod_nvcv/include/nvcv/python/ImageFormat.hpp
+++ b/python/mod_nvcv/include/nvcv/python/ImageFormat.hpp
@@ -34,13 +34,16 @@ struct type_caster
bool load(handle src, bool)
{
NVCVImageFormat p = cvpy::capi().ImageFormat_FromPython(src.ptr());
- value = nvcv::ImageFormat(p);
+ cvpy::CheckCAPIError();
+ value = nvcv::ImageFormat(p);
return true;
}
static handle cast(nvcv::ImageFormat type, return_value_policy /* policy */, handle /*parent */)
{
- return cvpy::capi().ImageFormat_ToPython(static_cast(type));
+ handle out = cvpy::capi().ImageFormat_ToPython(static_cast(type));
+ cvpy::CheckCAPIError();
+ return out;
}
};
diff --git a/python/mod_nvcv/include/nvcv/python/ResourceGuard.hpp b/python/mod_nvcv/include/nvcv/python/ResourceGuard.hpp
index 5ad2bae5d..0be46ff66 100644
--- a/python/mod_nvcv/include/nvcv/python/ResourceGuard.hpp
+++ b/python/mod_nvcv/include/nvcv/python/ResourceGuard.hpp
@@ -63,6 +63,7 @@ class ResourceGuard
{
py::object pyRes = r.get();
capi().Resource_SubmitSync(pyRes.ptr(), m_pyStream.ptr());
+ CheckCAPIError();
m_resourcesPerLockMode.append(std::make_pair(pyLockMode, std::move(pyRes)));
}
@@ -72,6 +73,7 @@ class ResourceGuard
void commit()
{
capi().Stream_HoldResources(m_pyStream.ptr(), m_resourcesPerLockMode.ptr());
+ CheckCAPIError();
}
private:
diff --git a/python/mod_nvcv/include/nvcv/python/Stream.hpp b/python/mod_nvcv/include/nvcv/python/Stream.hpp
index d55ca6f90..38ef51700 100644
--- a/python/mod_nvcv/include/nvcv/python/Stream.hpp
+++ b/python/mod_nvcv/include/nvcv/python/Stream.hpp
@@ -20,6 +20,7 @@
#include "CAPI.hpp"
+#include
#include
namespace nvcvpy {
@@ -33,12 +34,17 @@ class Stream : public py::object
static Stream Current()
{
- return Stream(py::reinterpret_borrow(capi().Stream_GetCurrent()));
+ py::object temp = py::reinterpret_borrow(capi().Stream_GetCurrent());
+ CheckCAPIError();
+ NVCV_ASSERT(temp.is_none() == false);
+ return Stream(temp);
}
cudaStream_t cudaHandle() const
{
- return capi().Stream_GetCudaHandle(this->ptr());
+ cudaStream_t out = capi().Stream_GetCudaHandle(this->ptr());
+ CheckCAPIError();
+ return out;
}
private:
diff --git a/python/mod_nvcv/include/nvcv/python/Tensor.hpp b/python/mod_nvcv/include/nvcv/python/Tensor.hpp
index 63fff4830..e3ba66053 100644
--- a/python/mod_nvcv/include/nvcv/python/Tensor.hpp
+++ b/python/mod_nvcv/include/nvcv/python/Tensor.hpp
@@ -23,6 +23,7 @@
#include "Resource.hpp"
#include "Shape.hpp"
+#include
#include
#include
#include
@@ -43,7 +44,8 @@ class Tensor
{
PyObject *otensor = capi().Tensor_Create(tshape.size(), &tshape[0], static_cast(dtype),
static_cast(tshape.layout()), rowalign);
-
+ CheckCAPIError();
+ NVCV_ASSERT(otensor != nullptr);
py::object pytensor = py::reinterpret_steal(otensor);
return Tensor(pytensor);
@@ -59,7 +61,8 @@ class Tensor
{
PyObject *otensor
= capi().Tensor_CreateForImageBatch(numImages, size.w, size.h, static_cast(fmt), rowalign);
-
+ CheckCAPIError();
+ NVCV_ASSERT(otensor != nullptr);
py::object pytensor = py::reinterpret_steal(otensor);
return Tensor(pytensor);
@@ -72,7 +75,7 @@ class Tensor
explicit Tensor(py::object obj)
: Resource(obj)
- , nvcv::Tensor(FromHandle(capi().Tensor_GetHandle(this->ptr()), true))
+ , nvcv::Tensor(FromHandle(CheckCAPIError(capi().Tensor_GetHandle(this->ptr())), true))
{
}
};
diff --git a/python/mod_nvcv/include/nvcv/python/TensorBatch.hpp b/python/mod_nvcv/include/nvcv/python/TensorBatch.hpp
index b13e184f7..c6bf604b4 100644
--- a/python/mod_nvcv/include/nvcv/python/TensorBatch.hpp
+++ b/python/mod_nvcv/include/nvcv/python/TensorBatch.hpp
@@ -21,6 +21,7 @@
#include "CAPI.hpp"
#include "Resource.hpp"
+#include
#include
#include
@@ -38,7 +39,8 @@ class TensorBatch
static TensorBatch Create(int capacity)
{
PyObject *tensorBatch = capi().TensorBatch_Create(capacity);
-
+ CheckCAPIError();
+ NVCV_ASSERT(tensorBatch != nullptr);
py::object pytensorBatch = py::reinterpret_steal(tensorBatch);
return TensorBatch(pytensorBatch);
@@ -47,16 +49,19 @@ class TensorBatch
void pushBack(Tensor tensor)
{
capi().TensorBatch_PushBack(this->ptr(), tensor.ptr());
+ CheckCAPIError();
}
void popBack(int cnt)
{
capi().TensorBatch_PopBack(this->ptr(), cnt);
+ CheckCAPIError();
}
void clear()
{
capi().TensorBatch_Clear(this->ptr());
+ CheckCAPIError();
}
using nvcv::TensorBatch::operator[];
@@ -70,7 +75,7 @@ class TensorBatch
explicit TensorBatch(py::object obj)
: Resource(obj)
- , nvcv::TensorBatch(FromHandle(capi().TensorBatch_GetHandle(this->ptr()), true))
+ , nvcv::TensorBatch(FromHandle(CheckCAPIError(capi().TensorBatch_GetHandle(this->ptr())), true))
{
}
};
diff --git a/python/setup.py.in b/python/setup.py.in
index c22e9d0ff..b88d9bc74 100644
--- a/python/setup.py.in
+++ b/python/setup.py.in
@@ -66,7 +66,7 @@ setup(
"": ["*.so", "cvcuda.libs/*.*"]
}, # Includes the binding .so + core .so files
include_package_data=True,
- install_requires=["numpy>=1.23.5"],
+ install_requires=["numpy>=1.23.5,<2.0.0"],
python_requires="==${PYTHON_VERSION}.*",
zip_safe=False,
cmdclass={
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index 806192fe1..d3767378a 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,6 +35,8 @@ set(PYSAMPLES classification
object_detection
label)
+# Append extra (proprietary) samples
+
foreach(sample ${CPPSAMPLES})
add_subdirectory(${sample})
endforeach()
diff --git a/samples/common/python/nvcodec_utils.py b/samples/common/python/nvcodec_utils.py
index 420e15fe2..36f5c4de7 100644
--- a/samples/common/python/nvcodec_utils.py
+++ b/samples/common/python/nvcodec_utils.py
@@ -614,12 +614,12 @@ def __call__(self, batch):
assert isinstance(batch.data, torch.Tensor)
- image_tensors_nchw = batch.data
+ image_tensors_nhwc = batch.data
# Create an empty list to store filenames
filenames = []
- chwtensor_list = []
+ hwctensor_list = []
# Iterate through each image to prepare the filenames
- for img_idx in range(image_tensors_nchw.shape[0]):
+ for img_idx in range(image_tensors_nhwc.shape[0]):
img_name = os.path.splitext(os.path.basename(batch.fileinfo[img_idx]))[0]
results_path = os.path.join(self.output_path, f"out_{img_name}.jpg")
self.logger.info(f"Preparing to save the image to: {results_path}")
@@ -627,10 +627,10 @@ def __call__(self, batch):
filenames.append(results_path)
# Add the image tensor CAI to a CAI list from an NCHW tensor
# (this was a stacked tensor if N images)
- chwtensor_list.append(image_tensors_nchw[img_idx].cuda())
+ hwctensor_list.append(image_tensors_nhwc[img_idx].cuda())
# Pass the image tensors and filenames to the encoder.
- self.encoder.write(filenames, chwtensor_list)
+ self.encoder.write(filenames, hwctensor_list)
self.cvcuda_perf.pop_range()
# docs_tag: end_call_imagebatchencoder_nvimagecodec
diff --git a/samples/scripts/run_samples.sh b/samples/scripts/run_samples.sh
index 40fae3cb9..f7f17b5b2 100755
--- a/samples/scripts/run_samples.sh
+++ b/samples/scripts/run_samples.sh
@@ -28,13 +28,13 @@ SAMPLES_DIR="$(dirname "$SCRIPT_DIR")"
CLASSIFICATION_OUT_DIR=/tmp/classification
SEGMENTATION_OUT_DIR="/tmp/segmentation"
DETECTION_OUT_DIR="/tmp/object_detection"
-DISTANCE_LABEL_OUT_DIR="/tmp/distance_label"
+LABEL_OUT_DIR="/tmp/label"
echo "SAMPLES_DIR: $SAMPLES_DIR"
echo "CLASSIFICATION_OUT_DIR: $CLASSIFICATION_OUT_DIR"
echo "SEGMENTATION_OUT_DIR: $SEGMENTATION_OUT_DIR"
echo "DETECTION_OUT_DIR: $DETECTION_OUT_DIR"
-echo "DISTANCE_LABEL_OUT_DIR: $DISTANCE_LABEL_OUT_DIR"
+echo "LABEL_OUT_DIR: $LABEL_OUT_DIR"
create_output_dir() {
local base_dir=$1
@@ -128,11 +128,11 @@ python3 $SAMPLES_DIR/object_detection/python/main.py -i $SAMPLES_DIR/assets/imag
DETECTION_RUN_DIR=$(create_output_dir "$DETECTION_OUT_DIR")
python3 $SAMPLES_DIR/object_detection/python/main.py -i $SAMPLES_DIR/assets/videos/pexels-chiel-slotman-4423925-1920x1080-25fps.mp4 -b 4 -bk tensorflow -o "$DETECTION_RUN_DIR"
-# Run the distance label Python sample with default settings, without any command-line args.
-rm -rf "$DISTANCE_LABEL_OUT_DIR"
-mkdir "$DISTANCE_LABEL_OUT_DIR"
-DISTANCE_LABEL_RUN_DIR=$(create_output_dir "$DISTANCE_LABEL_OUT_DIR")
-python3 $SAMPLES_DIR/label/python/main.py -o "$DISTANCE_LABEL_RUN_DIR"
+# Run the label Python sample with default settings, without any command-line args.
+rm -rf "$LABEL_OUT_DIR"
+mkdir "$LABEL_OUT_DIR"
+LABEL_RUN_DIR=$(create_output_dir "$LABEL_OUT_DIR")
+python3 $SAMPLES_DIR/label/python/main.py -o "$LABEL_RUN_DIR"
# Run it with batch size 1 on a single image
-DISTANCE_LABEL_RUN_DIR=$(create_output_dir "$DISTANCE_LABEL_OUT_DIR")
-python3 $SAMPLES_DIR/label/python/main.py -i $SAMPLES_DIR/assets/images/peoplenet.jpg -b 1 -o "$DISTANCE_LABEL_RUN_DIR"
+LABEL_RUN_DIR=$(create_output_dir "$LABEL_OUT_DIR")
+python3 $SAMPLES_DIR/label/python/main.py -i $SAMPLES_DIR/assets/images/peoplenet.jpg -b 1 -o "$LABEL_RUN_DIR"
diff --git a/src/cvcuda/OpResizeCropConvertReformat.cpp b/src/cvcuda/OpResizeCropConvertReformat.cpp
index 2db154d6f..4da7dd2cc 100644
--- a/src/cvcuda/OpResizeCropConvertReformat.cpp
+++ b/src/cvcuda/OpResizeCropConvertReformat.cpp
@@ -44,21 +44,21 @@ CVCUDA_DEFINE_API(0, 8, NVCVStatus, cvcudaResizeCropConvertReformatCreate, (NVCV
CVCUDA_DEFINE_API(0, 8, NVCVStatus, cvcudaResizeCropConvertReformatSubmit,
(NVCVOperatorHandle handle, cudaStream_t stream, NVCVTensorHandle in, NVCVTensorHandle out,
const NVCVSize2D resizeDim, const NVCVInterpolationType interpolation, const int2 cropPos,
- const NVCVChannelManip manip))
+ const NVCVChannelManip manip, const float scale, const float offset))
{
return nvcv::ProtectCall(
[&]
{
nvcv::TensorWrapHandle input(in), output(out);
priv::ToDynamicRef(handle)(stream, input, output, resizeDim, interpolation,
- cropPos, manip);
+ cropPos, manip, scale, offset);
});
}
CVCUDA_DEFINE_API(0, 8, NVCVStatus, cvcudaResizeCropConvertReformatVarShapeSubmit,
(NVCVOperatorHandle handle, cudaStream_t stream, NVCVImageBatchHandle in, NVCVTensorHandle out,
const NVCVSize2D resizeDim, const NVCVInterpolationType interpolation, const int2 cropPos,
- const NVCVChannelManip manip))
+ const NVCVChannelManip manip, const float scale, const float offset))
{
return nvcv::ProtectCall(
[&]
@@ -66,6 +66,6 @@ CVCUDA_DEFINE_API(0, 8, NVCVStatus, cvcudaResizeCropConvertReformatVarShapeSubmi
nvcv::ImageBatchVarShapeWrapHandle input(in);
nvcv::TensorWrapHandle output(out);
priv::ToDynamicRef(handle)(stream, input, output, resizeDim, interpolation,
- cropPos, manip);
+ cropPos, manip, scale, offset);
});
}
diff --git a/src/cvcuda/include/cvcuda/OpResizeCropConvertReformat.h b/src/cvcuda/include/cvcuda/OpResizeCropConvertReformat.h
index 041ff8003..ca27f038f 100644
--- a/src/cvcuda/include/cvcuda/OpResizeCropConvertReformat.h
+++ b/src/cvcuda/include/cvcuda/OpResizeCropConvertReformat.h
@@ -19,7 +19,7 @@
* @file OpResizeCropConvertReformat.h
*
* @brief Defines functions that fuses resize, crop, data type conversion, channel manipulation, and layout reformat operations to optimize pipelines.
- * @defgroup NVCV_C_ALGORITHM__RESIZE_CROP Resize Crop
+ * @defgroup NVCV_C_ALGORITHM__RESIZE_CROP Resize Crop Convert
* @{
*/
@@ -53,30 +53,58 @@ extern "C"
*/
CVCUDA_PUBLIC NVCVStatus cvcudaResizeCropConvertReformatCreate(NVCVOperatorHandle *handle);
-/** Executes the ResizeCropConvertReformat operation on the given cuda stream. This operation
- * does not wait for completion.
+/** Executes the fused ResizeCropConvertReformat operation on the given cuda
+ * stream. This operation does not wait for completion.
*
- * ResizeCropConvertReformat performs the following operations in order:
- * 1) Resize either a single tensor or each image in an ImageBatchVarShape
+ * ResizeCropConvertReformat is a fused operator that performs the following
+ * operations in order:
+ *
+ * 1. Resize either a single tensor or each image in an ImageBatchVarShape
* to a specified width and height (other dimensions are unchanged).
- * 2) Crops a specified region of size width x height (determined by the
- * output tensor's width & height) starting at the pixel position
- * (cropPos.x, cropPos.y) out of the resized tensor.
- * 3) Convert the element data type to the output tensor's data type. For
- * example, convert uchar elements to float. Limited options availble.
- * 4) Optional channel manipulation--i.e., re-order the channels
+ * This step is identical to the stand-alone Resize operation with the
+ * exception of optionally not type-casting the interpolation results
+ * back to the input data type (see the srcCast parameter for details).
+ *
+ * 2. Crops a specified region out of the resized tensor.
+ *
+ * 3. Apply a scale and offset to output result (after resizing and
+ * cropping). This can be used to normalize to a new range of values.
+ * For example, if the input is unsigned 8-bit values and the output is
+ * floating point, setting scale = 1.0/127.5 and offset = -1.0 will
+ * convert the 8-bit input values (ranging from 0 to 255) to floating
+ * point output values between -1.0 and 1.0.
+ *
+ * 4. Optional channel manipulation--i.e., re-order the channels
* of a tensor (e.g., RGB to BGR). Limited options available.
- * 5) If output tensor's layout doesn't match the input's layout, reshape
+ *
+ * 5. Convert the element data type to the output tensor's data type. For
+ * example, convert uchar elements to float. Limited options availble.
+ *
+ * 6. If output tensor's layout doesn't match the input's layout, reshape
* the layout to match output layout (e.g., NHWC to NCHW). Limited
* options available.
- * NOTE: Since all images in an ImageBatchVarShape are resized to the
- * same size, the resulting collection now fits in a single tensor.
+ *
+ * NOTES:
+ * + Since all images in an ImageBatchVarShape are resized to the same size,
+ * the resulting collection now fits in a single tensor.
+ * + Except for nearest-neighbor interpolation (NVCV_INTERP_NEAREST),
+ * interpolation (e.g., NVCV_INTERP_LINEAR, NVCV_INTERP_CUBIC, and
+ * NVCV_INTERP_AREA) computes resized pixel values using floating point
+ * math. However, the stand-alone resize operation (i.e., running the
+ * standard Resize operator independently) converts interpolated pixel
+ * values back to the source data type since its input and output types
+ * must be the same. As an option, this fused operator can either cast
+ * the resized pixel values back to the source type (to match results
+ * from running the steps independently), or leave them in the
+ * interpolated floating-point space to avoid quantization issues that
+ * occur from casting back to an integer source type (e.g., uchar). See
+ * the srcCast parameter for details.
*
* Limitations:
*
- * Input: STILL NEED TO FILL THIS IN
- * Data Layout: [NVCV_TENSOR_HWC, NVCV_TENSOR_NHWC]
- * Channels: [1, 3]
+ * Input:
+ * + Data Layout: [NVCV_TENSOR_HWC, NVCV_TENSOR_NHWC]
+ * + Channels: [1, 3]
*
* Data Type | Allowed
* -------------- | -------------
@@ -90,9 +118,9 @@ CVCUDA_PUBLIC NVCVStatus cvcudaResizeCropConvertReformatCreate(NVCVOperatorHandl
* 64bit Float | No
*
* Output:
- * Data Layout: [NVCV_TENSOR_NHWC, NVCV_TENSOR_HWC,
- * NVCV_TENSOR_NCHW, NVCV_TENSOR_CHW]
- * Channels: [1, 3]
+ * + Data Layout: [NVCV_TENSOR_NHWC, NVCV_TENSOR_HWC,
+ * NVCV_TENSOR_NCHW, NVCV_TENSOR_CHW]
+ * + Channels: [1, 3]
*
* Data Type | Allowed
* -------------- | -------------
@@ -105,7 +133,7 @@ CVCUDA_PUBLIC NVCVStatus cvcudaResizeCropConvertReformatCreate(NVCVOperatorHandl
* 32bit Float | Yes
* 64bit Float | No
*
- * Input/Output dependency
+ * Input/Output dependency:
*
* Property | Input == Output
* -------------- | -------------
@@ -116,41 +144,75 @@ CVCUDA_PUBLIC NVCVStatus cvcudaResizeCropConvertReformatCreate(NVCVOperatorHandl
* Width | No
* Height | No
*
- * @param [in] handle Handle to the operator.
- * + Must not be NULL.
- * @param [in] stream Handle to a valid CUDA stream.
- *
- * @param [in] in Input tensor or image batch. The images in an image batch can be of different
- * sizes, but all images must have the same data type, channels, and layout.
- *
- * @param [in] resizeDim Dimensions, {width, height}, to resize the tensor method to be used,
- * see \ref NVCVSize2D for more details.
- *
- * @param [in] interpolation Interpolation method to be used, see \ref NVCVInterpolationType for
- * more details. Currently, only NVCV_INTERP_NEAREST and NVCV_INTERP_LINEAR
- * are available.
+ * @param [in] handle Handle to the operator. Must not be NULL.
*
- * @param [in] cropPos Crop position, (x, y), specifying the top-left corner of the crop region.
- * The crop region's width and height is specified by the output tensor's
- * width & height.
- * @note: The crop must fall within the resized image. Let (x, y, w, h)
- * represent the crop rectangle, where x & y are the cropPos coordinates
- * and w & h are the output tensor's width and height, then the following
- * must all be true:
- * x >= 0
- * y >= 0
- * x + w <= resizeDim.w
- * y + h <= resizeDim.h
- *
- *
- * @param [in] manip Channel manipulation to be used (e.g., reshuffle RGB to BGR),
- * see \ref NVCVChannelManip for more details.
- *
- * @param [out] out Output tensor. In addition to the output tensor determining the crop width
- * and height, the output tensor also specifies the data type (e.g., uchar3 or
- * float) and tensor layout (NHWC or NCHW), with limitations.
+ * @param [in] stream Handle to a valid CUDA stream.
*
- * @retval #NVCV_ERROR_INVALID_ARGUMENT Some parameter is outside valid range.
+ * @param [in] in Input tensor or image batch. The images in an image batch can
+ * be of different sizes, but all images must have the same data
+ * type, channels, and layout.
+ *
+ * @param [in] resizeDim Dimensions, {width, height}, that tensor or image
+ * batch images are resized to prior to cropping, see
+ * \ref NVCVSize2D for more details.
+ *
+ * @param [in] interpolation Interpolation method to be used, (see \ref
+ * NVCVInterpolationType). Currently, only
+ * NVCV_INTERP_NEAREST and NVCV_INTERP_LINEAR are
+ * available.
+ *
+ * @param [in] cropPos Crop position, (x, y), specifying the top-left corner of
+ * the crop region. The crop region's width and height is
+ * specified by the output tensor's width & height. The crop
+ * must fall within the resized image. Let (x, y, w, h)
+ * represent the crop rectangle, where x & y are the cropPos
+ * coordinates and w and h are the output tensor's width and
+ * height, respectively, then it must be true that:
+ * + x >= 0,
+ * + y >= 0,
+ * + x + w <= resizeDim.w, and
+ * + y + h <= resizeDim.h.
+ *
+ * @param [in] manip Channel manipulation to be used--e.g., reshuffle RGB to
+ * BGR (see \ref NVCVChannelManip).
+ *
+ * @param [in] scale Scale (i.e., multiply) the resized and cropped output
+ * values by this amount. 1.0 results in no scaling of the
+ * output values.
+ *
+ * @param [in] offset Offset (i.e., add to) the output values by this amount.
+ * This is applied after scaling--if v is a resized and
+ * cropped value, then scale * v + offset is the final output
+ * value. 0.0 results in no offset being added to the output.
+ *
+ * @param [in] srcCast Boolean value indicating whether or not the interpolation
+ * results during the resize are re-cast back to the input
+ * (or source) data type. Most interpolation methods (e.g.,
+ * NVCV_INTERP_LINEAR) compute resized pixel values using
+ * floating point math. This parameter determines if the
+ * interpolation result is cast to the source data type
+ * before computing the remaining steps in this operator:
+ * + true: the interpolation result is cast back to the
+ * source type prior to computing the remaining steps --
+ * as if calling the stand-alone Resize operator (since
+ * its input and output types must be the same). Note:
+ * this option can produce quantized outputs (e.g., the
+ * input source type is uchar3), even if the destination
+ * data type is floating point.
+ * + false: the interpolation result is NOT cast back to
+ * the source type. Rather, the floating-point
+ * interpolation results are directly passed on to the
+ * remaining steps in the fused operator.
+ * + Note: in either case (true or false) the final (fused)
+ * result is still cast to the destination data type
+ * before writing values into the output tensor.
+ *
+ * @param [out] out Output tensor. In addition to the output tensor determining
+ * the crop width and height, the output tensor also specifies
+ * the data type (e.g., uchar3 or float) and tensor layout
+ * (NHWC or NCHW), with limitations.
+ *
+ * @retval #NVCV_ERROR_INVALID_ARGUMENT Some parameter is invalid or outside valid range.
* @retval #NVCV_ERROR_INTERNAL Internal error in the operator, invalid types passed in.
* @retval #NVCV_SUCCESS Operation executed successfully.
*/
@@ -159,14 +221,15 @@ CVCUDA_PUBLIC NVCVStatus cvcudaResizeCropConvertReformatSubmit(NVCVOperatorHandl
NVCVTensorHandle in, NVCVTensorHandle out,
const NVCVSize2D resizeDim,
const NVCVInterpolationType interpolation,
- const int2 cropPos, const NVCVChannelManip manip);
+ const int2 cropPos, const NVCVChannelManip manip,
+ const float scale, const float offset, bool srcCast);
CVCUDA_PUBLIC NVCVStatus cvcudaResizeCropConvertReformatVarShapeSubmit(NVCVOperatorHandle handle, cudaStream_t stream,
NVCVImageBatchHandle in, NVCVTensorHandle out,
const NVCVSize2D resizeDim,
const NVCVInterpolationType interpolation,
- const int2 cropPos,
- const NVCVChannelManip manip);
+ const int2 cropPos, const NVCVChannelManip manip,
+ const float scale, float offset, bool srcCast);
/** @} */
#ifdef __cplusplus
diff --git a/src/cvcuda/include/cvcuda/OpResizeCropConvertReformat.hpp b/src/cvcuda/include/cvcuda/OpResizeCropConvertReformat.hpp
index 1e7fb143f..cbb13ee78 100644
--- a/src/cvcuda/include/cvcuda/OpResizeCropConvertReformat.hpp
+++ b/src/cvcuda/include/cvcuda/OpResizeCropConvertReformat.hpp
@@ -46,11 +46,13 @@ class ResizeCropConvertReformat final : public IOperator
void operator()(cudaStream_t stream, const nvcv::Tensor &in, const nvcv::Tensor &out, const NVCVSize2D resizeDim,
const NVCVInterpolationType interpolation, const int2 cropPos,
- const NVCVChannelManip manip = NVCV_CHANNEL_NO_OP);
+ const NVCVChannelManip manip = NVCV_CHANNEL_NO_OP, const float scale = 1, const float offset = 0,
+ const bool srcCast = true);
void operator()(cudaStream_t stream, const nvcv::ImageBatchVarShape &in, const nvcv::Tensor &out,
const NVCVSize2D resizeDim, const NVCVInterpolationType interpolation, const int2 cropPos,
- const NVCVChannelManip manip = NVCV_CHANNEL_NO_OP);
+ const NVCVChannelManip manip = NVCV_CHANNEL_NO_OP, const float scale = 1, const float offset = 0,
+ const bool srcCast = true);
virtual NVCVOperatorHandle handle() const noexcept override;
@@ -72,19 +74,21 @@ inline ResizeCropConvertReformat::~ResizeCropConvertReformat()
inline void ResizeCropConvertReformat::operator()(cudaStream_t stream, const nvcv::Tensor &in, const nvcv::Tensor &out,
const NVCVSize2D resizeDim, const NVCVInterpolationType interpolation,
- const int2 cropPos, const NVCVChannelManip manip)
+ const int2 cropPos, const NVCVChannelManip manip, const float scale,
+ const float offset, const bool srcCast)
{
- nvcv::detail::CheckThrow(cvcudaResizeCropConvertReformatSubmit(m_handle, stream, in.handle(), out.handle(),
- resizeDim, interpolation, cropPos, manip));
+ nvcv::detail::CheckThrow(cvcudaResizeCropConvertReformatSubmit(
+ m_handle, stream, in.handle(), out.handle(), resizeDim, interpolation, cropPos, manip, scale, offset, srcCast));
}
inline void ResizeCropConvertReformat::operator()(cudaStream_t stream, const nvcv::ImageBatchVarShape &in,
const nvcv::Tensor &out, const NVCVSize2D resizeDim,
const NVCVInterpolationType interpolation, const int2 cropPos,
- const NVCVChannelManip manip)
+ const NVCVChannelManip manip, const float scale, const float offset,
+ const bool srcCast)
{
- nvcv::detail::CheckThrow(cvcudaResizeCropConvertReformatVarShapeSubmit(m_handle, stream, in.handle(), out.handle(),
- resizeDim, interpolation, cropPos, manip));
+ nvcv::detail::CheckThrow(cvcudaResizeCropConvertReformatVarShapeSubmit(
+ m_handle, stream, in.handle(), out.handle(), resizeDim, interpolation, cropPos, manip, scale, offset, srcCast));
}
inline NVCVOperatorHandle ResizeCropConvertReformat::handle() const noexcept
diff --git a/src/cvcuda/priv/CMakeLists.txt b/src/cvcuda/priv/CMakeLists.txt
index 85683e409..488669f70 100644
--- a/src/cvcuda/priv/CMakeLists.txt
+++ b/src/cvcuda/priv/CMakeLists.txt
@@ -35,6 +35,7 @@ set(CV_CUDA_PRIV_OP_FILES
OpNonMaximumSuppression.cu
OpReformat.cpp
OpResize.cpp
+ OpResize.cu
OpCustomCrop.cpp
OpNormalize.cpp
OpPadAndStack.cpp
diff --git a/src/cvcuda/priv/OpAdvCvtColor.cu b/src/cvcuda/priv/OpAdvCvtColor.cu
index be97e77df..cac368e71 100644
--- a/src/cvcuda/priv/OpAdvCvtColor.cu
+++ b/src/cvcuda/priv/OpAdvCvtColor.cu
@@ -537,10 +537,20 @@ void AdvCvtColor::Yuv2Bgr(cudaStream_t stream, const nvcv::TensorDataStridedCuda
{
case legacy::kCV_8U:
{
- auto srcWrap = cuda::CreateTensorWrapNHWC(in);
- auto dstWrap = cuda::CreateTensorWrapNHWC(out);
- const YUV2RGBConstants &cooef = getYUV2RGBCooef(spec);
- yuv_to_bgr_char_nhwc<<>>(srcWrap, dstWrap, dstSize, bidx, cooef);
+ const YUV2RGBConstants &cooef = getYUV2RGBCooef(spec);
+ auto outMaxStride = outAccess->sampleStride() * outAccess->numSamples();
+ auto inMaxStride = inAccess->sampleStride() * inAccess->numSamples();
+ if (std::max(outMaxStride, inMaxStride) <= cuda::TypeTraits::max)
+ {
+ auto srcWrap = cuda::CreateTensorWrapNHWC(in);
+ auto dstWrap = cuda::CreateTensorWrapNHWC(out);
+ yuv_to_bgr_char_nhwc<<>>(srcWrap, dstWrap, dstSize, bidx, cooef);
+ }
+ else
+ {
+ throw nvcv::Exception(nvcv::Status::ERROR_OVERFLOW, "Input or output size exceeds %d. Tensor is too large.",
+ cuda::TypeTraits