在Windows上编译OpenCV Android原生库全记录

无需Android Studio,脱离复杂的Gradle构建系统,仅用命令行工具完成OpenCV Android .so库的编译

前言

最近在开发一个需要集成OpenCV的Android项目时,我发现传统的Android Studio集成方式存在一些限制:构建流程不透明、难以自定义模块、集成到CI/CD流程复杂。经过一番探索,我成功找到了一种纯命令行编译OpenCV Android库的方法,整个过程完全掌控,非常适合需要自定义构建或自动化集成的场景。

本文将详细介绍我在Windows 11环境下,使用Git Bash、Android NDK、CMake和Ninja,从源码编译OpenCV 4.11.0 Android原生库的完整过程。

环境准备

在开始之前,需要确保你的系统已安装以下工具:

工具 版本要求 作用

Android NDK ≥ r21(推荐r26) Android原生开发工具链

CMake ≥ 3.18 跨平台构建系统

Git for Windows 最新版 提供Bash环境

Ninja 最新版 高性能构建系统

工具路径示例

我的实际环境配置如下:

· OpenCV源码:D:\opencv-4.11.0

· Android NDK:D:\AndroidSDK\ndk\26.3.11579264

· CMake:D:\AndroidSDK\cmake\3.22.1\bin\cmake

· Ninja:D:\ndkTest\ninja-win\ninja.exe

核心编译脚本

经过多次调试和优化,我总结出了以下可靠的编译脚本。这个脚本成功编译出了15个OpenCV Android动态库,总大小约300MB。

bash 复制代码
#!/bin/bash
# ============================================
# OpenCV 4.11.0 Android 纯命令行编译脚本
# ============================================

set -e  # 出错即停止

# === 配置 ===
OPENCV_SRC="/d/opencv-4.11.0"
NDK_PATH="/d/AndroidSDK/ndk/26.3.11579264"
CMAKE_BIN="/d/AndroidSDK/cmake/3.22.1/bin/cmake"
NINJA_BIN="/d/ndkTest/ninja-win/ninja.exe"

# === 编译选项 ===
ABI="arm64-v8a"  # 目标架构
API_LEVEL=24      # Android API级别
BUILD_TYPE="Release"  # 构建类型
BUILD_DIR="/d/opencv_build_${ABI}"  # 构建目录
INSTALL_DIR="/d/opencv-android-output"  # 输出目录

echo "========================================"
echo "🚀 OpenCV 4.11.0 Android 纯命令行编译"
echo "========================================"

# 环境检查
check_environment() {
    echo "🔍 环境检查..."
    [ -d "$OPENCV_SRC" ] || { echo "❌ OpenCV源码不存在: $OPENCV_SRC"; exit 1; }
    [ -f "$OPENCV_SRC/CMakeLists.txt" ] || { 
        echo "❌ OpenCV/CMakeLists.txt不存在"; exit 1; 
    }
    [ -f "$CMAKE_BIN" ] || { echo "❌ CMake不存在: $CMAKE_BIN"; exit 1; }
    [ -f "$NINJA_BIN" ] || { echo "❌ Ninja不存在: $NINJA_BIN"; exit 1; }
    [ -f "$NDK_PATH/build/cmake/android.toolchain.cmake" ] || { 
        echo "❌ NDK android.toolchain.cmake不存在"; exit 1; 
    }
    echo "✅ 环境检查通过"
}

# 清理构建目录
clean_build_dir() {
    echo "🧹 清理构建目录..."
    rm -rf "$BUILD_DIR"
    mkdir -p "$BUILD_DIR"
    cd "$BUILD_DIR"
}

# CMake配置
configure_cmake() {
    echo "⚙️ CMake配置..."
    echo "  构建目录: $BUILD_DIR"
    echo "  源码目录: $OPENCV_SRC"

    "$CMAKE_BIN" \
        "$OPENCV_SRC" \
        -G "Ninja" \
        -DCMAKE_MAKE_PROGRAM="$NINJA_BIN" \
        -DCMAKE_TOOLCHAIN_FILE="$NDK_PATH/build/cmake/android.toolchain.cmake" \
        -DANDROID_ABI="$ABI" \
        -DANDROID_PLATFORM="android-$API_LEVEL" \
        -DANDROID_STL="c++_shared" \
        -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
        -DBUILD_JAVA=OFF \
        -DBUILD_opencv_java=OFF \
        -DBUILD_SHARED_LIBS=ON \
        -DBUILD_opencv_core=ON \
        -DBUILD_opencv_imgproc=ON \
        -DBUILD_opencv_imgcodecs=ON \
        -DBUILD_TESTS=OFF \
        -DBUILD_EXAMPLES=OFF \
        -DBUILD_PERF_TESTS=OFF \
        -DBUILD_ANDROID_EXAMPLES=OFF \
        -DBUILD_ANDROID_PROJECTS=OFF

    [ $? -eq 0 ] && echo "✅ CMake配置成功" || {
        echo "❌ CMake配置失败"; exit 1
    }
}

# 编译OpenCV
compile_opencv() {
    echo "🔨 开始编译..."
    "$CMAKE_BIN" --build . --parallel 8
    [ $? -eq 0 ] && echo "✅ 编译成功" || {
        echo "❌ 编译失败"; exit 1
    }
}

# 整理输出文件
collect_output() {
    echo "📦 整理输出文件..."
    rm -rf "$INSTALL_DIR"
    mkdir -p "$INSTALL_DIR/libs/$ABI"
    mkdir -p "$INSTALL_DIR/include"

    # 复制.so文件
    echo "  复制.so文件..."
    if [ -d "lib" ]; then
        SO_PATHS=("lib/$ABI/*.so" "lib/*.so" "*.so" "bin/*.so")
        for pattern in "${SO_PATHS[@]}"; do
            if ls $pattern 1>/dev/null 2>&1; then
                echo "    找到文件: $pattern"
                cp $pattern "$INSTALL_DIR/libs/$ABI/" 2>/dev/null || true
            fi
        done
    fi

    # 复制头文件
    echo "  复制头文件..."
    cp -r "$OPENCV_SRC/include/opencv2" "$INSTALL_DIR/include/" 2>/dev/null || true

    # 统计结果
    local SO_COUNT=$(ls "$INSTALL_DIR/libs/$ABI/"*.so 2>/dev/null | wc -l)
    echo ""
    echo "========================================"
    echo "🎉 编译完成!"
    echo "========================================"
    echo "📊 结果统计:"
    echo "  架构:$ABI"
    echo "  API Level:$API_LEVEL"
    echo "  构建类型:$BUILD_TYPE"
    echo "  库文件数量:$SO_COUNT 个"
    echo "  输出目录:$INSTALL_DIR"
}

# 主流程
main() {
    check_environment
    clean_build_dir
    configure_cmake
    compile_opencv
    collect_output
}

main "$@"

编译过程详解

  1. 关键配置项解析

脚本中的CMake配置选项是编译成功的关键:

bash 复制代码
# 禁用Java绑定 - 避免与Android构建系统冲突
-DBUILD_JAVA=OFF
-DBUILD_opencv_java=OFF

# 禁用Android示例项目 - 简化构建流程
-DBUILD_ANDROID_EXAMPLES=OFF
-DBUILD_ANDROID_PROJECTS=OFF

# 启用动态库构建
-DBUILD_SHARED_LIBS=ON

# 使用c++_shared STL - 确保运行时兼容性
-DANDROID_STL="c++_shared"

# 仅启用核心模块(可按需添加更多)
-DBUILD_opencv_core=ON
-DBUILD_opencv_imgproc=ON
-DBUILD_opencv_imgcodecs=ON
  1. 编译输出结果

执行脚本后,成功编译出15个OpenCV动态库:

库文件 大小 核心功能

libopencv_core.so 23MB 核心数据结构与算法

libopencv_imgproc.so 25MB 图像处理(滤波、变换等)

libopencv_dnn.so 87MB 深度学习模块

libopencv_imgcodecs.so 23MB 图像编解码(JPEG、PNG等)

libopencv_calib3d.so 20MB 相机标定与3D重建

libopencv_features2d.so 6.2MB 特征检测与匹配

libopencv_gapi.so 76MB 图像处理流水线框架

其他8个模块 总计~40MB ML、视频处理等

  1. 编译耗时统计

· CMake配置阶段:约2-3分钟

· 编译阶段:约20-30分钟(1340个构建任务)

· 总计:约25-35分钟(取决于CPU性能)

在Android项目中的使用

  1. CMake集成示例

在Android项目的CMakeLists.txt中添加以下配置:

cmake 复制代码
cmake_minimum_required(VERSION 3.18.1)
project("MyOpenCVApp")

# 设置OpenCV路径
set(OPENCV_ANDROID_DIR "/d/opencv-android-output")

# 包含头文件
include_directories(${OPENCV_ANDROID_DIR}/include)

# 添加你的原生库
add_library(native-lib SHARED
    native-lib.cpp
)

# 链接OpenCV库
target_link_libraries(native-lib
    ${OPENCV_ANDROID_DIR}/libs/${ANDROID_ABI}/libopencv_core.so
    ${OPENCV_ANDROID_DIR}/libs/${ANDROID_ABI}/libopencv_imgproc.so
    # ... 其他需要的库
    log
    android
)
  1. JNI简单测试

创建一个简单的JNI函数测试OpenCV功能:

cpp 复制代码
#include <jni.h>
#include <android/log.h>
#include <opencv2/opencv.hpp>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_app_MainActivity_testOpenCV(
        JNIEnv* env,
        jobject /* this */) {
    
    // 创建测试图像
    cv::Mat testMat(100, 100, CV_8UC3, cv::Scalar(0, 255, 0));
    
    // 转换为灰度
    cv::Mat grayMat;
    cv::cvtColor(testMat, grayMat, cv::COLOR_BGR2GRAY);
    
    std::string result = "OpenCV 4.11.0工作正常!\n";
    result += "图像尺寸: " + std::to_string(testMat.cols) + 
              "x" + std::to_string(testMat.rows);
    
    return env->NewStringUTF(result.c_str());
}

常见问题与解决方案

问题1:CMake配置失败

症状:CMake Error: The source directory does not appear to contain CMakeLists.txt

解决:

bash 复制代码
# 验证OpenCV源码路径
ls -la "/d/opencv-4.11.0/CMakeLists.txt"

# 确保使用的是正确的路径格式(Git Bash使用正斜杠)

问题2:编译时内存不足

症状:编译过程卡住或编译器被杀死

解决:

bash 复制代码
# 减少并行编译线程数
"$CMAKE_BIN" --build . --parallel 4  # 改为4线程

# 关闭其他内存占用大的程序

问题3:生成的.so文件找不到

症状:编译成功但输出目录为空

解决:

bash 复制代码
# 手动查找.so文件
find "/d/opencv_build_arm64-v8a" -name "*.so" -type f

# 检查lib目录结构
ls -la "/d/opencv_build_arm64-v8a/lib/"

进阶优化

  1. 多ABI架构支持

修改脚本支持批量编译多个架构:

bash 复制代码
#!/bin/bash
# 批量编译多个ABI

ABI_LIST=("arm64-v8a" "armeabi-v7a" "x86_64")

for ABI in "${ABI_LIST[@]}"; do
    echo "开始编译 $ABI ..."
    # 修改ABI变量并重新执行编译逻辑
    BUILD_DIR="/d/opencv_build_${ABI}"
    # ... 编译流程
done
  1. 模块化定制

根据项目需求选择编译的模块:

bash 复制代码
# 基础图像处理配置(最小化)
-DBUILD_LIST="core,imgproc,imgcodecs"

# 计算机视觉项目配置
-DBUILD_opencv_calib3d=ON
-DBUILD_opencv_features2d=ON
-DBUILD_opencv_objdetect=ON

# 禁用不需要的模块以减少体积
-DBUILD_opencv_dnn=OFF
-DBUILD_opencv_gapi=OFF

总结

通过纯命令行方式编译OpenCV Android库,我获得了以下优势:

  1. 完全掌控构建过程:可以精确控制编译选项和模块
  2. 脱离Android Studio依赖:适合CI/CD自动化流程
  3. 定制化程度高:按需编译,减少应用体积
  4. 学习价值大:深入理解OpenCV构建系统

这种编译方式特别适合:

· 需要特定OpenCV配置的项目

· 对应用体积敏感的生产环境

· 自动化构建和部署流程

· 学习和研究OpenCV内部结构

希望这篇记录能帮助到有类似需求的开发者。如果在实践过程中遇到问题,欢迎留言讨论。


相关资源:

· OpenCV官方源码

· Android NDK下载

· 完整脚本下载

编译环境:Windows 11 + Git Bash + Android NDK r26 + OpenCV 4.11.0

相关推荐
三少爷的鞋6 小时前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
Dovis(誓平步青云)10 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
晚风叙码12 小时前
MySQL 数据类型详解:从数值到字符串,一篇讲透
android·mysql·adb
传奇开心果编程12 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程15 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓17 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer