如何将此项目更改为 OpenCV 实时人脸检测应用程序?

How can I change this project to a OpenCV realtime face detection app?

Project 是一个与我的项目相同的实时图像处理器,但它使用输入和输出两个值(我记得这些项目正在使用框架进行处理)。 我改变了它的原生-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);
        }
    }
}
}

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

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

请帮助我解决我的项目。

谢谢

此处您对 C++ 方法的定义做了一些更改 Java_com_example_nativeopencvandroidtemplate_MainActivity_adaptiveThresholdFromJNI,因此您必须在 Kotlin 端反映这些更改,因为此方法是使用 JNI 从您的 MainActivity.kt 调用。这是您必须在 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[=29 返回该参数=] 显示在屏幕上。

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

如果您想保持您的 C++ 代码完整无缺,您还可以使用 val mat = inputFrame.rgba().

将相机视图框架的彩色版本传递给您的 C++ 代码