OpenCV and C++: "Can't resolve variable 'Mat`" - android

I'm trying to integrate OpenCV in Android Java native interface using C++ language. I have placed the OpenCV inside the jni folder, where I'm writing my C++ code. I have included the Opencv header files in my HelloNative.c file. But I'm still getting this error while trying to access Mat object.
"Can't resolve variable Mat".
I have tried using namespace cv, but it gives an error to predeclare using and namespace; which is not a solution. I'm posting my code below, please somebody have a look at it and let me know what I'm doing wrong.
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/log.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <OpenCV/include/opencv2/opencv.hpp>
#include <OpenCV/include/opencv/cv.h>
#include <OpenCV/modules/core/include/opencv2/core.hpp>
#include <OpenCV/modules/core/include/opencv2/core/core_c.h>
#include <OpenCV/modules/core/include/opencv2/core/mat.hpp>
#include <OpenCV/modules/imgproc/include/opencv2/imgproc/imgproc.hpp>
#include <OpenCV/modules/imgproc/include/opencv2/imgproc/imgproc_c.h>
#include <OpenCV/modules/legacy/include/opencv2/legacy/legacy.hpp>
#include <OpenCV/modules/videostab/include/opencv2/videostab/motion_stabilizing.hpp>
#include <OpenCV/modules/videostab/include/opencv2/videostab/global_motion.hpp>
JNIEXPORT jint JNICALL
Java_com_example_soimporttest_MainActivity_getStringFromJNI(JNIEnv *env, jobject thisObj,
jstring imagepath) {
const char *jnamestr = (*env)->GetStringUTFChars(env, imagepath, 0);
int width, height, gray;
FILE *fp = fopen(jnamestr, "rb");
if (fp) {
//Read .pgm file
int scan = fscanf(fp, "P5%d%d%d", &width, &height, &gray);
if (scan != 3 || &gray > 256 || &width > 0xfffff || &height > 0xfffff || &gray <= 1 ||
&width < 32 || &height < 32) {
fclose(fp);
return 9;
} else {
return 0;
}
} else {
return -1;
}
}
JNIEXPORT void JNICALL
Java_com_example_soimporttest_MainActivity_displayImage(JNIEnv *env, jobject thisObj, jclass type, jlong inpAddr, jlong outAddr) {
::Mat &src = *(Mat*)inpAddr;
Mat &dst = *(Mat*)outAddr;
applyFilter(src , dst);
}
There are two functions in this file, the first function getStringFromJNI is working perfectly fine.
Thank you.

After a lot of research, I finally managed to find out a good solution for my question. Please follow below mentioned tutorial:
https://github.com/leadrien/opencv_native_androidstudio
You'll be facing some issues while integrating it. You can post those solutions in the comments and I will guide you through each.
Thanks.

Related

How to read a file in c using NDK in android

I am trying to read a file in c using NDK. When i debug the code, i see that i get a NULL pointer in f(file reading pointer). Also, my file which i need to read is in the same folder under cpp including all other header files. I have the read and write permissions for external storage in my app. Any help is appreciated.
C Code:
#ifndef client_h
#define client_h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "utility.h"
#define SENDBUFSIZE 1399
#define RECVBUFSIZE 1399
void pingServer(char *hostname, int portno)
{
//Some other functionality which works correctly
// File Read operations
FILE *f = fopen("somefile.csv", "r"); //Get the null pointer here
if (f == NULL)
perror("Could not open input file");
char *currentRow[3];
char *nextRow[3];
int rows = 3;
for (int i=0; i<rows; i++)
{
currentRow[i] = (char*)malloc(20 * sizeof(char));
nextRow[i] = (char*)malloc(20 * sizeof(char));
}
double current, next;
double elapsed;
int isNextRow, isCurentRow;
readCsvLine(f,currentRow,rows); //Get the headers
int counter = 2;
isCurentRow = readCsvLine(f,currentRow,rows);
//sends the data
//Free the memory
for (int i=0; i<rows; i++)
{
free(currentRow[i]);
free(nextRow[i]);
}
free(buf);
return;
}
char* printName(){
char* ptr = "hello From C";
return ptr;
}
#endif
Java code for calling the c methods:
#include <jni.h>
#include <string>
#include "client.h"
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_habbas_mobiledifferentiation_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
char *hostname = "127.0.0.1";
int portno = 1254;
pingServer(hostname, portno);
std::string hello = printName();
return env->NewStringUTF(hello.c_str());
}

"Not declared in this scope" error in Android JNI C++

I have this JNI code that uses C++.
#include <eigenfaces_jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/contrib/contrib.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
using namespace cv;
JNIEXPORT jstring JNICALL Java_com_example_facedetector_FaceTracker_nativeCreateObject
(JNIEnv *env, jclass, jstring JFileDir){
// These vectors hold the images and corresponding labels.
vector<Mat> images;
const char *str = env->GetStringUTFChars(jFileDir, NULL);
const char *buf;
/*Releasing the Java String once you have got the C string
is very important!!!*/
env->ReleaseStringUTFChars(jFileDir, str);
Mat im = imread(jFileDir);
if (im.empty())
{
cout << "Cannot load image!" << endl;
buf = "Can load image";
}
else{
buf = "Cannot load image";
}
return env->NewStringUTF("Hello");
}
However, there is always an error at
const char *str = env->GetStringUTFChars(jFileDir, NULL);
which states that
- Symbol 'jFileDir' could not be resolved
- 'jFileDir' was not declared in this scope
- Invalid arguments ' Candidates are: const char * GetStringUTFChars(_jstring *, unsigned
char *) '
Tried the solution in this link Type 'std::string' could not be resolved.
Still not working. Any help to solve this problem would be appreciated. Thank you.
You've declared a function parameter called JFileDir, but nothing called jFileDir. C++ is case-sensitive.
Well, since I don't have enough reputation points to commend, I have to write this as an answer. Check your function parameter list (JNIEnv *env, jclass, jstring JFileDir), what is jclass about, I feel something is missing here.

Reading frames from video file using openCV and Native code C++

I'm trying to write an app that gets all the frames of a video and manipulating them, I found oout that the best way to extract frames on Android is using OpenCv lib.
I saw in the sample code that uses VideoCapture object that receives the video path and can grab frames out of it, so I wrote the following code but the capture.open() doen't really open the video file, the capture.isOpen() is always false.
Source code:
#include <jni.h>
//opencv
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/background_segm.hpp>
#include <opencv2/core/mat.hpp>
//C
#include <stdio.h>
#include <string.h>
//C++
#include <iostream>
#include <sstream>
//Android
#include <android/log.h>
//#define LOGI(TAG,INFO) __android_log_print(ANDROID_LOG_INFO,INFO,__VA_ARGS__)
using namespace cv;
extern "C" {
JNIEXPORT void JNICALL Java_com_example_nativeopencvcheck_MainActivity_processVideo(JNIEnv* env,
jobject thsObj,jstring fileName) {
const char * fileNameNative;
jboolean isCopy;
fileNameNative = env->GetStringUTFChars(fileName, &isCopy);
//create the capture object
__android_log_print(ANDROID_LOG_ERROR, "From_Native",
"trying to open file: %s", fileNameNative);
VideoCapture capture(fileNameNative);
capture.open(fileNameNative);
if (!capture.isOpened()) { //!!!!!! ALWAYS CLOSED !!!!!
__android_log_write(ANDROID_LOG_ERROR, "From_Native",
"capture isn't open. closing..");
exit( EXIT_FAILURE);
}
Mat iplimage;
capture.retrieve(iplimage,0);
if (iplimage.size > 0) {
jclass cls = env->FindClass( "com/example/opencvframesext/MainActivity");
if (cls == 0) {
return;
}
jmethodID javamethod = env->GetMethodID(cls, "getCurrentFrameFromNative", "()V");
if (javamethod == 0) {
// LOGI("From_Native","GetMethodID error");
return;
}
jobject obj; // TODO
env->CallVoidMethod(obj, javamethod);
return;
}
/*bool gotFrame = capture.read(mat);
while (gotFrame) {
mats.addref(mat);
capture.read(mat);
}*/
//delete capture object
capture.release();
}
}
yea, that wont work, unfortunately.
there's no ffmpeg backend for VideoCapture on android.

Problems with JNI and C++

I did an Opencv's application en windows and now I am using JNI to convert this code to Android but I am having some problems.
In concrete my native code not do nothing.
This is my Java class where I define my native methods:
package com.example.telo3;
import org.opencv.core.Mat;
public class Process {
static {
System.loadLibrary("nativo");
}
public Process(){
dir=inicializar_nativo();
}
public void Procesar(Mat framedetect, Mat framedraw){
procesar_nativo(dir,framedetect.getNativeObjAddr(),framedraw.getNativeObjAddr());
}
private long dir;
private static native long inicializar_nativo();
private static native void procesar_nativo(long thiz, long framedetect, long framedraw);
}
This is my JNI code:
#include "nativo.h"
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/video/tracking.hpp"
#include <iostream>
#include <stdio.h>
#include "FaceDetector.h"
#include "Draw.h"
#include "Almacena.h"
#include "Runnable.h"
using namespace std;
using namespace cv;
#include <android/log.h>
#define LOG_TAG "NATIVO"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
struct variables {
Almacena almacena;
Draw draw;
FaceDetector face_detector;
};
JNIEXPORT jlong JNICALL Java_com_example_telo3_Process_inicializar_1nativo(
JNIEnv *, jobject) {
long dir = (long) new variables();
return (dir);
}
JNIEXPORT void JNICALL Java_com_example_telo3_Process_procesar_1nativo(JNIEnv *,
jobject, jlong dir, jlong framedetect, jlong framedraw) {
Mat* telo =(Mat*)framedetect;
Mat* telo2= (Mat*)framedraw;
((variables*)dir)->almacena = ((variables*)dir)->face_detector.Detect(*telo);
//almacena = face_detector.Detect(frame_gray);
((variables*)dir)->draw.Dibujar(*telo2,((variables*)dir)->almacena);
//frame_capturado = draw.Dibujar(frame_capturado, almacena);
if( (((variables*)dir)->almacena.get_faces()).size() ==0){
LOGD("no detecto caras");
}
}
I think that I use the Jni correctly but the function Detect not works correctly because when I uses this if return 0.
Looks like a simple typo for me.
Your package is "com.example.telo3"
Your class is "Process"
Your function is "inicializar_nativo()"
So the c++ function has to be declared as
JNIEXPORT jlong JNICALL Java_com_example_telo3_Process_inicializar_nativo(...)
You have declared it as
JNIEXPORT jlong JNICALL Java_com_example_telo3_Process_inicializar_1nativo(...)
Did you get an unsatisfied link exception or such?

JNI, C++ problems

I did an Opencv's application en windows and now I am using JNI to convert this code to Android but I am having some problems.
In concrete my native code not do nothing.
This is my Java class where I define my native methods:
package com.example.telo3;
import org.opencv.core.Mat;
public class Process {
static {
System.loadLibrary("nativo");
}
public Process(){
dir=inicializar_nativo();
}
public void Procesar(Mat framedetect, Mat framedraw){
procesar_nativo(dir,framedetect.getNativeObjAddr(),framedraw.getNativeObjAddr());
}
private long dir;
private static native long inicializar_nativo();
private static native void procesar_nativo(long thiz, long framedetect, long framedraw);
}
This is my JNI code:
#include "nativo.h"
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/video/tracking.hpp"
#include <iostream>
#include <stdio.h>
#include "FaceDetector.h"
#include "Draw.h"
#include "Almacena.h"
#include "Runnable.h"
using namespace std;
using namespace cv;
#include <android/log.h>
#define LOG_TAG "NATIVO"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
struct variables {
Almacena almacena;
Draw draw;
FaceDetector face_detector;
};
JNIEXPORT jlong JNICALL Java_com_example_telo3_Process_inicializar_1nativo(
JNIEnv *, jobject) {
long dir = (long) new variables();
return (dir);
}
JNIEXPORT void JNICALL Java_com_example_telo3_Process_procesar_1nativo(JNIEnv *,
jobject, jlong dir, jlong framedetect, jlong framedraw) {
Mat* telo =(Mat*)framedetect;
Mat* telo2= (Mat*)framedraw;
((variables*)dir)->almacena = ((variables*)dir)->face_detector.Detect(*telo);
//almacena = face_detector.Detect(frame_gray);
((variables*)dir)->draw.Dibujar(*telo2,((variables*)dir)->almacena);
//frame_capturado = draw.Dibujar(frame_capturado, almacena);
if( (((variables*)dir)->almacena.get_faces()).size() ==0){
LOGD("no detecto caras");
}
}
I think that I use the Jni correctly but the function Detect not works correctly because when I uses this if return 0.
Is framedetect 0? I made a test app based on this and it worked fine (that is, the jlong was converted to and from just fine, so that shouldn't be the issue).
Try catching the error with ndk-gdb to better understand the problem. Attaching it to the process might a problem though if it crashes straight away, in that case I like to put breakpoint on the java side before the crash, make the execution pause there using the debugger, attach ndk-gdb and continue let the java process continue.
Also I recommend using reinterpret_cast<jlong> and reinterpret_cast<variables*> instead of the C style casts, and save that cast to a separate variable to avoid casting all the time! cleaner code!

Categories

Resources