android - 如何将此项目更改为 OpenCV 实时人脸检测应用程序?
问题描述
Project是一个与我的 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 文件之前,应用程序已成功运行
请帮助我了解我的项目。
谢谢
解决方案
在这里,您对 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返回一个参数以显示在屏幕上。
我在您的 C++ 代码中看到您尝试做的第一件事是将输入的Mat转换为gray,但这不是必需的,因为传递给您的 C++ 代码的Matval mat = inputFrame.gray()
已经是灰色的(请参阅 参考资料)。
如果您想保持您的 C++ 代码完整,您还可以使用val mat = inputFrame.rgba()
.
推荐阅读
- python - Google API:将 auth_code 转换为 access_token | Python
- ruby-on-rails - 为什么我所有的 Gem 命令突然都不起作用了?
- frequency-analysis - matlab中的幅度平方相干性
- mysql - mysql使用没有连接的子查询
- python - PyImport_Import 段。从 Python 调用调用 Python 的 C 后的错误
- matlab - 无法将绘图保存为 png 文件(使用 hgexport 时出错)
- python - Python - 从 p7s 文件中提取证书
- laravel - 如何获取登录用户的愿望清单
- javascript - Do循环不断重复
- tensorflow - libtensorflow_framework.so:未定义符号:cuDevicePrimaryCtxGetState