I want create an element of a own c++ class.
My JNI function:
JNIEXPORT void JNICALL Java_com_example_telo3_Process_inicializar_1nativo
(JNIEnv *, jobject){
Almacena almacena;
}
And Almacena is a c++ class:
#pragma once
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
class Almacena
{
private:
std::vector<Rect> myfaces;
std::vector<Rect> myeyes_r;
std::vector<Rect> myeyes_l;
std::vector<Rect> mynoses;
std::vector<Rect> mymouths;
Point2f P0;
Point2f P1;
Point2f P2;
Point2f P3;
public:
Almacena(void);
~Almacena(void);
void set_faces(std::vector<Rect> faces);
void set_eyes_r(std::vector<Rect> eyes_r);
void set_eyes_l(std::vector<Rect> eyes_l);
void set_noses(std::vector<Rect> noses);
void set_mouths(std::vector<Rect> mouths);
void set_P0(Point2f aux);
void set_P1(Point2f aux1);
void set_P2(Point2f aux2);
void set_P3(Point2f aux3);
std::vector<Rect> get_faces();
std::vector<Rect> get_eyes_r();
std::vector<Rect> get_eyes_l();
std::vector<Rect> get_noses();
std::vector<Rect> get_mouths();
Point2f get_P0();
Point2f get_P1();
Point2f get_P2();
Point2f get_P3();
};
How Can I do? Because if I do like in my code, appears these errors:
undefined reference to 'Almacena::~Almacena()' telo3 line 41, external location: C:\Users\telo\Desktop\ANDROID\android-ndk-r8d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\arm-linux-androideabi\bin\ld.exe: .\obj\local\armeabi\objs\nativo\nativo.o: in function Java_com_example_telo3_Process_inicializar_1nativo:jni\nativo.cpp C/C++ Problem
undefined reference to 'Almacena::Almacena()' telo3 line 41, external location: C:\Users\telo\Desktop\ANDROID\android-ndk-r8d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\arm-linux-androideabi\bin\ld.exe: .\obj\local\armeabi\objs\nativo\nativo.o: in function Java_com_example_telo3_Process_inicializar_1nativo:jni\nativo.cpp C/C++ Problem
In your Android.mk you should have
LOCAL_SRC_FILES := nativo.cpp \
Almacena.cpp \
... all other cpp files
Related
Project is a realtime image processer same as my Project but it uses two values which are input and output(I remember that these projects are using frame for processing like that).
I changed its native-lib.cpp file this
#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);
}
}
to this
#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);
}
}
}
}
But in my phone there was a black screen for probably five seconds and app stopping repeatedly.
Note: Sync and build were successfully and before I changed cpp file app was working successfully
Please help me about my Project.
Thanks
Here you made some changes to the definition of the C++ method Java_com_example_nativeopencvandroidtemplate_MainActivity_adaptiveThresholdFromJNI, you will therefore have to reflect these changes on the Kotlin side, as this method is called from your MainActivity.kt using JNI. Here is the code you'll have to adapt in 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)
...
}
Here adaptiveThresholdFromJNI was adapted to handle only one argument (as you did with the C++ equivalent) and that one argument is then returned from onCameraFrame to be displayed on the screen.
I see in your C++ code that the first thing you try to do is to convert your input Mat to gray, but this is not necessary because the Mat passed to your C++ code is already gray (see val mat = inputFrame.gray()).
If you want to keep your C++ code intact, you can also pass the colorized version of the camera view frame to your C++ code by using val mat = inputFrame.rgba().
I'm actually developing a C app on Android Studio using the SDL 2, a C graphic library. But the problem doesn't come from the library itself but from the #include of my own files.
I created source files in which I put my functions, I associated to them header files with the declarations of the functions. But when I call the functions in my main source file, I get the error:
error: undefined reference to 'draw_render_rectangle' for example.
It doesn't work for any of my files or functions. But it works for the SDL.
So I try to #include.
Main source file "main_graphics.c":
#include "main_graphics.h"
void disp_main_menu(int selected) {
POINT A, B;
A.x = 0;
A.y = 0;
B.x = WIDTH;
B.y = HEIGHT;
draw_render_rectangle(A, B, 70, 70, 70);
}
Main header file "main_graphics.h":
#ifndef ANDROID_GAME_MAIN_GRAPHICS_H
#define ANDROID_GAME_MAIN_GRAPHICS_H
#include "../SDL2/include/SDL.h"
#include "../SDL2/include/SDL.h"
#include "../SDL2_ttf/SDL_ttf.h"
#include "../SDL2_image/SDL_image.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "graphics_mobile.h"
int WIDTH = 1080;
int HEIGHT = 1920;
void disp_main_menu(int selected);
#endif //ANDROID_GAME_MAIN_GRAPHICS_H
"graphics_mobile.c" :
#include "graphics_mobile.h"
typedef struct point {int x,y;} POINT;
void draw_render_rectangle(POINT p1, POINT p2, Uint8 r, Uint8 g, Uint8 b)
{
SDL_Rect rectangle;
int xmin, xmax;
int ymin, ymax;
int i,j;
if (p1.x < p2.x) {xmin=p1.x; xmax=p2.x;} else{xmin=p2.x; xmax=p1.x;}
if (p1.y < p2.y) {ymin=p1.y; ymax=p2.y;} else{ymin=p2.y; ymax=p1.y;}
rectangle.x = xmin;
rectangle.y = HEIGHT - (ymax-ymin) - ymin;
rectangle.w = xmax-xmin;
rectangle.h = ymax-ymin;
SDL_SetRenderTarget(renderer, texture);
SDL_RenderDrawRect(renderer,&rectangle);
SDL_SetRenderDrawColor(renderer, r, g, b, 0x00);
SDL_RenderFillRect(renderer, &rectangle);
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, texture, NULL, NULL);
}
"graphics_mobile.h"
#ifndef ANDROID_GAME_GRAPHICS_MOBILE_H
#define ANDROID_GAME_GRAPHICS_MOBILE_H
#include "main_graphics.h"
typedef struct point {int x,y;} POINT;
void draw_render_rectangle(POINT p1, POINT p2, Uint8 r, Uint8 g, Uint8 b);
#endif //ANDROID_GAME_GRAPHICS_MOBILE_H
One thing that is weird is that the autocompletion is working, when I type the function, it actually recognize it and tells me in the little window of the autocompletion that it is defined in "graphics_mobile.h".
Can the problem come from the compilator?
I tried ndk-bundle_10e and ndk-bundle_16b and I get the same error.
So I did some tests and I got a working code :
you have to put in "graphics_mobile.h":
#ifndef ANDROID_GAME_GRAPHICS_MOBILE_H
#define ANDROID_GAME_GRAPHICS_MOBILE_H
#include "main_graphics.h"
#include "graphics_mobile.c"
#endif //ANDROID_GAME_GRAPHICS_MOBILE_H
and remove the declarations of the functions
I have a C++ source file, and I want to call a method from my C++ file, but I dont know whats wrong.
Here is my cpp method:
static unsigned ALawEncode(uint8_t* dst, int16_t* src, size_t srcSize);
Here is where I would like to call my method:
#include <string.h>
#include <jni.h>
#include <stdint.h>
#include "G711.h"
extern "C" {
uint8_t* Java_com_example_qonclient_Codecs_encodeG711( JNIEnv* env, jobject thiz, int16_t* source ){
size_t size0 = sizeof(source);
G711 g711;
uint8_t *dst;
g711.ALawEncode(dst, source, size0);
return dst;
}
}
Could you help me?
I am studying OpenCV4Android SDK, in the 2.4.5 version, with the NDK framework, using which I can use native code (written in C/C++) in the Android environment. But I don't exactly understand how parameters are passed from Android to C.
For example, in the 'mixedprocessing' sample, in the directory 'jni' there's a .cpp file named 'jni_part', whose code is:
#include <jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <vector>
using namespace std;
using namespace cv;
extern "C" {
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba) {
Mat& mGr = *(Mat*)addrGray;
Mat& mRgb = *(Mat*)addrRgba;
vector<KeyPoint> v;
FastFeatureDetector detector(50);
detector.detect(mGr, v);
for( unsigned int i = 0; i < v.size(); i++ ) {
const KeyPoint& kp = v[i];
circle(mRgb, Point(kp.pt.x, kp.pt.y), 10, Scalar(255,0,0,255));
}
}
}
In the MainActivity there's the method:
public native void FindFeatures(long matAddrGr, long matAddrRgba);
So it's passed as parameter the native address of a Mat object, but how does it become a matrix in C?
And which features are detected from a FastFeatureDetector object?
FindFeatures, in Java, calls its exact equivalent in C/C++:
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba){
Mat& mGr = *(Mat*)addrGray;
Mat& mRgb = *(Mat*)addrRgba;
...
This is where it becomes a cv::Mat. (Mat*) casts what is pointed by address addrGray (respectively addrRgba) to a "pointer to a cv::Mat". Then, the value pointed by this newly created pointer is put in mGr (respectively mRgb), which is a cv::Mat.
In other words, you only give to C/C++ an address in the memory, and you have to make sure that what's there actually is a valid cv::Mat.
About your second question, the FAST detector detects points of interest in the image (i.e. points that contain a lot of information). The idea is to be able to identify those points on multiple different images. To simplify, you can consider a feature detected by FAST as a corner in the image.
I was tring to use ORB feature in Android apps,and create a project.When I use BruteForceMatcher and write the code:dist=matches[i].distance, My IDE notice me that "Field 'distance' could not be resolved". Why this happened?
#include <jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/legacy/legacy.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
extern "C" {
JNIEXPORT int JNICALL Java_org_opencv_samples_tutorial2_Tuturial2Activity_CompareFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);
JNIEXPORT int JNICALL Java_org_opencv_samples_tutorial2_Tuturial2Activity_CompareFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
char img_filename1[]="/sdcard/src.jpg";
char img_filename2[]="/sdcard/demo.jpg";
Mat src1,src2;
src1=imread(img_filename1,CV_LOAD_IMAGE_GRAYSCALE);
src2=imread(img_filename2,CV_LOAD_IMAGE_GRAYSCALE);
ORB orb;
vector<KeyPoint> keys1,keys2;
Mat descriptors1,descriptors2;
orb(src1,Mat(),keys1,descriptors1);
orb(src2,Mat(),keys2,descriptors2);
BruteForceMatcher<HammingLUT> matcher;
vector<DMatch> matches;
matcher.match(descriptors1,descriptors2,matches);
double max_dist=0; double min_dist=255;
//--Quick calculation of max and min distances between keypoints
for (int i=0;i<descriptors1.rows;i++)
{
double dist=matches[i].distance;
}
return 0;
}
}
Goto Project Properties -> C/C++ General -> GNU C++ ->
Edit change 4.x to 4.4.3 in ${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.x....