Jetson OpenCV 4.14 CUDA Python Wheel 编译指南
Jetson OpenCV 4.14 CUDA Python Wheel 编译指南
本文记录在 NVIDIA Jetson Orin Nano / ARM64 / Ubuntu 24.04 环境下,从 OpenCV 源码编译带 CUDA、cuDNN、contrib、FFmpeg/GStreamer 支持的 Python wheel。
当前验证环境:
Jetson Orin Nano
Jetpack 7.2.1
Ubuntu 24.04
Python 3.12
CUDA 13.2
cuDNN 9.20
OpenCV 4.14.0
OpenCV-contrib 4.14.0
Python architecture: aarch64
CUDA architecture: 8.7
最终生成:
opencv_contrib_python-4.14.0+<revision>-cp312-cp312-linux_aarch64.whl
1. 原理和最终结果
最终的 Python 环境结构:
Conda / venv
│
├── Python 3.12
├── NumPy 2.x
│
└── cv2
│
├── OpenCV 4.14
├── OpenCV contrib
├── CUDA
├── cuDNN
├── NPP
├── cuBLAS
├── cuFFT
├── FFmpeg
├── GStreamer
└── 其他 OpenCV 模块
OpenCV 本身使用:
BUILD_SHARED_LIBS=OFF
因此 OpenCV 的核心代码会静态链接进:
cv2.abi3.so
但 CUDA、cuDNN、FFmpeg、GStreamer 等系统库仍然是动态依赖。
所以这个 wheel 是:
Python 包 + Jetson 系统动态库依赖
而不是一个完全自包含的 OpenCV。
2. 目录结构
推荐使用:
~/dev/opencv-wheel/opencv-python/
最终目录类似:
opencv-python/
├── opencv/
├── opencv_contrib/
├── opencv_extra/
├── cv2/
├── setup.py
├── pyproject.toml
├── find_version.py
├── patches/
├── scripts/
└── ...
其中:
opencv/
是 OpenCV 源码。
opencv_contrib/
是 OpenCV contrib 源码。
二者版本必须匹配。
例如:
OpenCV 4.14.0
OpenCV-contrib 4.14.0
3. 获取源码
准备一个版本,例如 OpenCV 4.14(已验证):
mkdir ~/dev
mkdir -p ~/dev/opencv-wheel
cd ~/dev/opencv-wheel
git clone --recursive https://github.com/opencv/opencv-python.git
cd opencv-python
git submodule status
会看到类似:
-xxxxxxxx opencv
-xxxxxxxx opencv_contrib
把4.14.0 源码接进去
cd ~/dev/opencv-wheel/opencv-python
rm -rf opencv opencv_contrib
git clone --branch 4.14.0 --depth 1 \
https://github.com/opencv/opencv.git opencv
git clone --branch 4.14.0 --depth 1 \
https://github.com/opencv/opencv_contrib.git opencv_contrib
如果源码里面存在:
opencv/build/
删除:
rm -rf ~/dev/opencv-wheel/opencv-python/opencv/build
原因是 CMake cache 可能保存旧版本、旧路径和旧编译器配置。
4. 准备 Python 环境
说明:本文使用 venv 作为 wheel 的构建环境;生成的 wheel 与具体虚拟环境无关,之后可以安装到 Conda 或 venv 环境中。本文第 14 节使用 Conda 进行独立安装验证。
sudo apt install -y python3.12-venv
python3 -m venv ~/venvs/opencv-wheel
source ~/venvs/opencv-wheel/bin/activate
安装 NumPy:
python -m pip install -U pip
python -m pip install numpy
确认:
python -c "import numpy; print(numpy.__version__)"
推荐 NumPy 2.x。
5. 安装编译依赖
根据当前 Jetson Ubuntu 系统安装基础工具:
sudo apt update
sudo apt install -y \
build-essential \
cmake \
ninja-build \
pkg-config \
git \
python3-dev \
python3-pip \
libgtk-3-dev \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
libswscale-dev \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libv4l-dev
Jetson 上优先使用 NVIDIA JetPack 提供的系统 CUDA。
检查:
nvcc --version
例如:
CUDA 13.2
检查 CUDA:
ls -ld /usr/local/cuda*
6. 使用 opencv-python packaging repository
进入:
cd ~/dev/opencv-wheel/opencv-python
确认:
ls
应该能看到:
opencv
opencv_contrib
setup.py
pyproject.toml
cv2
7. 关键环境变量
7.1 启用 contrib
export ENABLE_CONTRIB=1
setup.py 会自动加入:
-DOPENCV_EXTRA_MODULES_PATH=<opencv-python>/opencv_contrib/modules
因此:
不要自己再次添加 OPENCV_EXTRA_MODULES_PATH。
8. 防止 setup.py 修改你的源码
因为源码是手工放进去的,并不是 packaging repository 自己管理的 OpenCV submodule,所以设置:
export OPENCV_PYTHON_SKIP_GIT_COMMANDS=1
非常重要。
否则 setup.py 可能尝试:
git submodule sync
git submodule update
从而影响你自己准备的源码。
9. CMake 参数
推荐配置:
export CMAKE_ARGS="\
-DWITH_CUDA=ON \
-DWITH_CUBLAS=ON \
-DENABLE_FAST_MATH=ON \
-DCUDA_FAST_MATH=ON \
-DCUDA_ARCH_BIN=8.7 \
-DWITH_FFMPEG=ON \
-DWITH_GSTREAMER=ON \
-DWITH_V4L=ON \
-DWITH_OPENGL=ON \
-DWITH_QT=OFF \
-DOPENCV_ENABLE_NONFREE=ON \
-DBUILD_EXAMPLES=OFF \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_CXX_STANDARD_REQUIRED=ON"
参数说明
CUDA
-DWITH_CUDA=ON
启用 OpenCV CUDA。
-DWITH_CUBLAS=ON
启用 cuBLAS。
-DENABLE_FAST_MATH=ON
-DCUDA_FAST_MATH=ON
启用 CUDA fast math。
CUDA 架构
Orin Nano:
SM 8.7
因此:
-DCUDA_ARCH_BIN=8.7
如果以后换 Jetson 型号,需要根据 GPU Compute Capability 修改。
10. 不建议把 CUDA Toolkit 放进 wheel
不要为了“让 wheel 自包含”而把:
/usr/local/cuda-13.2/
整个打包进去。
Jetson 上应该使用系统 NVIDIA CUDA:
/usr/local/cuda-13.2/lib64
以及 JetPack 提供的:
cuDNN
NPP
CUDA driver
TensorRT
这样 wheel 才适合在同一 JetPack 软件栈的多个 Python 环境中复用。
11. 清理旧构建
每次换 OpenCV 版本、换 JetPack、换关键编译参数,都建议清理:
cd ~/dev/opencv-wheel/opencv-python
rm -rf _skbuild
rm -rf build
rm -rf dist
如果源码目录里面存在:
opencv/build
也删除:
rm -rf opencv/build
12. 开始构建 wheel
执行:
cd ~/dev/opencv-wheel/opencv-python
export ENABLE_CONTRIB=1
export OPENCV_PYTHON_SKIP_GIT_COMMANDS=1
export CMAKE_ARGS="\
-DWITH_CUDA=ON \
-DWITH_CUBLAS=ON \
-DENABLE_FAST_MATH=ON \
-DCUDA_FAST_MATH=ON \
-DCUDA_ARCH_BIN=8.7 \
-DWITH_FFMPEG=ON \
-DWITH_GSTREAMER=ON \
-DWITH_V4L=ON \
-DWITH_OPENGL=ON \
-DWITH_QT=OFF \
-DOPENCV_ENABLE_NONFREE=ON \
-DBUILD_EXAMPLES=OFF \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_CXX_STANDARD_REQUIRED=ON"
rm -rf _skbuild build dist
python -m pip wheel . --verbose
成功后:
ls -lh *.whl
例如:
opencv_contrib_python-4.14.0+031876b-cp312-cp312-linux_aarch64.whl
13. wheel 文件名怎么理解
例如:
opencv_contrib_python-4.14.0+031876b-cp312-cp312-linux_aarch64.whl
拆解:
opencv_contrib_python
│
└── OpenCV Python contrib package
4.14.0+031876b
│
└── OpenCV 版本 + 源码 revision
cp312
│
└── Python 3.12
cp312
│
└── CPython ABI
linux_aarch64
│
└── ARM64 Linux
因此它主要面向:
Python 3.12
Linux ARM64
14. 安装 wheel
例如conda:
conda create -n cv-test python=3.12
conda activate cv-test
安装 NumPy:
python -m pip install -U pip
python -m pip install numpy
安装自己的 wheel:
pip install ~/dev/opencv-wheel/opencv-python/opencv_contrib_python-4.14.0+031876b-cp312-cp312-linux_aarch64.whl
15. 基础验证
一定要在 OpenCV 源码目录之外测试。
例如:
cd /tmp
然后:
python - <<'PY'
import sys
import cv2
import numpy as np
print("Python :", sys.version)
print("OpenCV :", cv2.__version__)
print("NumPy :", np.__version__)
print("cv2 path :", cv2.__file__)
print("CUDA dev :", cv2.cuda.getCudaEnabledDeviceCount())
print("CUDA build info contains 13.2:", "13.2" in cv2.getBuildInformation())
PY
预期:
OpenCV : 4.14.0
NumPy : 2.x
CUDA dev : 1
CUDA build info contains 13.2: True
16. 检查 OpenCV 编译配置
执行:
python - <<'PY'
import cv2
print(cv2.getBuildInformation())
PY
重点确认:
NVIDIA CUDA: YES
cuDNN: YES
NVIDIA GPU arch: 87
FFMPEG: YES
GStreamer: YES
Python 3: YES
17. 检查动态库依赖
找到 cv2:
python - <<'PY'
import cv2
print(cv2.__file__)
PY
例如:
/home/jetson/miniforge3/envs/cv/lib/python3.12/site-packages/cv2/cv2.abi3.so
然后:
ldd /home/jetson/miniforge3/envs/cv/lib/python3.12/site-packages/cv2/cv2.abi3.so
检查是否存在:
not found
可以直接:
ldd "$(python -c 'import cv2; print(cv2.__file__)')" | grep "not found"
没有任何输出才是正常的。
18. 检查 CUDA 实际运行
仅仅:
cv2.cuda.getCudaEnabledDeviceCount()
只能证明 OpenCV 找到了 CUDA。
还应该进行实际 CUDA 运算。
测试:
cd /tmp
python - <<'PY'
import cv2
import numpy as np
import time
print("OpenCV:", cv2.__version__)
print("NumPy :", np.__version__)
print("CUDA devices:", cv2.cuda.getCudaEnabledDeviceCount())
img = np.random.randint(
0, 256, (1080, 1920, 3), dtype=np.uint8
)
gpu = cv2.cuda_GpuMat()
gpu.upload(img)
gauss = cv2.cuda.createGaussianFilter(
cv2.CV_8UC3,
cv2.CV_8UC3,
(15, 15),
0
)
for _ in range(10):
result = gauss.apply(gpu)
cv2.cuda.Stream_Null().waitForCompletion()
t0 = time.perf_counter()
for _ in range(100):
result = gauss.apply(gpu)
cv2.cuda.Stream_Null().waitForCompletion()
t1 = time.perf_counter()
print(f"100 CUDA Gaussian filters: {(t1-t0)*1000:.2f} ms")
print(f"Average: {(t1-t0)*10:.3f} ms/frame")
out = result.download()
print("Output shape:", out.shape)
print("Output dtype:", out.dtype)
print("CUDA test: OK")
PY
当前 Jetson Orin Nano 的实际测试结果:
CUDA devices: 1
100 CUDA Gaussian filters: 456.14 ms
Average: 4.561 ms/frame
Output shape: (1080, 1920, 3)
Output dtype: uint8
CUDA test: OK
19. auditwheel 检查
安装:
pip install auditwheel
然后:
auditwheel show \
~/dev/opencv-wheel/opencv-python/opencv_contrib_python-4.14.0+031876b-cp312-cp312-linux_aarch64.whl
实际标签取决于本机 glibc、系统库和 wheel 元数据,可能显示较高版本的 Linux ARM64 平台要求;请以 auditwheel show 的实际输出为准。
这并不意味着 wheel 有问题。
这是一个:
Jetson / JetPack 特定 wheel
而不是一个准备上传 PyPI、兼容所有 ARM64 Linux 的通用 wheel。
不要为了得到 manylinux wheel 而强行 auditwheel repair。
CUDA、cuDNN、NPP、GStreamer、FFmpeg 等 Jetson 系统依赖本来就不应该被随意塞进 wheel。
20. RPATH / RUNPATH 检查
检查:
readelf -d \
/home/jetson/miniforge3/envs/cv/lib/python3.12/site-packages/cv2/cv2.abi3.so \
| grep -E 'RPATH|RUNPATH'
当前构建可能看到类似:
/home/jetson/dev/opencv-wheel/opencv-python/_skbuild/linux-aarch64-3.12/cmake-install/lib:
/usr/local/cuda-13.2/lib64
其中:
/usr/local/cuda-13.2/lib64
是合理的 Jetson CUDA 路径。
而:
~/dev/opencv-wheel/opencv-python/_skbuild/...
是构建机路径。
如果:
ldd "$(python -c 'import cv2; print(cv2.__file__)')"
能够正常解析所有依赖,那么这个路径通常不是运行所必需的。
后续如果要制作更干净的 wheel,可以进一步优化 RUNPATH,但不要在第一次成功构建时急着修改。
21. OpenCV GUI检查
OpenCV 最终应该是 GTK HighGUI。cv2.imshow() 需要图形桌面和有效的 DISPLAY;在 SSH 或无显示器环境中失败,不一定表示 CUDA 构建失败。
检查 GUI:
cd /tmp
python - <<'PY'
import cv2
info = cv2.getBuildInformation()
start = info.find("GUI:")
print(info[start:start+500])
PY
确认存在:
GTK+: YES
然后:
python - <<'PY'
import cv2
import numpy as np
img = np.zeros((480, 800, 3), dtype=np.uint8)
cv2.putText(
img,
"OpenCV 4.14 + CUDA",
(100, 220),
cv2.FONT_HERSHEY_SIMPLEX,
1.5,
(0, 255, 0),
3,
cv2.LINE_AA,
)
cv2.imshow("OpenCV Test", img)
print("Press any key in the window to exit.")
cv2.waitKey(0)
cv2.destroyAllWindows()
PY
22. 如果JetPack 后续升级
例如:
JetPack 7.2
↓
JetPack 7.2.2
或者:
JetPack 7.2
↓
JetPack 7.3
JetPack 升级后可以先在新系统中测试已有 wheel;如果出现动态库 ABI 不兼容、CUDA/cuDNN 版本不匹配或 Python 版本变化,再重新编译。
23. Conda 使用注意事项
推荐:
conda create -n cv python=3.12
conda activate cv
python -m pip install -U pip
python -m pip install numpy
pip install opencv_contrib_python-....whl
不要同时:
conda install opencv
因为这样可能引入另外一套 OpenCV。
也不建议为了这个 wheel:
conda install cudatoolkit
Jetson 上 CUDA 应该优先使用 JetPack 系统提供的 CUDA。
最终:
Conda
├── Python
├── NumPy
└── OpenCV wheel
│
└── JetPack 系统
├── CUDA
├── cuDNN
├── NPP
├── cuBLAS
├── cuFFT
├── NVIDIA Driver
├── GStreamer
└── FFmpeg
24. 命令汇总
如果源码已经准备好,实际上核心命令就是:
cd ~/dev/opencv-wheel/opencv-python
sudo apt install -y python3.12-venv
python3 -m venv ~/venvs/opencv-wheel
source ~/venvs/opencv-wheel/bin/activate
python -m pip install -U pip
python -m pip install -U pip wheel scikit-build setuptools
export ENABLE_CONTRIB=1
export OPENCV_PYTHON_SKIP_GIT_COMMANDS=1
export CMAKE_ARGS="\
-DWITH_CUDA=ON \
-DWITH_CUBLAS=ON \
-DENABLE_FAST_MATH=ON \
-DCUDA_FAST_MATH=ON \
-DCUDA_ARCH_BIN=8.7 \
-DWITH_FFMPEG=ON \
-DWITH_GSTREAMER=ON \
-DWITH_V4L=ON \
-DWITH_OPENGL=ON \
-DWITH_QT=OFF \
-DOPENCV_ENABLE_NONFREE=ON \
-DBUILD_EXAMPLES=OFF \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_CXX_STANDARD_REQUIRED=ON"
rm -rf _skbuild build dist
rm -rf opencv/build
python -m pip wheel . --verbose
然后:
ls -lh *.whl
安装:
pip install \
~/dev/opencv-wheel/opencv-python/opencv_contrib_python-4.14.0+031876b-cp312-cp312-linux_aarch64.whl
验证:
cd /tmp
python - <<'PY'
import cv2
import numpy as np
print("OpenCV:", cv2.__version__)
print("NumPy :", np.__version__)
print("CUDA :", cv2.cuda.getCudaEnabledDeviceCount())
print("CUDA build info contains 13.2:", "13.2" in cv2.getBuildInformation())
PY
最后:
ldd $(python -c 'import cv2; print(cv2.__file__)') \
| grep "not found"
以及 CUDA 实际运算测试(GUI测试可选)。
浙公网安备 33010602011771号