Android集成OpenCV(NDK)

这篇具有很好参考价值的文章主要介绍了Android集成OpenCV(NDK)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.下载OpenCv的动态库(.so)

OpenCv官网,这边下载的是4.6.0
Android集成OpenCV(NDK)

2.解压opencv-4.6.0-android-sdk.zip

复制目录opencv-4.6.0-android-sdk\OpenCV-android-sdk\sdk\native\jniinclude文件夹,和opencv-4.6.0-android-sdk\OpenCV-android-sdk\sdk\native\libs\armeabi-v7a目录对应的cpu架构类型.项目没有对应目录,手动创建一下.
Android集成OpenCV(NDK)

3.配置CMakeLists

可以参考Android NDK项目CMakeLists.txt配置导入第三方库

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.18.1)

# Declares and names the project.

project("mnnmyh")

aux_source_directory(. SRC_LIST) # 当前文件夹下的所有文件,不包含子文件夹
add_library( # Sets the name of the library.
        mnnmyh
        # Sets the library as a shared library.
        SHARED
        # Provides a relative path to your source file(s).
        #native-lib.cpp)
        ${SRC_LIST})
        
#opencv
include_directories(${CMAKE_SOURCE_DIR}/opencv/include/)
add_library(libopencv_java4 SHARED IMPORTED)
set_target_properties(
        libopencv_java4
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libopencv_java4.so)


find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

target_link_libraries( # Specifies the target library.
        mnnmyh
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib}
        #jnigraphics库可以用来从android.bitmap.Graphics类 访问C / C ++中的位图缓冲区
        jnigraphics
        libopencv_java4
        )

4.测试OpenCV是否配置正常

参考github OpenCV ,实现图片灰度转换
先写一个bitmap转mat工具类
utils.hpp

//
// Created by moyihen on 2022/8/17.
//

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"

#ifdef __ANDROID__

#include <android/bitmap.h>
#include "android/log.h"

#define TAG "org.opencv.android.Utils"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
using namespace cv;

void BitmapToMat(JNIEnv *env, jobject bitmap, Mat &dst, jboolean needUnPremultiplyAlpha) {
    AndroidBitmapInfo info;
    void *pixels = 0;
    try {
        CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
        CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
                  info.format == ANDROID_BITMAP_FORMAT_RGB_565);
        CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
        CV_Assert(pixels);
        dst.create(info.height, info.width, CV_8UC4);
        if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
            LOGD("nBitmapToMat: RGBA_8888 -> CV_8UC4");
            Mat tmp(info.height, info.width, CV_8UC4, pixels);
            if (needUnPremultiplyAlpha) cvtColor(tmp, dst, COLOR_mRGBA2RGBA);
            else tmp.copyTo(dst);
        } else {
            // info.format == ANDROID_BITMAP_FORMAT_RGB_565
            LOGD("nBitmapToMat: RGB_565 -> CV_8UC4");
            Mat tmp(info.height, info.width, CV_8UC2, pixels);
            cvtColor(tmp, dst, COLOR_BGR5652RGBA);
        }
        AndroidBitmap_unlockPixels(env, bitmap);
        return;
    } catch (const cv::Exception &e) {
        AndroidBitmap_unlockPixels(env, bitmap);
        LOGE("nBitmapToMat caught cv::Exception: %s", e.what());
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
        return;
    } catch (...) {
        AndroidBitmap_unlockPixels(env, bitmap);
        LOGE("nBitmapToMat caught unknown exception (...)");
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}");
        return;
    }
}
void MatToBitmap(JNIEnv *env, Mat &src, jobject bitmap, jboolean needPremultiplyAlpha) {
    AndroidBitmapInfo info;
    void *pixels = 0;
    try {
        LOGD("nMatToBitmap");
        CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
        CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
                  info.format == ANDROID_BITMAP_FORMAT_RGB_565);
        CV_Assert(src.dims == 2 && info.height == (uint32_t) src.rows &&
                  info.width == (uint32_t) src.cols);
        CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4);
        CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
        CV_Assert(pixels);
        if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
            Mat tmp(info.height, info.width, CV_8UC4, pixels);
            if (src.type() == CV_8UC1) {
                LOGD("nMatToBitmap: CV_8UC1 -> RGBA_8888");
                cvtColor(src, tmp, COLOR_GRAY2RGBA);
            } else if (src.type() == CV_8UC3) {
                LOGD("nMatToBitmap: CV_8UC3 -> RGBA_8888");
                cvtColor(src, tmp, COLOR_RGB2RGBA);
            } else if (src.type() == CV_8UC4) {
                LOGD("nMatToBitmap: CV_8UC4 -> RGBA_8888");
                if (needPremultiplyAlpha) cvtColor(src, tmp, COLOR_RGBA2mRGBA);
                else src.copyTo(tmp);
            }
        } else {
            // info.format == ANDROID_BITMAP_FORMAT_RGB_565
            Mat tmp(info.height, info.width, CV_8UC2, pixels);
            if (src.type() == CV_8UC1) {
                LOGD("nMatToBitmap: CV_8UC1 -> RGB_565");
                cvtColor(src, tmp, COLOR_GRAY2BGR565);
            } else if (src.type() == CV_8UC3) {
                LOGD("nMatToBitmap: CV_8UC3 -> RGB_565");
                cvtColor(src, tmp, COLOR_RGB2BGR565);
            } else if (src.type() == CV_8UC4) {
                LOGD("nMatToBitmap: CV_8UC4 -> RGB_565");
                cvtColor(src, tmp, COLOR_RGBA2BGR565);
            }
        }
        AndroidBitmap_unlockPixels(env, bitmap);
        return;
    } catch (const cv::Exception &e) {
        AndroidBitmap_unlockPixels(env, bitmap);
        LOGE("nMatToBitmap caught cv::Exception: %s", e.what());
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
        return;
    } catch (...) {
        AndroidBitmap_unlockPixels(env, bitmap);
        LOGE("nMatToBitmap caught unknown exception (...)");
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
        return;
    }
}
#endif //__ANDROID__

nativ方法实现
native-lib.cpp

#include <jni.h>
#include <string>
#include "utils.hpp"

extern "C"
JNIEXPORT jstring JNICALL
Java_com_moyihen_mnnmyh_JniBitmapUtil_stringFromJNI(JNIEnv *env, jclass clazz) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}



extern "C"
JNIEXPORT void JNICALL
Java_com_moyihen_mnnmyh_JniBitmapUtil_coverImg2Gray(JNIEnv *env, jclass clazz, jobject bitmap) {
    //源图像
    Mat src;
    //将Bitmap转换为Mat
    BitmapToMat(env,bitmap,src, JNI_FALSE);

    //转换的灰度图
    Mat gray_image;
    cvtColor(src, gray_image, COLOR_BGR2GRAY );

    //将Mat转换为Bitmap
    MatToBitmap(env,gray_image,bitmap, JNI_FALSE);

    //释放Mat
    src.release();
    gray_image.release();
}
import android.graphics.Bitmap;

public class JniBitmapUtil {
    // Used to load the 'mnnmyh' library on application startup.
    static {
        System.loadLibrary("mnnmyh");
    }

    /**
     * A native method that is implemented by the 'mnnmyh' native library,
     * which is packaged with this application.
     */
    public static native String stringFromJNI();

    public static native void coverImg2Gray(Bitmap bitmap);
}

调用

 mCvBinding.button.setOnClickListener(v -> {
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.hzw);
            JniBitmapUtil.coverImg2Gray(bitmap);

            mCvBinding.img2.setImageBitmap(bitmap);

        });

效果
Android集成OpenCV(NDK)

注意:调试的时候出现几个问题,可以参考下
1. dlopen failed: library “libc++_shared.so” not found
Android集成OpenCV(NDK)
需在在app的build.gradle配置arguments “-DANDROID_STL=c++_shared”

defaultConfig {
        externalNativeBuild {
            cmake {
                cppFlags '-std=c++11'
                arguments "-DANDROID_STL=c++_shared"
            }
        }
    }

2.error: undefined symbol: AndroidBitmap_getInfo
Android集成OpenCV(NDK)
需要在CMakeLists.txt的target_link_libraries 加上jnigraphics文章来源地址https://www.toymoban.com/news/detail-461676.html

target_link_libraries( # Specifies the target library.
        mnnmyh
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib}
        #jnigraphics库可以用来从android.bitmap.Graphics类 访问C / C ++中的位图缓冲区
        jnigraphics
        libopencv_java4
        )

到了这里,关于Android集成OpenCV(NDK)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android ffmpeg入门(1)—— 使用NDK交叉编译ffmpeg集成到Android项目

    最近在学习android NDK开发相关内容,借ffmpeg练练手。ffmpeg是做音视频方面功能的基础,后面会随着个人的学习更新一系列ffmpeg博客,防止自己遗忘。 这个系列博客主要目的是基于ffmpeg通过NDK开发的方式完成一个基本的视频播放器。 本篇博客主要实现了 ffmpeg编译 以及 引入 a

    2023年04月08日
    浏览(33)
  • android studio 如何下载指定版本的NDK

    安装及配置 NDK 和 CMake  |  Android 开发者  |  Android Developers 如果官方文档看不懂的,就看我写的口水话版本吧; 1、AS打开SDK、NDK下载的那个对话框,如图:    2、非常关键的一步,默认情况下选项的子项未展开,所以需要勾选右下角 “Show Package Detail” ,CMake也是一样的哈

    2024年02月12日
    浏览(41)
  • 什么是集成测试来看这边

    什么是集成测试 集成测试(Integration Testing),也叫组装测试或联合测试。在单元测试的基础上,将所有模块按照设计要求(如根据结构图)组装成为子系统或系统,进行集成测试。 集成测试(也叫组装测试,联合测试)是单元测试的逻辑扩展。它最简单的形式是:把两个已

    2024年02月15日
    浏览(46)
  • opencv官网文档学习

    在github上面也可以找到资源: https://github.com/opencv/opencv/tree/4.x 手写数据图片:https://github.com/opencv/opencv/blob/4.x/samples/data/digits.png 手写数据data:https://github.com/opencv/opencv/blob/4.x/samples/data/letter-recognition.data 人脸识别xml文件:https://github.com/opencv/opencv/tree/4.x/data/haarcascades 我将项目

    2024年02月06日
    浏览(32)
  • android ndk clang交叉编译ffmpeg动态库踩坑

    1.ffmpeg默认使用gcc编译,在android上无法使用,否则各种报错,所以要用ndk的clang编译 2.下载ffmpeg源码 修改configure文件,增加命令 cross_prefix_clang 修改以下命令 修改后 3.新建脚本文件,ffmpeg目录下执行脚本文件即可。 编译32位,则ARCH改为arm,CPU改为armv7-a,TARGET改为armv7a-linux-

    2024年02月13日
    浏览(38)
  • 【跟官网学opencv-python】笔记1.2:opencv基本绘图函数

    目录 前言 目标 函数详解 1、cv2.line()画线 2、cv2.rectangle()画矩形 3、cv2.circle()画圆 4、cv2.ellipse()画椭圆 5、cv2.polylines()画多边形 6、cv2.putText()绘制文本 代码演示 运行效果 参考 跟着官网学习才是基础入门的最佳选择,下文是opencv-python官网的学习记录及扩展! 掌握基本绘图函数

    2024年02月07日
    浏览(33)
  • 【跟官网学opencv-python】笔记1.3:opencv鼠标绘图 cv2.setMouseCallback()

    目录 前言 目标 函数详解 1、cv2.setMouseCallback()鼠标回调函数 2、鼠标事件简介 代码演示 ​编辑 应用演示 运行效果 参考 跟着官网学习才是基础入门的最佳选择,下文是opencv-python官网的学习记录及扩展! 学习函数cv2.setMouseCallback()并使用鼠标绘制不同图形(矩形、多边形等)

    2024年02月03日
    浏览(64)
  • 官网下载历史版本Android studio

    有时我们个更新到了最新版本的AndroidStudio,但发现最新版的有一些bug影响使用,这时我们需要将新版卸载安装到旧版本,本文便是记录如何在官网下载旧版本的android studio。 下载地址 点击下载即可

    2024年02月12日
    浏览(40)
  • Android Studio 进行NDK开发,实现JNI,以及编写C++与Java交互(Java调用本地函数)并编译出本地so动态库

    1.首先认识一下NDK。 (1)什么是NDK? NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C/C++的动态库,并能自动将so和java应用一起打包成apk。NDK集成了交叉编译器(交叉编译器需要UNIX或LINUX系统环境),并提供了相应的mk文件隔离CPU、平台、ABI等差异,

    2024年02月11日
    浏览(35)
  • 解决Android Studio无法连接官网下载SDK、SDK组件消失等问题(不用科学上网)

    今天笔者在Android Studio下载安装的问题上被折磨了好久,终于找到了解决方法,不用科学上网。进入网址多个地点Ping服务器,网站测速 - 站长工具 (chinaz.com) 在这里输入谷歌官方的的资源库网址dl.google.com,点击查询,找到延迟比较低的ip节点然后复制下来修改hosts,关于hosts的修

    2024年02月13日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包