0
点赞
收藏
分享

微信扫一扫

Ubuntu安装OpenCV CUDA版 + NVIDIA光流


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=


举报

相关推荐

0 条评论