【问题标题】:How can I change this project to a OpenCV realtime face detection app?如何将此项目更改为 OpenCV 实时人脸检测应用程序?
【发布时间】:2020-01-09 09:00:12
【问题描述】:

Project 是一个与我的项目相同的实时图像处理器,但它使用两个值,即输入和输出(我记得这些项目使用帧进行类似的处理)。 我更改了它的 native-lib.cpp 文件

#include <jni.h>
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include <android/log.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#define TAG "NativeLib"

using namespace std;
using namespace cv;

extern "C" {
//void detect(Mat& input);
void JNICALL Java_com_example_nativeopencvandroidtemplate_MainActivity_adaptiveThresholdFromJNI(JNIEnv *env, jobject instance, jlong inputAddr, jlong outputAddr) {

    Mat &input = *(Mat *) inputAddr;
    Mat &output = *(Mat *) outputAddr;

    clock_t begin = clock();

    cv::adaptiveThreshold(input, output, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV, 21, 5);

    double total_time = double (clock() - begin ) / CLOCKS_PER_SEC;
    __android_log_print(ANDROID_LOG_INFO, TAG, "adaptiveThreshold computation time = %f seconds\n",  total_time);
}
}

到这里

#include <jni.h>
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include <android/log.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>



using namespace std;
using namespace cv;

extern "C" {
void detect(Mat &input);
void JNICALL
Java_com_example_nativeopencvandroidtemplate_MainActivity_adaptiveThresholdFromJNI(JNIEnv *env, jobject instance,
                                                                                   jlong inputAddr) {

    Mat &input = *(Mat *) inputAddr;
    detect(input);
 }
void detect(Mat &input) {
    String face_cascade_name = "/storage/emulated/0/ony.xml";
    String eyes_cascade_name = "/storage/emulated/0/moe.xml";
    CascadeClassifier face_cascade;
    CascadeClassifier eyes_cascade;


    if (!face_cascade.load(face_cascade_name)) {
        printf("--(!)Error loading\n");
        return;
    };
    if (!eyes_cascade.load(eyes_cascade_name)) {
        printf("--(!)Error loading\n");
        return;
    };


    std::vector<Rect> faces;
    Mat frame_gray;


    cvtColor( input, frame_gray, COLOR_RGB2GRAY );
    equalizeHist(frame_gray, frame_gray);

    //-- Detect faces
    face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));

    for (size_t i = 0; i < faces.size(); i++) {
        Point center(faces[i].x + faces[i].width * 0.5, faces[i].y + faces[i].height * 0.5);
        ellipse(input, center, Size(faces[i].width * 0.5, faces[i].height * 0.5), 0, 0, 360, Scalar(255, 0, 255), 4, 8,
                0);

        Mat faceROI = frame_gray(faces[i]);
        std::vector<Rect> eyes;

        //-- In each face, detect eyes
        eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));

        for (size_t j = 0; j < eyes.size(); j++) {
            Point center(faces[i].x + eyes[j].x + eyes[j].width * 0.5, faces[i].y + eyes[j].y + eyes[j].height * 0.5);
            int radius = cvRound((eyes[j].width + eyes[j].height) * 0.25);
            circle(input, center, radius, Scalar(255, 0, 0), 4, 8, 0);
        }
    }
}
}

但在我的手机中,黑屏可能持续了五秒钟,并且应用程序反复停止。

注意:同步和构建已成功,在我更改 cpp 文件之前,应用程序已成功运行

请帮助我了解我的项目。

谢谢

【问题讨论】:

标签: android c++ opencv java-native-interface


【解决方案1】:

在这里,您对 C++ 方法 Java_com_example_nativeopencvandroidtemplate_MainActivity_adaptiveThresholdFromJNI 的定义进行了一些更改,因此您必须在 Kotlin 端反映这些更改,因为此方法是从您的 MainActivity.kt 调用的 使用 JNI。以下是您必须在 MainActivity.kt 中调整的代码:

class MainActivity : Activity(), CameraBridgeViewBase.CvCameraViewListener2 {

    ...

    override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame): Mat {
        val mat = inputFrame.gray()

        adaptiveThresholdFromJNI(mat.nativeObjAddr)

        return mat
    }

    private external fun adaptiveThresholdFromJNI(matAddr: Long)

    ...

}

这里 adaptiveThresholdFromJNI 被调整为只处理一个参数(就像您对 C++ 等效项所做的那样),然后从 onCameraFrame 返回一个参数以显示在屏幕上.

我在您的 C++ 代码中看到您尝试做的第一件事是将输入的 Mat 转换为 gray,但这不是必需的,因为 传递给您的 C++ 代码的 Mat 已经是灰色的(请参阅 val mat = inputFrame.gray())。

如果您想保持您的 C++ 代码完好无损,您还可以使用 val mat = inputFrame.rgba() 将相机视图框架的彩色版本传递给您的 C++ 代码。

【讨论】:

  • 谢谢!我做到了,现在相机工作正常但没有检测到。而且我认为我们需要使用“框架”作为“输入”。请帮忙。再次感谢你们的好 cmets!
  • 正确,我将更改我的答案并使用“matAddr”而不是“input”。如果它解决了您的问题,您可以将我的回复标记为答案吗?对于人脸检测部分,如果它不起作用,请不要忘记您也可以在 C++ 代码中使用带有一些断点的 Android Studio 调试器!您还可以在 C++ 代码中使用“__android_log_print”将一些调试日志打印到 Android logcat 以帮助调试。您能尝试了解您的 C++ 代码在哪里出错吗?
  • 是的,我在 MainActivity.kt 中使用“mat”而不是“input”修复了它,我在 cpp 中使用了“matAddr”而不是“inputAddr”,并添加了您所说的其他更改。谢谢!
猜你喜欢
  • 2012-12-10
  • 2016-03-13
  • 2012-02-04
  • 2013-05-24
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 2014-01-31
  • 2012-04-15
相关资源
最近更新 更多