Android下使用jni实现基于opencv与dlib的68关键点检测

关键点:
  • 配置项目依赖项环境
  • 从手机摄像头获取图片帧
  • 将图片帧数据传到C++层及从C++层获取处理后的图片帧数据
  • 不安装opencv manager运行基于android opencv库
  • C++层68关键点检测
  • 项目编译

效果图:

这里写图片描述

配置项目依赖项环境

NDK的安装配置请自行百度,Android opencv sdk下载
1.新建Android项目
2.右键项目—>Android Tools—>Add Native Supports…

3.在生成的jni目录下新建Application.mk

APP_PLATFORM := android-18
APP_STL := gnustl_static
APP_ABI := armeabi-v7a 

4.右键项目—>properties—>c/c++General—>Paths and Symbols—>Include—>add

${NDK_HOME}/platforms/android-18/arch-arm/usr/include
${NDK_HOME}/sources/cxx-stl/gnu-libstdc++/4.9/include
${NDK_HOME}/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include

5.在Project Explorer空白处右键import->General->Existing Projects into Workspace->选择下载的opencvSDK目录下sdk目录
如:E:\OpenCV-2.4.10-android-sdk\sdk,在Project中选择Opencv Library这个项目->Finish.
然后右键之前创建的项目->properties->android->在Library栏中点击Add,弹出框中选择OpenCV Library,点击OK,然后Apply,OK。

6.在项目根目录创建third_party目录,然后将E:\OpenCV-2.4.10-android-sdk\sdk\native拷贝进来具体结构可参考Demo

从手机摄像头获取图片帧(下一篇博文讲述)

将图片帧数据传到C++层及从C++层获取处理后的图片

private Bitmap srcBitmap;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.person);
srcBitmap = bitmap;
Mat input = new Mat();
Mat output = new Mat();
Utils.bitmapToMat(srcBitmap, input);
Landmarks.landMarks(input.getNativeObjAddr(), output.getNativeObjAddr());
Utils.matToBitmap(output, srcBitmap);  

不安装opencv manager运行基于android opencv库

1.在项目jni目录下创建prebuilt文件夹,在opencv sdk中将相应Android架构下的libopencv_java.so拷贝进来然后新建Androidusc.mk文件.

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := opencv_java
LOCAL_SRC_FILES := libopencv_java.so
include $(PREBUILT_SHARED_LIBRARY)

在Android.mk文件最后添加include $(TOP_LEVEL_PATH)/prebuilt/Androidusc.mk(TOP_LEVEL_PATH路径根据项目进行修改)
在Java代码中引用

@Override
public void onResume()
{
    super.onResume();
    if (!OpenCVLoader.initDebug()) {

    } else {
        System.loadLibrary("DlibLandmarks");  
    }
}

C++层68关键点检测

void detect(cv::Mat input){
    LOGE("detect");
    Mat result;
    cvtColor(input, result, CV_RGBA2BGR);
    assign_image(img, cv_image<bgr_pixel>(result));

    std::vector<dlib::rectangle> dets = detector(img);//检测人脸,获得边界框

    int Max = 0;
    int area = 0;
    if (dets.size() != 0)
    {
        for (unsigned long t = 0; t < dets.size(); ++t)
        {
            if (area < dets[t].width()*dets[t].height())
            {
                area = dets[t].width()*dets[t].height();
                Max = t;
            }
        }
    }

    full_object_detection shape = sp(img, dets[Max]);
    box.x = dets[Max].left();
    box.y = dets[Max].top();
    box.width = dets[Max].width();
    box.height = dets[Max].height();

    pts2d.clear();
    // 将结果保存至 pts2d 里面
    for (size_t k = 0; k < shape.num_parts(); k++) {
        Point2d p(shape.part(k).x(), shape.part(k).y());
        pts2d.push_back(p);
    }
}

项目编译

项目Android.mk

LOCAL_PATH := $(call my-dir)
# =======================================================
include $(CLEAR_VARS)

# Define 3rd party path
TOP_LEVEL_PATH = $(LOCAL_PATH)/..
$(info TOP_LEVEL_PATH: $(TOP_LEVEL_PATH))
THIRD_PARTY_PATH = $(LOCAL_PATH)/../../third_party
OPENCV_PATH = $(THIRD_PARTY_PATH)/opencv

OpenCV_INSTALL_MODULES := on
OPENCV_LIB_TYPE := SHARE
include $(OPENCV_PATH)/jni/OpenCV.mk

LOCAL_MODULE := DlibLandmarks

LOCAL_C_INCLUDES :=$(OPENCV_PATH)/jni/include \
    $(LOCAL_PATH)/../dlib \

LOCAL_SRC_FILES := \
    ../dlib//dlib/threads/threads_kernel_shared.cpp \
    ../dlib/dlib/entropy_decoder/entropy_decoder_kernel_2.cpp \
    ../dlib/dlib/base64/base64_kernel_1.cpp \
    ../dlib/dlib/threads/threads_kernel_1.cpp \
    ../dlib/dlib/threads/threads_kernel_2.cpp 


LOCAL_SRC_FILES += \
           DlibLandmarks.cpp

LOCAL_LDLIBS := -lm -llog -ldl -lz -ljnigraphics
LOCAL_CPPFLAGS += -fexceptions -frtti -std=c++11

LOCAL_ARM_MODE := arm
ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
    LOCAL_ARM_NEON := true
endif

include $(BUILD_SHARED_LIBRARY)
#-----------------------------------------------------------------------------
include $(TOP_LEVEL_PATH)/prebuilt/Androidusc.mk

注意:请仔细查看各级文件路径,具体文件层级请参考Demo。

Demo(DlibLandmarks)下载

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Android使用JNI调用OpenCV库来实现摄像头功能是可行的。以下是调用摄像头的简单步骤: 首先,你需要在Android项目中集成OpenCV库。可以通过将OpenCV库添加到Gradle依赖项或手动导入库文件来完成。 其次,创建一个JNI接口,将Java代码与C/C++代码进行绑定。JNI接口允许在Java和C/C++之间进行双向通信。 然后,在C/C++代码中编写与摄像头相关的功能。可以使用OpenCV提供的函数和类来处理视频流。例如,你可以使用VideoCapture类打开摄像头并获取图像帧。 接下来,在JNI接口中实现调用摄像头的功能。通过JNI接口,将Java代码的请求传递给C/C++函数来执行摄像头操作。你可以设置一个循环,不断从摄像头读取图像帧并进行处理。 最后,在Java代码中调用JNI接口中的方法来启动摄像头。可以使用SurfaceView来显示摄像头捕获的图像。你可以使用Camera类来控制摄像头的预览以及其他设置。 需要注意的是,在JNI和C/C++代码中处理摄像头操作时,要遵循正确的线程管理和图像处理技术,以确保流畅的手机摄像头应用程序。 总之,通过JNI调用OpenCV库,可以很方便地在Android实现摄像头功能。项目中要同时涉及Java和C/C++代码,需要进行正确的接口绑定和线程管理。这样,你可以轻松地使用OpenCV函数和类来处理摄像头操作并实现自己的摄像头应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sun-Eve

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值