【android opencv学习笔记】Day 1: Hello OpenCV
·

初识 OpenCV for Android
大家好,本篇文章将带你从零开始,在 Android 项目中集成 OpenCV,并使用 Native C++ 实现一张全屏的「Hello OpenCV」图像绘制。
什么是 OpenCV
OpenCV(Open Source Computer Vision Library)是一个开源计算机视觉库,用于图像处理、视频分析、特征检测、人脸识别、目标跟踪等。
在 Android 上,OpenCV 有两种使用方式:
- Java 版:简单、速度一般
- Native C++ 版:高性能、原生执行(本篇使用)
性能差距:复杂图像处理时,C++ 版本比 Java 快 3~10 倍。
| 任务 | Java 版耗时 | Native(C++) 版耗时 | 差距 |
|---|---|---|---|
| Hello World / 画文字 | 1ms | 0.5ms | 几乎一样 |
| 灰度化 (640x480) | 8~12ms | 2~3ms | 快 3~5 倍 |
| 高斯模糊/边缘检测 | 20~40ms | 5~8ms | 快 4~6 倍 |
| 特征点检测(SIFT/SURF) | 200ms+ | 30~50ms | 快 5~10 倍 |
| 4K 大图处理 | 经常卡顿 | 流畅 | 差距巨大 |
开发环境
- Android Studio
- NDK 27+
- OpenCV Android SDK 4.8.0
- Kotlin + build.gradle.kts
- 真机(arm64-v8a)
OpenCV 下载
官网:https://opencv.org/releases/
下载:
OpenCV-4.8.0-android.zip
解压备用。
项目结构(必须严格对应)
app/
├── src/main/
│ ├── cpp/
│ │ ├── opencv/include/ <-- OpenCV 头文件
│ │ ├── native-lib.cpp <-- C++ 代码
│ │ └── CMakeLists.txt <-- C++ 构建配置
│ ├── jniLibs/
│ │ ├── arm64-v8a/
│ │ ├── armeabi-v7a/
│ │ └── ...其他架构
│ ├── res/layout/activity_main.xml
│ └── java/.../MainActivity.kt
└── build.gradle.kts
项目实例
开源库:gitee仓库
CMakeLists.txt
cmake_minimum_required(VERSION 3.22.1)
project(nativeopencv)
# OpenCV 头文件
include_directories(${CMAKE_SOURCE_DIR}/opencv/include)
# OpenCV 库路径
set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
link_directories(${OpenCV_DIR})
# 编译自己的 so
add_library(
native-lib
SHARED
native-lib.cpp
)
# 链接库
target_link_libraries(
native-lib
opencv_java4
log
jnigraphics
android
)
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_show"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
MainActivity.kt
package com.nicoli.helloopencv
import android.graphics.Bitmap
import android.os.Bundle
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 获取屏幕宽高
val display = windowManager.defaultDisplay
val size = android.graphics.Point()
display.getSize(size)
val w = size.x
val h = size.y
val iv = findViewById<ImageView>(R.id.iv_show)
iv.setImageBitmap(getHelloOpenCVBitmap(w, h))
}
// 调用 C++ 函数
private external fun getHelloOpenCVBitmap(width: Int, height: Int): Bitmap
companion object {
init {
System.loadLibrary("opencv_java4")
System.loadLibrary("native-lib")
}
}
}
native-lib.cpp
// JNI 基础头文件
#include <jni.h>
// OpenCV 核心头文件
#include <opencv2/opencv.hpp>
// Android Bitmap 操作库
#include <android/bitmap.h>
// 使用 OpenCV 命名空间
using namespace cv;
/**
* 供 Kotlin 调用的 JNI 函数
* 函数名规则:Java_包名_类名_方法名
*
* @param env JNI 环境
* @param thiz 当前 Activity 对象
* @param width 屏幕宽
* @param height 屏幕高
* @return Bitmap 对象
*/
extern "C"
JNIEXPORT jobject JNICALL
Java_com_nicoli_helloopencv_MainActivity_getHelloOpenCVBitmap(
JNIEnv *env,
jobject thiz,
jint width,
jint height
) {
// ==========================
// 1. 创建与屏幕一样大的黑色图像
// ==========================
// Mat:OpenCV 存储图像的类
// 高、宽、图像类型(CV_8UC3=彩色图)、颜色(0,0,0=黑色)
Mat mat(height, width, CV_8UC3, Scalar(0, 0, 0));
// ==========================
// 2. 在图像上绘制绿色文字
// ==========================
putText(
mat, // 目标图像
"Hello, OpenCV!", // 文字内容
Point(width/2 - 230, height/2), // 位置(居中)
FONT_HERSHEY_SIMPLEX, // 字体
3.0, // 字体大小
Scalar(0, 255, 0), // 颜色:绿色(BGR)
5 // 文字粗细
);
// ==========================
// 3. 颜色格式转换
// OpenCV:BGR
// Android:RGBA
// ==========================
cvtColor(mat, mat, COLOR_BGR2RGBA);
// ==========================
// 4. 创建 Android Bitmap
// ==========================
jclass bmpCls = env->FindClass("android/graphics/Bitmap");
jclass configCls = env->FindClass("android/graphics/Bitmap$Config");
// 获取 ARGB_8888 配置
jfieldID argbField = env->GetStaticFieldID(configCls, "ARGB_8888", "Landroid/graphics/Bitmap$Config;");
jobject config = env->GetStaticObjectField(configCls, argbField);
// 创建 Bitmap
jmethodID createBmp = env->GetStaticMethodID(bmpCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jobject bitmap = env->CallStaticObjectMethod(bmpCls, createBmp, width, height, config);
// ==========================
// 5. 将 Mat 数据写入 Bitmap
// ==========================
void *pixels;
// 锁定 Bitmap 内存
AndroidBitmap_lockPixels(env, bitmap, &pixels);
// 拷贝图像数据
memcpy(pixels, mat.data, mat.total() * mat.elemSize());
// 解锁
AndroidBitmap_unlockPixels(env, bitmap);
// 返回 Bitmap 给 Kotlin
return bitmap;
}

核心知识点总结
Mat 类
1. 定义
Mat = Matrix(矩阵)
OpenCV 中存储图像的基础数据结构。
你可以把它理解为:
一张图片 = 一个数字矩阵
2. 作用
- 存储图像像素数据
- 存储图像宽、高、通道数、深度
- 所有 OpenCV 操作都围绕 Mat 展开
3. 类结构(简化版)
class Mat
{
public:
int rows; // 高
int cols; // 宽
int channels(); // 通道数:彩色图3,灰度图1
uchar* data; // 像素数据指针
};
4. 继承关系(OpenCV 官方继承链)
Mat
↑
MatExpr
↑
Matx
↑
InputArray / OutputArray
真正重要的继承关系(实际开发):
Mat
↑
UMat (用于OpenCL加速)
↑
cuda::GpuMat (GPU加速)
5. 图像类型解释
CV_8UC1→ 8 位灰度图CV_8UC3→ 8 位彩色图(BGR)CV_8UC4→ 8 位带透明通道(RGBA)
6. 我们代码中的 Mat
Mat mat(height, width, CV_8UC3, Scalar(0, 0, 0));
- 高 height
- 宽 width
- 3 通道彩色图
- 黑色背景
putText 函数(绘制文字)
1. 作用
在图像上绘制文字。
2. 归属
属于 imgproc 模块 的绘图功能。
3. 函数原型
void putText(
InputArray img, // 输入图像(Mat)
const String& text, // 文字
Point org, // 文字位置
int fontFace, // 字体
double fontScale, // 字体大小
Scalar color, // 颜色
int thickness = 1 // 粗细
);
4. 继承关系
putText 不是类,是全局函数,但它操作的类关系:
drawMarker
putText → 都继承自:DrawingFunctions
line
rectangle
circle
5. 代码中的使用
putText(
mat,
"Hello, OpenCV!",
Point(width/2 - 230, height/2),
FONT_HERSHEY_SIMPLEX,
3.0,
Scalar(0,255,0),
5
);
cvtColor 函数(颜色空间转换)
1. 作用
转换图像的颜色格式。
2. 为什么必须用?
- OpenCV 默认:BGR
- Android Bitmap 默认:RGBA
颜色顺序不一样,必须转换!
3. 函数原型
void cvtColor(
InputArray src, // 源图像
OutputArray dst, // 目标图像
int code, // 转换类型
int dstCn = 0
);
4. 常用转换
COLOR_BGR2GRAY→ 彩色转灰度COLOR_BGR2RGB→ BGR 转 RGBCOLOR_BGR2RGBA→ BGR 带透明通道
5. 代码中的作用
cvtColor(mat, mat, COLOR_BGR2RGBA);
把 OpenCV 格式 → 转为 Android 能显示的格式。
最重要的三张继承图
1. 图像数据容器继承图
BaseMat
↑
-------
↑ ↑
Mat SparseMat
↑
UMat
↑
cuda::GpuMat
2. 绘图功能关系
DrawingFunctions
↑ ↑ ↑ ↑ ↑
putText
rectangle
circle
line
drawMarker
3. 颜色转换模块
ColorProcessing
↑
cvtColor
↑
COLOR_BGR2GRAY
COLOR_BGR2RGB
COLOR_BGR2HSV
...
结语
这篇文章带你完成了 Android + OpenCV + Native C++ 的第一个真正原生项目。
OpenCV 非常强大,从简单的绘图到复杂的 AI 视觉算法都能轻松实现。Native 开发虽然配置稍复杂,但换来的是极致性能。

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)