Ubuntu OpenCV CUDA + NVIDIA光流 安装指南
概述
本指南提供了在Ubuntu系统上编译安装支持CUDA和NVIDIA光流的OpenCV的完整解决方案。包含自动化安装脚本和验证工具。
文件说明
-
install_opencv_cuda_ubuntu.sh
- 自动化安装脚本 -
README.md
- 本说明文档
系统要求
硬件要求
- NVIDIA GPU(支持CUDA计算能力6.0+)
- 至少4GB显存
- 至少8GB系统内存
- 至少20GB可用磁盘空间
软件要求
- Ubuntu 18.04/20.04/22.04
- NVIDIA驱动(版本≥450.80.02)
- CUDA Toolkit(版本≥11.0)
- CMake(版本≥3.18)
快速安装
需要注意CUDA等环境问题,为了安全脚本对部分环境安装进行了注释
install_opencv_cuda_ubuntu.sh
#!/bin/bash
# Ubuntu OpenCV CUDA + NVIDIA光流 自动安装脚本
# 支持Ubuntu 18.04/20.04/22.04
set -e # 遇到错误立即退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查是否为root用户
check_root() {
if [[ $EUID -eq 0 ]]; then
log_error "请不要使用root用户运行此脚本"
exit 1
fi
}
# 检查Ubuntu版本
check_ubuntu_version() {
if ! command -v lsb_release &> /dev/null; then
sudo apt update && sudo apt install -y lsb-release
fi
UBUNTU_VERSION=$(lsb_release -rs)
log_info "检测到Ubuntu版本: $UBUNTU_VERSION"
if [[ "$UBUNTU_VERSION" != "18.04" && "$UBUNTU_VERSION" != "20.04" && "$UBUNTU_VERSION" != "22.04" ]]; then
log_warning "此脚本主要针对Ubuntu 18.04/20.04/22.04,其他版本可能不兼容"
read -p "是否继续?(y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
}
# 检查GPU
check_gpu() {
if ! command -v nvidia-smi &> /dev/null; then
log_warning "未检测到NVIDIA驱动,将尝试安装"
install_nvidia_driver
else
log_success "NVIDIA驱动已安装"
nvidia-smi
fi
}
# 安装NVIDIA驱动
install_nvidia_driver() {
log_info "安装NVIDIA驱动..."
# 添加NVIDIA驱动PPA
sudo add-apt-repository ppa:graphics-drivers/ppa -y
sudo apt update
# 自动检测并安装推荐驱动
sudo ubuntu-drivers autoinstall
log_warning "NVIDIA驱动安装完成,需要重启系统"
log_warning "请重启后重新运行此脚本"
exit 0
}
# 安装CUDA
install_cuda() {
if command -v nvcc &> /dev/null; then
CUDA_VERSION=$(nvcc --version | grep "release" | awk '{print $6}' | cut -c2-)
log_success "CUDA已安装,版本: $CUDA_VERSION"
return
fi
log_info "安装CUDA Toolkit..."
# 根据Ubuntu版本选择CUDA版本
case $UBUNTU_VERSION in
"18.04")
CUDA_VERSION="11.8"
CUDA_PIN="cuda-ubuntu1804.pin"
CUDA_REPO="cuda-repo-ubuntu1804-11-8-local_11.8.0-520.61.05-1_amd64.deb"
;;
"20.04")
CUDA_VERSION="11.8"
CUDA_PIN="cuda-ubuntu2004.pin"
CUDA_REPO="cuda-repo-ubuntu2004-11-8-local_11.8.0-520.61.05-1_amd64.deb"
;;
"22.04")
CUDA_VERSION="12.0"
CUDA_PIN="cuda-ubuntu2204.pin"
CUDA_REPO="cuda-repo-ubuntu2204-12-0-local_12.0.0-525.60.13-1_amd64.deb"
;;
esac
# 下载并安装CUDA
cd /tmp
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu${UBUNTU_VERSION//.}/x86_64/${CUDA_PIN}
sudo mv ${CUDA_PIN} /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/${CUDA_VERSION}/local_installers/${CUDA_REPO}
sudo dpkg -i ${CUDA_REPO}
sudo cp /var/cuda-repo-ubuntu${UBUNTU_VERSION//.}-${CUDA_VERSION//.}-local/cuda-*-keyring.gpg /usr/share/keyrings/
sudo apt update
sudo apt install -y cuda
# 设置环境变量
echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
log_success "CUDA安装完成"
}
# 安装NVIDIA容器库
install_nvidia_container_toolkit() {
log_info "安装NVIDIA容器库..."
# 移除可能存在的旧仓库配置
sudo rm -f /etc/apt/sources.list.d/nvidia-container-toolkit.list
# 检查网络连接
if ! curl -s --connect-timeout 10 https://nvidia.github.io > /dev/null; then
log_warning "无法连接到NVIDIA GitHub,跳过NVIDIA容器库安装"
log_warning "您可以稍后手动安装:"
log_warning " curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg"
log_warning " curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list"
log_warning " sudo apt update && sudo apt install -y nvidia-container-toolkit"
return
fi
# 添加NVIDIA GPG密钥
if curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg; then
log_success "NVIDIA GPG密钥添加成功"
else
log_warning "NVIDIA GPG密钥添加失败,跳过NVIDIA容器库安装"
return
fi
# 添加NVIDIA容器库仓库
if curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list; then
log_success "NVIDIA容器库仓库添加成功"
else
log_warning "NVIDIA容器库仓库添加失败"
return
fi
# 更新包列表
if sudo apt update; then
log_success "包列表更新成功"
else
log_warning "包列表更新失败,移除NVIDIA容器库仓库"
sudo rm -f /etc/apt/sources.list.d/nvidia-container-toolkit.list
return
fi
# 安装NVIDIA容器库
if sudo apt install -y nvidia-container-toolkit; then
log_success "NVIDIA容器库安装完成"
else
log_warning "NVIDIA容器库安装失败,但继续其他安装步骤"
fi
}
# 安装依赖包
install_dependencies() {
log_info "安装系统依赖包..."
# 先尝试更新,如果失败则移除有问题的仓库
if ! sudo apt update 2>&1 | grep -q "Release"; then
log_warning "检测到仓库问题,正在清理..."
sudo rm -f /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update
fi
# 基础开发工具
sudo apt install -y \
build-essential \
cmake \
git \
wget \
curl \
unzip \
yasm \
pkg-config \
software-properties-common \
apt-transport-https \
ca-certificates \
gnupg \
lsb-release
# OpenCV依赖
sudo apt install -y \
libswscale-dev \
libtbb2 \
libtbb-dev \
libjpeg-dev \
libpng-dev \
libtiff-dev \
libavformat-dev \
libpq-dev \
libxine2-dev \
libglew-dev \
libtiff5-dev \
zlib1g-dev \
libavcodec-dev \
libavutil-dev \
libpostproc-dev \
libeigen3-dev \
libgtk2.0-dev \
libdc1394-dev \
libxvidcore-dev \
libx264-dev \
libgtk-3-dev \
libatlas-base-dev \
gfortran \
libprotobuf-dev \
protobuf-compiler \
libgoogle-glog-dev \
libgflags-dev \
libgphoto2-dev \
libhdf5-dev \
doxygen \
libopenblas-dev \
liblapack-dev \
liblapacke-dev \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libv4l-dev \
python3-dev \
python3-numpy \
libhdf5-serial-dev \
libhdf5-103
log_success "依赖包安装完成"
}
# 代理站配置
declare -A PROXY_SITES=(
["ghfast"]="https://ghfast.top/"
["githubfast"]="https://githubfast.com/"
["gitclone"]="https://gitclone.com/"
["wget"]="https://wget.la/"
["ghproxy"]="https://ghproxy.com/"
["91chi"]="https://github.91chi.fun/"
["cnpmjs"]="https://github.com.cnpmjs.org/"
["fastgit"]="https://hub.fastgit.xyz/"
)
# 默认代理站列表(按优先级排序)
DEFAULT_PROXY_ORDER=("ghfast" "githubfast" "gitclone" "wget" "ghproxy" "91chi" "cnpmjs" "fastgit")
# 显示可用代理站
show_proxy_sites() {
log_info "可用的代理站:"
for key in "${!PROXY_SITES[@]}"; do
echo " $key: ${PROXY_SITES[$key]}"
done
}
# 下载函数
download_with_proxy() {
local url="$1"
local output="$2"
local filename=$(basename "$output")
local proxy_order=("${@:3}")
log_info "下载: $filename"
# 尝试直接下载
if wget --timeout=30 --tries=3 -O "$output" "$url" 2>/dev/null; then
log_success "直接下载成功: $filename"
return 0
fi
# 尝试指定的代理站下载
for proxy_key in "${proxy_order[@]}"; do
if [ -n "${PROXY_SITES[$proxy_key]}" ]; then
local proxy_url="${PROXY_SITES[$proxy_key]}${url#https://}"
log_info "尝试代理站: $proxy_key (${PROXY_SITES[$proxy_key]})"
if wget --timeout=30 --tries=2 -O "$output" "$proxy_url" 2>/dev/null; then
log_success "代理下载成功: $filename (使用 $proxy_key)"
return 0
fi
fi
done
log_error "所有下载方式都失败了: $filename"
return 1
}
# 下载OpenCV依赖文件
download_opencv_dependencies() {
log_info "下载OpenCV依赖文件..."
# 创建下载目录
mkdir -p /tmp/opencv_downloads/wechat_qrcode
mkdir -p /tmp/opencv_downloads/xfeatures2d/boostdesc
mkdir -p /tmp/opencv_downloads/xfeatures2d/vgg
mkdir -p /tmp/opencv_downloads/data
mkdir -p /tmp/opencv_downloads/ade
mkdir -p /tmp/opencv_downloads/nvidia_optical_flow
# 获取代理站参数
local proxy_order=("${DEFAULT_PROXY_ORDER[@]}")
if [ -n "$1" ]; then
proxy_order=("$1")
log_info "使用指定代理站: $1"
else
log_info "使用默认代理站顺序"
fi
# 下载 WeChat QRCode 文件
log_info "下载 WeChat QRCode 文件..."
local wechat_base="https://raw.githubusercontent.com/WeChatCV/opencv_3rdparty/a8b69ccc738421293254aec5ddb38bd523503252"
download_with_proxy "${wechat_base}/detect.prototxt" "/tmp/opencv_downloads/wechat_qrcode/detect.prototxt" "${proxy_order[@]}"
download_with_proxy "${wechat_base}/detect.caffemodel" "/tmp/opencv_downloads/wechat_qrcode/detect.caffemodel" "${proxy_order[@]}"
download_with_proxy "${wechat_base}/sr.prototxt" "/tmp/opencv_downloads/wechat_qrcode/sr.prototxt" "${proxy_order[@]}"
download_with_proxy "${wechat_base}/sr.caffemodel" "/tmp/opencv_downloads/wechat_qrcode/sr.caffemodel" "${proxy_order[@]}"
# 下载 xfeatures2d boostdesc 文件
log_info "下载 xfeatures2d boostdesc 文件..."
local boostdesc_base="https://raw.githubusercontent.com/opencv/opencv_3rdparty/34e4206aef44d50e6bbcd0ab06354b52e7466d26"
download_with_proxy "${boostdesc_base}/boostdesc_bgm.i" "/tmp/opencv_downloads/xfeatures2d/boostdesc/boostdesc_bgm.i" "${proxy_order[@]}"
download_with_proxy "${boostdesc_base}/boostdesc_bgm_bi.i" "/tmp/opencv_downloads/xfeatures2d/boostdesc/boostdesc_bgm_bi.i" "${proxy_order[@]}"
download_with_proxy "${boostdesc_base}/boostdesc_bgm_hd.i" "/tmp/opencv_downloads/xfeatures2d/boostdesc/boostdesc_bgm_hd.i" "${proxy_order[@]}"
download_with_proxy "${boostdesc_base}/boostdesc_lbgm.i" "/tmp/opencv_downloads/xfeatures2d/boostdesc/boostdesc_lbgm.i" "${proxy_order[@]}"
download_with_proxy "${boostdesc_base}/boostdesc_binboost_064.i" "/tmp/opencv_downloads/xfeatures2d/boostdesc/boostdesc_binboost_064.i" "${proxy_order[@]}"
download_with_proxy "${boostdesc_base}/boostdesc_binboost_128.i" "/tmp/opencv_downloads/xfeatures2d/boostdesc/boostdesc_binboost_128.i" "${proxy_order[@]}"
download_with_proxy "${boostdesc_base}/boostdesc_binboost_256.i" "/tmp/opencv_downloads/xfeatures2d/boostdesc/boostdesc_binboost_256.i" "${proxy_order[@]}"
# 下载 xfeatures2d vgg 文件
log_info "下载 xfeatures2d vgg 文件..."
local vgg_base="https://raw.githubusercontent.com/opencv/opencv_3rdparty/fccf7cd6a4b12079f73bbfb21745f9babcd4eb1d"
download_with_proxy "${vgg_base}/vgg_generated_48.i" "/tmp/opencv_downloads/xfeatures2d/vgg/vgg_generated_48.i" "${proxy_order[@]}"
download_with_proxy "${vgg_base}/vgg_generated_64.i" "/tmp/opencv_downloads/xfeatures2d/vgg/vgg_generated_64.i" "${proxy_order[@]}"
download_with_proxy "${vgg_base}/vgg_generated_80.i" "/tmp/opencv_downloads/xfeatures2d/vgg/vgg_generated_80.i" "${proxy_order[@]}"
download_with_proxy "${vgg_base}/vgg_generated_120.i" "/tmp/opencv_downloads/xfeatures2d/vgg/vgg_generated_120.i" "${proxy_order[@]}"
# 下载 data 文件
log_info "下载 data 文件..."
local data_base="https://raw.githubusercontent.com/opencv/opencv_3rdparty/8afa57abc8229d611c4937165d20e2a2d9fc5a12"
download_with_proxy "${data_base}/face_landmark_model.dat" "/tmp/opencv_downloads/data/face_landmark_model.dat" "${proxy_order[@]}"
# 下载 ADE 文件
log_info "下载 ADE 文件..."
local ade_url="https://github.com/opencv/ade/archive/v0.1.2e.zip"
download_with_proxy "$ade_url" "/tmp/opencv_downloads/ade/v0.1.2e.zip" "${proxy_order[@]}"
# 下载 NVIDIA 光流 SDK
log_info "下载 NVIDIA 光流 SDK..."
local nvof_url="https://github.com/NVIDIA/NVIDIAOpticalFlowSDK/archive/edb50da3cf849840d680249aa6dbef248ebce2ca.zip"
download_with_proxy "$nvof_url" "/tmp/opencv_downloads/nvidia_optical_flow/edb50da3cf849840d680249aa6dbef248ebce2ca.zip" "${proxy_order[@]}"
log_success "依赖文件下载完成"
}
# 准备OpenCV源码
prepare_opencv() {
log_info "准备OpenCV源码..."
OPENCV_VERSION="4.12.0"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="$SCRIPT_DIR/opencv_build"
# 检查本地源码
LOCAL_OPENCV="$SCRIPT_DIR/opencv"
LOCAL_OPENCV_CONTRIB="$SCRIPT_DIR/opencv_contrib"
if [ -d "$LOCAL_OPENCV" ] && [ -d "$LOCAL_OPENCV_CONTRIB" ]; then
log_success "发现本地OpenCV源码,优先使用本地版本"
# 检查版本
if [ -d "$LOCAL_OPENCV/.git" ]; then
LOCAL_VERSION=$(cd "$LOCAL_OPENCV" && git describe --tags 2>/dev/null | head -1)
log_info "本地OpenCV版本: $LOCAL_VERSION"
fi
# 创建构建目录的符号链接
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# 创建符号链接到本地源码
if [ ! -L "opencv" ]; then
ln -sf "$LOCAL_OPENCV" opencv
log_success "创建OpenCV主仓库符号链接"
fi
if [ ! -L "opencv_contrib" ]; then
ln -sf "$LOCAL_OPENCV_CONTRIB" opencv_contrib
log_success "创建OpenCV contrib仓库符号链接"
fi
else
log_warning "未找到本地OpenCV源码,将下载到构建目录"
BUILD_DIR="$HOME/opencv_build"
# 创建构建目录
mkdir -p $BUILD_DIR
cd $BUILD_DIR
# 下载OpenCV主仓库
if [ ! -d "opencv" ]; then
log_info "下载OpenCV主仓库..."
git clone https://github.com/opencv/opencv.git
cd opencv
git checkout $OPENCV_VERSION
cd ..
else
log_info "OpenCV主仓库已存在,跳过下载"
fi
# 下载OpenCV contrib仓库
if [ ! -d "opencv_contrib" ]; then
log_info "下载OpenCV contrib仓库..."
git clone https://github.com/opencv/opencv_contrib.git
cd opencv_contrib
git checkout $OPENCV_VERSION
cd ..
else
log_info "OpenCV contrib仓库已存在,跳过下载"
fi
fi
# 导出构建目录路径供其他函数使用
export OPENCV_BUILD_DIR="$BUILD_DIR"
log_success "OpenCV源码准备完成"
}
# 配置和编译OpenCV
build_opencv() {
log_info "配置和编译OpenCV..."
# 使用导出的构建目录路径
if [ -z "$OPENCV_BUILD_DIR" ]; then
log_error "构建目录路径未设置,请先运行 prepare_opencv"
exit 1
fi
BUILD_DIR="$OPENCV_BUILD_DIR"
cd $BUILD_DIR
# 创建构建目录
mkdir -p build
cd build
# 检测GPU架构
GPU_ARCH=""
if command -v nvidia-smi &> /dev/null; then
GPU_NAME=$(nvidia-smi --query-gpu=name --format=csv,noheader,nounits | head -1)
log_info "检测到GPU: $GPU_NAME"
# 根据GPU设置架构
case $GPU_NAME in
*"RTX 4090"*|*"RTX 4080"*|*"RTX 4070"*)
GPU_ARCH="8.9"
;;
*"RTX 3090"*|*"RTX 3080"*|*"RTX 3070"*|*"RTX 3060"*)
GPU_ARCH="8.6"
;;
*"RTX 2080"*|*"RTX 2070"*|*"RTX 2060"*)
GPU_ARCH="7.5"
;;
*"GTX 1080"*|*"GTX 1070"*|*"GTX 1060"*)
GPU_ARCH="6.1"
;;
*)
GPU_ARCH="7.5,8.0,8.6" # 默认支持多个架构
;;
esac
log_info "设置GPU架构: $GPU_ARCH"
else
GPU_ARCH="7.5,8.0,8.6"
log_warning "无法检测GPU架构,使用默认值: $GPU_ARCH"
fi
# 设置CUDA环境变量
export CUDA_HOME=/usr/local/cuda
export CUDA_ROOT=/usr/local/cuda
export PATH=$CUDA_HOME/bin:$PATH
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
# 创建下载目录
mkdir -p /tmp/opencv_downloads
# CMake配置
log_info "配置CMake..."
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D INSTALL_C_EXAMPLES=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D WITH_CUDA=ON \
-D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda \
-D CUDA_HOST_COMPILER=/usr/bin/gcc \
-D CUDA_NVCC_FLAGS="-D_FORCE_INLINES" \
-D WITH_CUDNN=OFF \
-D OPENCV_DNN_CUDA=OFF \
-D ENABLE_FAST_MATH=ON \
-D CUDA_FAST_MATH=ON \
-D WITH_CUBLAS=ON \
-D WITH_CUFFT=ON \
-D WITH_NVCUVID=ON \
-D WITH_NVCUVENC=ON \
-D CUDA_ARCH_BIN=$GPU_ARCH \
-D WITH_OPENGL=ON \
-D WITH_OPENCL=ON \
-D WITH_IPP=OFF \
-D WITH_TBB=ON \
-D WITH_EIGEN=ON \
-D WITH_V4L=ON \
-D WITH_FFMPEG=ON \
-D WITH_GSTREAMER=ON \
-D WITH_GTK=ON \
-D WITH_QT=OFF \
-D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules \
-D BUILD_opencv_wechat_qrcode=OFF \
-D BUILD_opencv_xfeatures2d=OFF \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D BUILD_EXAMPLES=ON \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D BUILD_opencv_python3=ON \
-D BUILD_opencv_python2=OFF \
-D PYTHON3_EXECUTABLE=/usr/bin/python3 \
-D PYTHON3_INCLUDE_DIR=/usr/include/python3.8 \
-D PYTHON3_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
-D PYTHON3_NUMPY_INCLUDE_DIRS=/usr/lib/python3/dist-packages/numpy/core/include \
-D OPENCV_PYTHON3_INSTALL_PATH=/usr/local/lib/python3.8/dist-packages \
-D OPENCV_DOWNLOAD_PATH=/tmp/opencv_downloads \
-D OPENCV_DOWNLOAD_TRY_MIRRORS=OFF \
../opencv
# 编译
log_info "开始编译OpenCV(这可能需要1-2小时)..."
make -j$(nproc)
# 安装
log_info "安装OpenCV..."
sudo make install
sudo ldconfig
log_success "OpenCV编译和安装完成"
}
# 配置环境
setup_environment() {
log_info "配置环境变量..."
# 添加到.bashrc
echo 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
# 更新库缓存
sudo ldconfig
log_success "环境配置完成"
}
# 创建验证脚本
create_test_script() {
log_info "创建验证脚本..."
cat > test_opencv_cuda.py << 'EOF'
#!/usr/bin/env python3
"""
OpenCV CUDA + NVIDIA光流验证脚本
"""
import cv2
import numpy as np
import sys
def test_opencv_cuda():
print("=" * 50)
print("OpenCV CUDA + NVIDIA光流验证")
print("=" * 50)
# 基本信息
print(f"OpenCV版本: {cv2.__version__}")
print(f"CUDA设备数量: {cv2.cuda.getCudaEnabledDeviceCount()}")
if cv2.cuda.getCudaEnabledDeviceCount() == 0:
print("❌ CUDA不可用")
return False
print("✅ CUDA可用")
# 测试CUDA光流
try:
print("\n测试CUDA光流...")
# 创建测试图像
img1 = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
img2 = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
# 转换为灰度图
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 测试Farneback光流
optical_flow = cv2.cuda_FarnebackOpticalFlow.create()
gpu_img1 = cv2.cuda_GpuMat()
gpu_img2 = cv2.cuda_GpuMat()
gpu_img1.upload(gray1)
gpu_img2.upload(gray2)
flow = optical_flow.calc(gpu_img1, gpu_img2, None)
print("✅ CUDA Farneback光流测试成功")
# 测试NVIDIA光流2.0
try:
nvof = cv2.cuda_NvidiaOpticalFlow_2_0.create(
(640, 480),
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_OUTPUT_VECTOR_GRID_SIZE_1,
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_HINT_VECTOR_GRID_SIZE_OFF,
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_PERF_LEVEL_SLOW,
False, False, False, False
)
print("✅ NVIDIA光流2.0支持可用")
# 测试NVIDIA光流计算
nvof_flow = nvof.calc(gpu_img1, gpu_img2, None)
print("✅ NVIDIA光流2.0计算测试成功")
except Exception as e:
print(f"⚠️ NVIDIA光流2.0不可用: {e}")
print(" 但CUDA光流功能正常")
return True
except Exception as e:
print(f"❌ CUDA光流测试失败: {e}")
return False
def test_performance():
print("\n性能测试...")
# 创建较大的测试图像
img1 = np.random.randint(0, 255, (1080, 1920, 3), dtype=np.uint8)
img2 = np.random.randint(0, 255, (1080, 1920, 3), dtype=np.uint8)
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# CPU光流
import time
start_time = time.time()
cpu_flow = cv2.calcOpticalFlowFarneback(gray1, gray2, None, 0.5, 3, 15, 3, 5, 1.2, 0)
cpu_time = time.time() - start_time
# CUDA光流
start_time = time.time()
optical_flow = cv2.cuda_FarnebackOpticalFlow.create()
gpu_img1 = cv2.cuda_GpuMat()
gpu_img2 = cv2.cuda_GpuMat()
gpu_img1.upload(gray1)
gpu_img2.upload(gray2)
gpu_flow = optical_flow.calc(gpu_img1, gpu_img2, None)
gpu_time = time.time() - start_time
print(f"CPU光流耗时: {cpu_time:.3f}秒")
print(f"CUDA光流耗时: {gpu_time:.3f}秒")
print(f"加速比: {cpu_time/gpu_time:.2f}x")
if __name__ == "__main__":
success = test_opencv_cuda()
if success:
test_performance()
print("\n🎉 所有测试通过!OpenCV CUDA + NVIDIA光流安装成功!")
else:
print("\n❌ 测试失败,请检查安装")
sys.exit(1)
EOF
chmod +x test_opencv_cuda.py
log_success "验证脚本创建完成"
}
# 显示帮助信息
show_help() {
echo "OpenCV CUDA + NVIDIA光流 自动安装脚本"
echo ""
echo "使用方法:"
echo " $0 [选项] [代理站]"
echo ""
echo "选项:"
echo " -h, --help 显示此帮助信息"
echo " -p, --proxy 显示可用代理站列表"
echo " -d, --download 仅下载依赖文件"
echo ""
echo "代理站参数:"
echo " 指定要使用的代理站名称"
echo ""
echo "示例:"
echo " $0 # 使用默认设置安装"
echo " $0 ghproxy # 使用 ghproxy 代理站"
echo " $0 -p # 显示可用代理站"
echo " $0 -d ghfast # 仅下载依赖文件,使用 ghfast 代理站"
echo ""
show_proxy_sites
}
# 主函数
main() {
local proxy_site=""
local download_only=false
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-p|--proxy)
show_proxy_sites
exit 0
;;
-d|--download)
download_only=true
shift
;;
-*)
log_error "未知选项: $1"
show_help
exit 1
;;
*)
if [ -z "$proxy_site" ]; then
proxy_site="$1"
fi
shift
;;
esac
done
if [ "$download_only" = true ]; then
log_info "仅下载依赖文件模式"
download_opencv_dependencies "$proxy_site"
exit 0
fi
log_info "开始安装OpenCV CUDA + NVIDIA光流支持"
# check_root
check_ubuntu_version
check_gpu
# install_cuda
install_nvidia_container_toolkit
install_dependencies
# download_opencv_dependencies "$proxy_site"
prepare_opencv
build_opencv
setup_environment
create_test_script
log_success "安装完成!"
log_info "请运行以下命令验证安装:"
log_info " source ~/.bashrc"
log_info " python3 test_opencv_cuda.py"
# 询问是否立即运行测试
read -p "是否立即运行验证测试?(Y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]] || [[ -z $REPLY ]]; then
source ~/.bashrc
python3 test_opencv_cuda.py
fi
}
# 运行主函数
main "$@"
1. 下载脚本
# 下载安装脚本
chmod +x install_opencv_cuda_ubuntu.sh
2. 运行安装
# 运行自动化安装脚本
./install_opencv_cuda_ubuntu.sh
3. 验证安装
# 运行验证脚本
python3 test_opencv_cuda.py
手动安装步骤
如果自动化脚本失败,可以按照以下步骤手动安装:
1. 安装系统依赖
sudo apt update
sudo apt install -y build-essential cmake git wget curl unzip yasm pkg-config
sudo apt install -y libswscale-dev libtbb2 libtbb-dev libjpeg-dev libpng-dev
sudo apt install -y libtiff-dev libavformat-dev libpq-dev libxine2-dev
sudo apt install -y libglew-dev libtiff5-dev zlib1g-dev libavcodec-dev
sudo apt install -y libavutil-dev libpostproc-dev libeigen3-dev libgtk2.0-dev
sudo apt install -y libdc1394-dev libxvidcore-dev libx264-dev libgtk-3-dev
sudo apt install -y libatlas-base-dev gfortran libprotobuf-dev protobuf-compiler
sudo apt install -y libgoogle-glog-dev libgflags-dev libgphoto2-dev libhdf5-dev
sudo apt install -y doxygen libopenblas-dev liblapack-dev liblapacke-dev
sudo apt install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
sudo apt install -y libv4l-dev libqtgui4 libqtwebkit4 libqt4-test python3-dev
sudo apt install -y python3-numpy python3-pyqt5 libhdf5-serial-dev libhdf5-103
2. 安装NVIDIA驱动和CUDA
# 安装NVIDIA驱动
sudo add-apt-repository ppa:graphics-drivers/ppa -y
sudo apt update
sudo ubuntu-drivers autoinstall
# 重启系统
sudo reboot
# 安装CUDA Toolkit
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda-repo-ubuntu2004-11-8-local_11.8.0-520.61.05-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu2004-11-8-local_11.8.0-520.61.05-1_amd64.deb
sudo cp /var/cuda-repo-ubuntu2004-11-8-local/cuda-*-keyring.gpg /usr/share/keyrings/
sudo apt update
sudo apt install -y cuda
# 设置环境变量
echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc
3. 下载OpenCV源码
mkdir -p ~/opencv_build
cd ~/opencv_build
# 下载OpenCV主仓库
git clone https://github.com/opencv/opencv.git
cd opencv
git checkout 4.8.0
cd ..
# 下载OpenCV contrib仓库
git clone https://github.com/opencv/opencv_contrib.git
cd opencv_contrib
git checkout 4.8.0
cd ..
4. 配置和编译
mkdir build
cd build
# CMake配置
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D INSTALL_C_EXAMPLES=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D WITH_CUDA=ON \
-D WITH_CUDNN=ON \
-D OPENCV_DNN_CUDA=ON \
-D ENABLE_FAST_MATH=ON \
-D CUDA_FAST_MATH=ON \
-D WITH_CUBLAS=ON \
-D WITH_CUFFT=ON \
-D WITH_NVCUVID=ON \
-D WITH_NVCUVENC=ON \
-D CUDA_ARCH_BIN=7.5,8.0,8.6,8.9 \
-D WITH_OPENGL=ON \
-D WITH_OPENCL=ON \
-D WITH_IPP=OFF \
-D WITH_TBB=ON \
-D WITH_EIGEN=ON \
-D WITH_V4L=ON \
-D WITH_FFMPEG=ON \
-D WITH_GSTREAMER=ON \
-D WITH_GTK=ON \
-D WITH_QT=OFF \
-D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D BUILD_EXAMPLES=ON \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D BUILD_opencv_python3=ON \
-D BUILD_opencv_python2=OFF \
-D PYTHON3_EXECUTABLE=/usr/bin/python3 \
-D PYTHON3_INCLUDE_DIR=/usr/include/python3.8 \
-D PYTHON3_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
-D PYTHON3_NUMPY_INCLUDE_DIRS=/usr/lib/python3/dist-packages/numpy/core/include \
-D OPENCV_PYTHON3_INSTALL_PATH=/usr/local/lib/python3.8/dist-packages \
../opencv
# 编译
make -j$(nproc)
# 安装
sudo make install
sudo ldconfig
5. 配置环境
echo 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc
验证安装
运行验证脚本
python3 test_opencv_cuda.py
手动验证
import cv2
import numpy as np
# 检查CUDA支持
print(f"OpenCV版本: {cv2.__version__}")
print(f"CUDA设备数量: {cv2.cuda.getCudaEnabledDeviceCount()}")
# 测试CUDA光流
if cv2.cuda.getCudaEnabledDeviceCount() > 0:
img1 = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
img2 = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# CUDA光流
optical_flow = cv2.cuda_FarnebackOpticalFlow.create()
gpu_img1 = cv2.cuda_GpuMat()
gpu_img2 = cv2.cuda_GpuMat()
gpu_img1.upload(gray1)
gpu_img2.upload(gray2)
flow = optical_flow.calc(gpu_img1, gpu_img2, None)
print("CUDA光流测试成功")
# NVIDIA光流(如果支持)
try:
nvof = cv2.cuda_NvidiaOpticalFlow_2_0.create(
(640, 480),
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_OUTPUT_VECTOR_GRID_SIZE_1,
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_HINT_VECTOR_GRID_SIZE_OFF,
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_PERF_LEVEL_SLOW,
False, False, False, False
)
print("NVIDIA光流2.0支持可用")
except:
print("NVIDIA光流2.0不可用")
使用示例
CUDA光流示例
import cv2
import numpy as np
# 创建CUDA光流对象
optical_flow = cv2.cuda_FarnebackOpticalFlow.create(
numLevels=3,
pyrScale=0.5,
fastPyramids=False,
winSize=15,
numIters=3,
polyN=5,
polySigma=1.2,
flags=0
)
# 读取图像
frame1 = cv2.imread('frame1.jpg')
frame2 = cv2.imread('frame2.jpg')
# 转换为灰度图
gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# 上传到GPU
gpu_img1 = cv2.cuda_GpuMat()
gpu_img2 = cv2.cuda_GpuMat()
gpu_img1.upload(gray1)
gpu_img2.upload(gray2)
# 计算光流
flow = optical_flow.calc(gpu_img1, gpu_img2, None)
flow_result = flow.download()
print(f"光流形状: {flow_result.shape}")
NVIDIA光流示例
import cv2
import numpy as np
# 创建NVIDIA光流对象
nvof = cv2.cuda_NvidiaOpticalFlow_2_0.create(
(640, 480), # 图像尺寸
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_OUTPUT_VECTOR_GRID_SIZE_1,
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_HINT_VECTOR_GRID_SIZE_OFF,
cv2.cuda.NVIDIA_OPTICAL_FLOW_2_0_PERF_LEVEL_FAST,
False, False, False, False
)
# 读取图像
frame1 = cv2.imread('frame1.jpg')
frame2 = cv2.imread('frame2.jpg')
# 转换为灰度图
gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# 上传到GPU
gpu_img1 = cv2.cuda_GpuMat()
gpu_img2 = cv2.cuda_GpuMat()
gpu_img1.upload(gray1)
gpu_img2.upload(gray2)
# 计算NVIDIA光流
flow = nvof.calc(gpu_img1, gpu_img2, None)
flow_result = flow.download()
print(f"NVIDIA光流形状: {flow_result.shape}")
测试光流补帧程序
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
OpenCV 光流补帧示例
输入视频 -> 光流计算 -> 帧率 x2 输出
需要: opencv-python>=4.5
"""
import cv2
import numpy as np
def interpolate_frame(frame1, frame2, t: float) -> np.ndarray:
"""
利用稠密光流在 frame1 和 frame2 之间插值
:param t: 插值比例 [0,1]
"""
# 转灰度计算光流
gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
flow = cv2.calcOpticalFlowFarneback(
gray1, gray2,
None,
0.5, # 金字塔缩放
3, # 金字塔层数
15, # 窗口大小
3, # 迭代次数
5, # 多项式邻域
1.2, # 高斯标准差
0
)
# 根据 t 计算正向与反向映射
h, w = gray1.shape
flow_t = flow * t
flow_inv_t = -flow * (1 - t)
grid_x, grid_y = np.meshgrid(np.arange(w), np.arange(h))
# frame1 向前
map_x1 = (grid_x + flow_t[...,0]).astype(np.float32)
map_y1 = (grid_y + flow_t[...,1]).astype(np.float32)
warp1 = cv2.remap(frame1, map_x1, map_y1, cv2.INTER_LINEAR)
# frame2 向后
map_x2 = (grid_x + flow_inv_t[...,0]).astype(np.float32)
map_y2 = (grid_y + flow_inv_t[...,1]).astype(np.float32)
warp2 = cv2.remap(frame2, map_x2, map_y2, cv2.INTER_LINEAR)
# 融合
interp = cv2.addWeighted(warp1, 1 - t, warp2, t, 0)
return interp
def optical_flow_interpolation(input_path: str, output_path: str, scale: int = 2):
"""
光流补帧,帧率提升 scale 倍
:param scale: 倍率,如 2 表示输出帧率是原来的 2 倍
"""
cap = cv2.VideoCapture(input_path)
if not cap.isOpened():
raise IOError(f"无法打开视频: {input_path}")
fps = cap.get(cv2.CAP_PROP_FPS)
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps * scale, (w, h))
ret, prev = cap.read()
if not ret:
raise IOError("读取第一帧失败")
while True:
ret, nxt = cap.read()
if not ret:
break
# 写入原始帧
out.write(prev)
# 插入中间帧 (scale-1 个)
for i in range(1, scale):
t = i / scale
mid = interpolate_frame(prev, nxt, t)
out.write(mid)
prev = nxt
# 最后一帧
out.write(prev)
cap.release()
out.release()
print(f"完成!输出文件: {output_path}, 帧率约 {fps*scale:.2f}")
if __name__ == "__main__":
input_video = "input.mp4"
output_video = "output_interpolated.mp4"
optical_flow_interpolation(input_video, output_video, scale=2) # 2x 帧率
常见问题
Q1: CUDA设备数量为0
A: 检查NVIDIA驱动是否正确安装:
nvidia-smi
Q2: 编译时内存不足
A: 减少并行编译进程:
make -j4 # 而不是 make -j$(nproc)
Q3: NVIDIA光流不可用
A: 确保GPU支持光流硬件加速,检查GPU架构:
nvidia-smi --query-gpu=name,compute_cap --format=csv
Q4: Python绑定问题
A: 重新安装Python绑定:
sudo make install
sudo ldconfig
Q5: 编译时间过长
A: 可以禁用一些不必要的模块:
-D BUILD_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF
性能优化
GPU架构优化
根据您的GPU设置正确的CUDA_ARCH_BIN
:
- RTX 4090/4080/4070:
8.9
- RTX 3090/3080/3070/3060:
8.6
- RTX 2080/2070/2060:
7.5
- GTX 1080/1070/1060:
6.1
内存优化
- 确保有足够的系统内存(推荐16GB+)
- 确保有足够的显存(推荐8GB+)
编译优化
- 使用
-DCMAKE_BUILD_TYPE=RELEASE
进行优化编译 - 启用快速数学运算:
-DENABLE_FAST_MATH=ON -DCUDA_FAST_MATH=ON
=