C code not compiling correctly - android

I wrote a simple loop to aid in billboarding that will check if a pixel is white. if so, it will set it to 100% transparency. i wrote it in native code because the java equivalent of this loop took 19 seconds to run for a 256x256 bitmap, too slow.
when compiling:
#include "org_me_renderscene_Billboard.h"
#include <stdio.h>
#include <stdlib.h>
JNIEXPORT jintArray JNICALL Java_org_me_renderscene_Billboard_NativeSetAlphaWhereWhite
(JNIEnv *envptr, jclass jClass, jintArray pixels, jint length)
{
int *mPixels = (*int)malloc(length * 4);
static int currentcolor;
static int writecolor;
static int red, green, blue;
for(int x = 0; x < length; x++)
{
currentcolor = pixels[x];
red = currentcolor << 16;
green = currentcolor << 8;
blue = currentcolor;
if((red == 0) && (green == 0) && (blue == 0))
{
mPixels[x] = 0x00000000;
}
else
{
mPixels[x] = currentcolor;
}
}
return mPixels;
}
the auto-generated stub for which is:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_me_renderscene_Billboard */
#ifndef _Included_org_me_renderscene_Billboard
#define _Included_org_me_renderscene_Billboard
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_me_renderscene_Billboard
* Method: NativeSetAlphaWhereWhite
* Signature: ([II)[I
*/
JNIEXPORT jintArray JNICALL Java_org_me_renderscene_Billboard_NativeSetAlphaWhereWhite
(JNIEnv *, jclass, jintArray, jint);
#ifdef __cplusplus
}
#endif
#endif
i get these errors:
thomas#THOMASDESKLINUX:~/Documents/LinuxProgramming/EclipseWorkspace/RenderScene$ /home/thomas/Documents/LinuxProgramming/AndroidSDKs/android-ndk-r4b/ndk-build
Compile thumb : Billboardlib <= /home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c: In function 'Java_org_me_renderscene_Billboard_NativeSetAlphaWhereWhite':
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:9: error: expected expression before 'int'
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:9: error: expected ',' or ';' before 'malloc'
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:15: error: 'for' loop initial declarations are only allowed in C99 mode
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:15: note: use option -std=c99 or -std=gnu99 to compile your code
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:17: warning: dereferencing 'void *' pointer
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:17: error: void value not ignored as it ought to be
make: *** [/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/obj/local/armeabi/objs/Billboardlib/org_me_renderscene_Billboard.o] Error 1
why is this happening? my C code should be fine, and these errors dont make much sense.

Try (int*) instead of (*int)

what flags are you using in you Android.mk ?
did you set LOCAL_CFLAGS := -std=c99
also
you need to change to this
int *mPixels = (int*)malloc(length * 4);

int *mPixels = (*int)malloc(length * 4);
should be
int *mPixels = (int*)malloc(length * 4);
or even better
int *mPixels = (int*)malloc(length * sizeof(int));
and also note that this will not properly separate red, green, and blue:
red = currentcolor << 16;
green = currentcolor << 8;
blue = currentcolor;
Given that you're just checking for zero, and you don't really care about the individual RGB values, you can probably just get away with:
if ( (currentcolor & 0x00FFFFFF) == 0)
This will zero out the Alpha from the pixel, leaving behind just the RGB portion. If that whole thing is zero, each color must be zero, so there's no need to check each color individually.
Final thought:
I haven't done much with Android specifically, but isn't 0x000000 black and 0xFFFFFF white? So you're actually matching on black instead of white here.

Related

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

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().

Place image on rectangle after detection in OpenCV

I'm currently developing an android application where user can choose a shirt they want and it will be placed on top of their body with the use of the rear camera. The detection part is done and working and down below are the codes I've made so far.
nerds_thesis_clartips_OpencvClass.h //header file for nerds_thesis_clartips_OpencvClass.cpp
#include <jni.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
/* Header for class nerds_thesis_clartips_OpencvClass */
using namespace cv;
using namespace std;
#ifndef _Included_nerds_thesis_clartips_OpencvClass
#define _Included_nerds_thesis_clartips_OpencvClass
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nerds_thesis_clartips_OpencvClass
* Method: humanDetection
* Signature: (J)V
*/
void detectHuman(Mat& frame);
JNIEXPORT void JNICALL Java_nerds_thesis_clartips_OpencvClass_humanDetection
(JNIEnv *, jclass, jlong);
#ifdef __cplusplus
}
#endif
#endif
nerds_thesis_clartips_OpencvClass.cpp //C++ File
#include "nerds_thesis_clartips_OpencvClass.h"
JNIEXPORT void JNICALL Java_nerds_thesis_clartips_OpencvClass_humanDetection (JNIEnv *, jclass, jlong addrRgba){
Mat& frame = *(Mat*)addrRgba;
detectHuman(frame);
}
void detectHuman(Mat& frame){
// assign xml file to a variable
String human_cascade_name = "/storage/emulated/0/data/haarcascade_upperbody.xml";
CascadeClassifier human_cascade;
// load xml file
if(!human_cascade.load( human_cascade_name ) ) { printf("--(!)Error loading\n"); return; };
std::vector<Rect> humans;
Mat frame_gray;
Mat original;
frame.copyTo(original);
//convert input to grayscale
cvtColor( frame, frame_gray, CV_BGR2GRAY );
//increase image contrast
equalizeHist( frame_gray, frame_gray);
//Detect Human
human_cascade.detectMultiScale( frame_gray, humans, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(100, 100) );
//for (int i=0; i<humans.size(); i++)
//rectangle(frame, Point(humans[i].x, humans[i].y), Point(humans[i].x+humans[i].width, humans[i].y+humans[i].height), Scalar(0,255,0));
Mat imageMask = imread("C:/Users/Requinala/AndroidStudioProjects/CLARTIPS/app/src/main/res/drawable/bluevelvet.png", 1);
// Draw the mask over all rectangles
for (size_t i = 0; i < humans.size(); i++){
Rect r = humans[i];
Mat humanROI = frame_gray( humans[i] ); //image of the upper body
int h_temp = humans[i].height; // storing original height
int x = humans[i].x;
int y = humans[i].y - h_temp*(-0.6); // y is increased by 0.6*h
int w = humans[i].width;
int h = h_temp; // height detected
rectangle(frame,Point (x,y),Point(x + w,y +h),Scalar(255,0,255),1,4,0);
/*int xx =0, yy =0;
// Just iterate in face region pixel by pixel
for(int x = humans[i].x; x < humans[i].x+humans[i].width; x++){
for (int y = humans[i].y; y < humans[i].y+humans[i].height; y++){
//Copy Mask to Original image If the 0 chan
//Proper condition is over all color channels
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at(y,x)[0] = imageMask.at(xx,yy)[0];
humanROI.at(y,x)[1] = imageMask.at(xx,yy)[1];
humanROI.at(y,x)[2] = imageMask.at(xx,yy)[2];
//}
// Iterate in mask x
xx =xx+1;
}
// iterate next row of imageMask
xx = 0;
yy =yy+1;
}*/
}
}
However, I'm getting errors:
no matching member function for call to 'at'
What should I do? Any help/ideas will be appreciated.
By looking at your code:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at(y,x)[0] = imageMask.at(xx,yy)[0];
humanROI.at(y,x)[1] = imageMask.at(xx,yy)[1];
humanROI.at(y,x)[2] = imageMask.at(xx,yy)[2];
//}
it is easy to spot the problem. You are missing the template specification.
you can change it to the following:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at<uchar>(y,x)[0] = imageMask.at<uchar>(xx,yy)[0];
humanROI.at<uchar>(y,x)[1] = imageMask.at<uchar>(xx,yy)[1];
humanROI.at<uchar>(y,x)[2] = imageMask.at<uchar>(xx,yy)[2];
//}
or even better:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at<Vec3b>(y,x) = imageMask.at<Vec3b>(xx,yy);
//}
That should solve your compiling error, however the humanROI is in greyscale, you can do:
Mat humanColorROI;
cvtColor( humanROI, humanColorROI, CV_GRAY2BGR );
To get a 3 channel grey image. This way it should work.
P.S.: Regarding your stopping after detecting the body, it could be that it crashes or that you are just calling this function once? Is better to make another question for you to receive help from more members and for other members to find the answer quicker.

ndk-build guess wrong about "template" of qualifier in C++. It's just variable name in C

I get error like this when I do ndk-build:
/Users/../handle.c:80: error: 'struct _AR2Tracking2DParamT' has no member named 'template'
/Users/../handle.c:100: error: 'struct _AR2Tracking2DParamT' has no member named 'template'
I didn't know about "template", so searched about it on google. Finally, I know it's the qualifier of C++.
But handle.c is a C file. Why does ndk-build incorrectly guess that its a C++ file?
Is there any way to specify it is a C file in Android.mk?
thanks.
2013/11/22 edit:
Sorry I put another error code. Relevant error code is the following:
-- template.h --
int ar2FreeTemplate( AR2TemplateT *template );
-- ndk-build says --
/Users/.../template.h:63: error: expected ',' or '...' before 'template'
so ndk-build incorrectly guesses that template.h is C++ header file.
If it understands that it is a C header file, it should analyze template as a variable, not a keyword.
2013/11/25 edit:
here is template.h.
I replaced "template" to "temp". So i fixed this issue for the moment.
#ifndef AR2_TEMPLATE_H
#define AR2_TEMPLATE_H
#include <AR/ar.h>
#include <AR2/config.h>
#include <AR2/imageSet.h>
#include <AR2/featureSet.h>
#ifdef __cplusplus
extern "C" {
#endif
(An omission)
AR2TemplateT *ar2GenTemplate ( int ts1, int ts2 );
int ar2FreeTemplate( AR2TemplateT *temp );
int ar2SetTemplateSub ( ARParamLT *cparamLT, float trans[3][4], AR2ImageSetT *imageSet,
AR2FeaturePointsT *featurePoints, int num,
AR2TemplateT *temp );
int ar2GetBestMatching ( ARUint8 *img, ARUint8 *mfImage, int xsize, int ysize, int pixFormat,
AR2TemplateT *mtemp, int rx, int ry,
int search[3][2], int *bx, int *by, float *val);
int ar2GetBestMatching2(void);
int ar2GetResolution( ARParamLT *cparamLT, float trans[3][4], float pos[2], float dpi[2] );
int ar2GetResolution2( ARParam *cparam, float trans[3][4], float pos[2], float dpi[2] );
int ar2SelectTemplate( AR2TemplateCandidateT *candidate, AR2TemplateCandidateT *prevFeature, int num,
float pos[4][2], int xsize, int ysize );
#ifdef __cplusplus
}
#endif
#endif
Unfortunately, template is a reserved word in C++. Therefore, you cannot use this as identifier in C++ context, even in an h file included from C++, even if you wrap it with extren "C", as
extern "C" {
#include "template.h"
}
The best solution would be to change the name of parameter in template.h. If the file is carved in stone, here is a workaround:
extern "C" {
#define template notemplate
#include "template.h"
#undef template
}

Accessing to OpenCv cell values of Mat from native c++ function of android app

:)
I'm programming an algorithm for detect symmetric radial center of an image, to detect eyes position into face framePicture. I know that already exist a project of public domain that do this work, but i would base my work about another kind of studies.
This is the scenario:
Doing by hand this manipulation frame by frame, i have seen that writting code on java layer, like this:
private Mat mGray = new Mat(height,width,CvType.CV_8U);
private Mat mOut = new Mat(height,width,CvType.CV_8U);
private Mat mIntermediateMat = Mat.zeros(height,width,CvType.CV_32F);
[...common methods of opencv app...]
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
switch (ImageManipulationsActivity.viewMode) {
case ImageManipulationsActivity.VIEW_MODE_RGBA:
mOut = inputFrame.rgba();
break;
case ImageManipulationsActivity.VIEW_MODE_MODIFY:
mGray = inputFrame.gray();
int h = mGray.rows();
int w = mGray.cols();
int sobxVal,sobyVal;
/**
* Appling manually sobel filtering to calculate dx and dy image,
* moreover calculate magnitudo matrix and cosValue and sinValue
* matrices for computing, using lut techniques.
*/
for(int i = 1; i < h-1; i++)
for(int j = 1; j < w-1; j++) {
sobxVal = (int) (
((int)mGray.get(i-1,j)[0] << 1) +
mGray.get(i-1,j-1)[0] +
mGray.get(i-1,j+1)[0] - (
((int)mGray.get(i+1,j)[0] << 1) +
mGray.get(i+1,j-1)[0] +
mGray.get(i+1,j+1)[0] ) );
sobyVal = (int) (
((int)mGray.get(i,j-1)[0] << 1) +
mGray.get(i-1,j-1)[0] +
mGray.get(i+1,j-1)[0] - (
((int)mGray.get(i,j+1)[0] << 1) +
mGray.get(i-1,j+1)[0] +
mGray.get(i+1,j+1)[0] ) );
// compute magnitudo and atan2
}
// ...other calculations...
Core.convertScaleAbs(mIntermediateMat, mOut);
}
return mOut;
}
is not all efficient! So I decided to write c++ for a native function to manipulate matrix in this way:
Code by c++ side
#include <jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
#include <vector>
#include <android/log.h>
#define LOG_TAG "Example Filter"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define RADIUS 10
#define _K 9.9
#define _A 2 //radial strictness parameter, found experimentally
using namespace std;
using namespace cv;
extern "C" {
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(
JNIEnv* env,
jobject,
jlong addrGray,
jlong addrRgba,
jlong addrlutCosSin,
jlong addrlutM );
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(
JNIEnv* env,
jobject,
jlong addrGray,
jlong addrOut,
jlong addrlutCosSin,
jlong addrlutM )
{
Mat& mGr = *(Mat*)addrGray;
Mat& mOut = *(Mat*)addrOut;
Mat& lutCosSin = *(Mat*)addrlutCosSin;
Mat& lutM = *(Mat*)addrlutM;
int w = mGr.cols;
int h = mGr.rows;
double sobelxVal,sobelyVal,angle;
Mat magnitudo(h,w,CV_32F,Scalar(0));
Mat xMat(h,w,CV_8S,Scalar(0));
Mat yMat(h,w,CV_8S,Scalar(0));
Mat oMat(h,w,CV_32F,Scalar(0));
Mat mMat(h,w,CV_32F,Scalar(0));
/*
* Convolves Matrix with Sobel ky kernel and Sobel kx kernel
*ky = [ 1 2 1 ;
* 0 0 0 ;
* -1 -2 -1 ]
*
*kx = [ 1 0 -1 ;
* 2 0 -2 ;
* 1 0 -1 ]
*
* doing dedicated computation
*/
for( int i = 1; i < h-1; i++ )
{
for (int j = 1; j < w-1; j++ )
{
sobelxVal = (mGr.at<int>(i-1,j) << 1) +
mGr.at<int>(i-1,j-1) +
mGr.at<int>(i-1,j+1) - (
(mGr.at<int>(i+1,j) << 1) +
mGr.at<int>(i+1,j-1) +
mGr.at<int>(i+1,j+1) );
sobelyVal = (mGr.at<int>(i,j-1) << 1) +
mGr.at<int>(i-1,j-1) +
mGr.at<int>(i+1,j-1) - (
(mGr.at<int>(i,j+1) << 1) +
mGr.at<int>(i-1,j+1) +
mGr.at<int>(i+1,j+1) );
magnitudo.at<double>(i,j) = lutM.at<double>((int)sobelxVal+255/4,(int)sobelxVal+255/4);
angle = floor(atan2(sobelyVal,sobelxVal)*180/M_PI);
xMat.at<double>(i,j) = lutCosSin.at<double>(0,angle);
yMat.at<double>(i,j) = lutCosSin.at<double>(1,angle);
}
}
// other code calculation to determine mOut matrix values
}
}
By java code side
private Mat mRgba;
private Mat mGray;
/*
* Matrix of 360 cols and 2 rows
* row[0] cos values
* row[1] sin values
*/
private static Mat lutCosSin;
/*
* Matrix 510 x 510
* where lutM(i,j) = atan2(i,j)
*/
private static Mat lutMagnitudo
// common methods and declarations...
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
final int viewMode = mViewMode;
switch (viewMode) {
case VIEW_MODE_RGBA:
// input frame has RBGA format
mRgba = inputFrame.rgba();
break;
case VIEW_MODE_FEATURES:
// input frame has RGBA format
mGray = inputFrame.gray();
mRgba = Mat.zeros(mGray.rows(), mGray.cols(), mGray.type());
FindFeatures(
mGray.getNativeObjAddr(),
mRgba.getNativeObjAddr(),
lutCosSin.getNativeObjAddr(),
lutMagnitudo.getNativeObjAddr()
);
//Core.convertScaleAbs(mRgba, mRgba);
// Log.d(TAG, "Called native function :"+mRgba.submat(new Range(0,5), new Range(0,5)).toString()+
// "\nAngles matrix:"+mGray);
break;
}
return mRgba;
}
public native void FindFeatures(long matAddrGr, long matAddrRgba, long matAddrlutCS, long matAddrlutM);
the first important issue of this snipped code is that on accessing to mGr cells with "at" method in this way:
mGr.at<int>(i,j)
previus check that mGr type is int, the returned values isn't the effective gray level pixel of gray frame (i saw it by log).
I suppose that there are linkin bug of matrix from java code to c++ code, but i'm not sure for this.
I hope may anyone help me to solve this issue XD !!

How can I display results of a timer with a putText in C++ OpenCV?

How can I display results od a timer with a putText in my OpenCV Android app? The is detecting features on the view from a camera and the main algorithm and the timer is written in C++. The full code of my C++ JNI file:
#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_tutorial3_Sample3View_FindFeatures(JNIEnv* env, jobject, jint
width, jint height, jbyteArray yuv, jintArray bgra)
{
jbyte* _yuv = env->GetByteArrayElements(yuv, 0);
jint* _bgra = env->GetIntArrayElements(bgra, 0);
Mat myuv(height + height/2, width, CV_8UC1, (unsigned char *)_yuv);
Mat mbgra(height, width, CV_8UC4, (unsigned char *)_bgra);
Mat mgray(height, width, CV_8UC1, (unsigned char *)_yuv);
//Please make attention about BGRA byte order
//ARGB stored in java as int array becomes BGRA at native level
cvtColor(myuv, mbgra, CV_YUV420sp2BGR, 4);
vector<KeyPoint> v;
OrbFeatureDetector detector(1);
double t = (double)getTickCount();
detector.detect(mgray, v);
t = ((double)getTickCount() - t)/getTickFrequency();
putText(mbgra, t+" detection time", Point2f(100,100), FONT_HERSHEY_PLAIN, 2, Scalar(0,0,255,255), 2);
for( size_t i = 0; i < v.size(); i++ )
circle(mbgra, Point(v[i].pt.x, v[i].pt.y), 10, Scalar(0,0,255,255));
env->ReleaseIntArrayElements(bgra, _bgra, 0);
env->ReleaseByteArrayElements(yuv, _yuv, 0); }}
The problem is in the line with putText: I get an error "invalid operands of types 'double' and 'char const [15]' to binary 'operator+'". Is my timer OK? How else can I display the results of it? I will be grateful for your help.
't' is of class double and the constant " detection time" is treated as a string. String + double is something that the compiler doesn't understand, which is why it pukes on you.
Instead, try this approach:
std::stringstream s;
s << t;
s << " detection time";
putText(mbgra, s.str(), Point2f(100,100), FONT_HERSHEY_PLAIN, 2, Scalar(0,0,255,255), 2);
In the above code, the stringstream class has all the overloads built in to the "<<" operator such that it knows what to do with doubles and integers and strings and how to mash them together. With a little more research in to the various attributes, you can get it to format the precision of decimel points and such.

Categories

Resources