Skip to content

Commit 2191f3b

Browse files
committed
send bitmap to native
1 parent 17566d2 commit 2191f3b

File tree

6 files changed

+196
-101
lines changed

6 files changed

+196
-101
lines changed

visionSamples/FaceTracker/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ find_library( # Sets the name of the path variable.
4040
target_link_libraries( # Specifies the target library.
4141
native-lib
4242

43+
-ljnigraphics
44+
4345
# Links the target library to the log library
4446
# included in the NDK.
4547
${log-lib} )
Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
#include <jni.h>
22
#include <string>
33
#include <android/log.h>
4+
#include <android/bitmap.h>
45

56
using namespace std;
6-
#define AppTag "Native"
77

8-
extern "C"
9-
JNIEXPORT void JNICALL
10-
Java_com_google_android_gms_samples_vision_face_facetracker_FaceGraphic_test(JNIEnv *env,
11-
jobject instance) {
8+
#define LOG_TAG "Native"
9+
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
10+
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
1211

13-
__android_log_print(ANDROID_LOG_DEBUG, AppTag, "Load resources started test1" );
12+
extern "C"
13+
JNIEXPORT jstring JNICALL
14+
Java_com_google_android_gms_samples_vision_face_facetracker_CustomDetector_test(JNIEnv *env,
15+
jobject instance,
16+
jobject bmp) {
17+
AndroidBitmapInfo infocolor;
18+
int ret;
19+
if ((ret = AndroidBitmap_getInfo(env, bmp, &infocolor)) < 0) {
20+
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
21+
return env->NewStringUTF("Image broken");
22+
}
23+
LOGI("color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",
24+
infocolor.width,infocolor.height,infocolor.stride,infocolor.format,infocolor.flags);
1425

26+
if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
27+
LOGE("Bitmap format is not RGBA_8888 !");
28+
return env->NewStringUTF("Image broken 2");
29+
}
30+
const char *returnValue = "test";
31+
return env->NewStringUTF(returnValue);
1532
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package com.google.android.gms.samples.vision.face.facetracker;
22

33
import android.graphics.Bitmap;
4+
import android.graphics.BitmapFactory;
5+
import android.graphics.ImageFormat;
6+
import android.graphics.Rect;
7+
import android.graphics.YuvImage;
48
import android.os.Environment;
59
import android.util.Log;
610
import android.util.SparseArray;
@@ -9,46 +13,77 @@
913
import com.google.android.gms.vision.Frame;
1014
import com.google.android.gms.vision.face.Face;
1115

16+
import java.io.ByteArrayOutputStream;
17+
import java.io.File;
1218
import java.io.FileOutputStream;
13-
import java.io.IOException;
14-
import java.util.Map;
19+
20+
interface RecognitionInterface
21+
{
22+
void onRecognized(String obj);
23+
}
1524

1625
public class CustomDetector extends Detector<Face> {
1726
private static final String TAG = "CustomDetector";
1827
private Detector<Face> mDelegate;
19-
private Map<Face, String> mFaceNameMap;
28+
public RecognitionInterface recognitionHandler;
29+
public Frame mFrame;
30+
public Bitmap tmpBitmap;
31+
private volatile boolean IsFirst;
32+
33+
public Face faceToRegognize;
34+
public boolean IsBusy;
35+
private Thread mT;
36+
37+
private int faceid;
38+
private int x, y, w, h;
2039

21-
CustomDetector(Detector<Face> delegate, Map<Face, String> faceNameMap) {
40+
CustomDetector(Detector<Face> delegate)
41+
{
2242
mDelegate = delegate;
23-
mFaceNameMap = faceNameMap;
43+
IsFirst = true;
44+
}
45+
46+
void startRecognition(int faceId, int _x, int _y, int _w, int _h)
47+
{
48+
IsBusy = true;
49+
faceid = faceId;
50+
x = _x;
51+
y = _y;
52+
w = _w;
53+
h = _h;
54+
}
55+
56+
public void setHandlerListener(RecognitionInterface listener)
57+
{
58+
recognitionHandler = listener;
2459
}
60+
2561
//@Override
2662
public SparseArray<Face> detect(Frame frame) {
27-
Log.i(TAG, "CustomDetector detect");
28-
SparseArray<Face> faces = mDelegate.detect(frame);
29-
// Bitmap bmp = frame.getBitmap();
30-
//
31-
// FileOutputStream out = null;
32-
// try {
33-
// String path = Environment.getExternalStorageDirectory().toString();
34-
// out = new FileOutputStream(path +"SDCARD name + increment");
35-
// bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
36-
// } catch (Exception e) {
37-
// e.printStackTrace();
38-
// } finally {
39-
// try {
40-
// if (out != null) {
41-
// out.close();
42-
// }
43-
// } catch (IOException e) {
44-
// e.printStackTrace();
45-
// }
46-
// }
47-
48-
for(int i = 0; i < faces.size(); i++) {
49-
Face f = faces.valueAt(i);
50-
mFaceNameMap.put(f, "put cropped bitmap here");
63+
mFrame = frame;
64+
if (IsBusy) {
65+
if (recognitionHandler != null) {
66+
YuvImage yuvImage = new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, frame.getMetadata().getWidth(), frame.getMetadata().getHeight(), null);
67+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
68+
yuvImage.compressToJpeg(new Rect(0, 0, frame.getMetadata().getWidth(), frame.getMetadata().getHeight()), 100, byteArrayOutputStream);
69+
byte[] jpegArray = byteArrayOutputStream.toByteArray();
70+
Bitmap tmpBitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);
71+
final Bitmap cropped = Bitmap.createBitmap(tmpBitmap, x, y, w, h);
72+
73+
mT = new Thread(new Runnable() {
74+
@Override
75+
public void run() {
76+
String res = test(cropped);
77+
recognitionHandler.onRecognized(res);
78+
setHandlerListener(null);
79+
IsBusy = false; //todo: stop reset
80+
}
81+
});
82+
mT.start();
83+
}
5184
}
85+
86+
SparseArray<Face> faces = mDelegate.detect(frame);
5287
return faces;
5388
}
5489

@@ -59,4 +94,7 @@ public boolean isOperational() {
5994
public boolean setFocus(int id) {
6095
return mDelegate.setFocus(id);
6196
}
97+
98+
99+
public native String test(Bitmap bmp);
62100
}

visionSamples/FaceTracker/app/src/main/java/com/google/android/gms/samples/vision/face/facetracker/FaceGraphic.java

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,55 +15,66 @@
1515
*/
1616
package com.google.android.gms.samples.vision.face.facetracker;
1717

18+
import android.graphics.Bitmap;
1819
import android.graphics.Canvas;
1920
import android.graphics.Color;
2021
import android.graphics.Paint;
22+
import android.os.Environment;
2123
import android.util.Log;
2224
import android.util.SparseArray;
2325

2426
import com.google.android.gms.samples.vision.face.facetracker.ui.camera.GraphicOverlay;
2527
import com.google.android.gms.vision.Detector;
2628
import com.google.android.gms.vision.face.Face;
29+
import com.google.android.gms.vision.Frame;
2730

31+
import java.io.ByteArrayOutputStream;
32+
import java.io.File;
33+
import java.io.FileOutputStream;
34+
import java.io.OutputStreamWriter;
2835
import java.util.Map;
2936

3037
/**
3138
* Graphic instance for rendering face position, orientation, and landmarks within an associated
3239
* graphic overlay view.
3340
*/
34-
class FaceGraphic extends GraphicOverlay.Graphic {
41+
class FaceGraphic extends GraphicOverlay.Graphic implements RecognitionInterface {
3542
private static final String TAG = "FaceGraphic";
43+
3644
private static final float FACE_POSITION_RADIUS = 10.0f;
3745
private static final float ID_TEXT_SIZE = 40.0f;
3846
private static final float ID_Y_OFFSET = 50.0f;
3947
private static final float ID_X_OFFSET = -50.0f;
4048
private static final float BOX_STROKE_WIDTH = 5.0f;
4149

4250
private static final int COLOR_CHOICES[] = {
43-
Color.BLUE,
44-
Color.CYAN,
45-
Color.GREEN,
46-
Color.MAGENTA,
47-
Color.RED,
48-
Color.WHITE,
49-
Color.YELLOW
51+
Color.BLUE,
52+
Color.CYAN,
53+
Color.GREEN,
54+
Color.MAGENTA,
55+
Color.RED,
56+
Color.WHITE,
57+
Color.YELLOW
5058
};
5159
private static int mCurrentColorIndex = 0;
5260

5361
private Paint mFacePositionPaint;
5462
private Paint mIdPaint;
5563
private Paint mBoxPaint;
5664

57-
private volatile Face mFace;
65+
public volatile Face mFace;
5866
private int mFaceId;
5967
private float mFaceHappiness;
6068

69+
public int frame_cx = 5; //start after 5 frames
6170

6271
private Thread mT;
72+
private CustomDetector mCustomDetector;
73+
private boolean IsRecognized;
6374

64-
FaceGraphic(GraphicOverlay overlay) {
75+
FaceGraphic(GraphicOverlay overlay, CustomDetector customDetector) {
6576
super(overlay);
66-
77+
mCustomDetector = customDetector;
6778
mCurrentColorIndex = (mCurrentColorIndex + 1) % COLOR_CHOICES.length;
6879
final int selectedColor = COLOR_CHOICES[mCurrentColorIndex];
6980

@@ -84,42 +95,6 @@ void setId(int id) {
8495
mFaceId = id;
8596
}
8697

87-
public void startRecognition(Face item, Map<Face, String> mFaceNameMap)
88-
{
89-
Log.i(TAG, String.format("hashmap: %d" , mFaceNameMap.size()));
90-
// test();
91-
// mT = new Thread(new Runnable() {
92-
// @Override
93-
// public void run() {
94-
// Log.i(TAG, "startRecognition: ");
95-
//
96-
// try {
97-
// Thread.sleep(5000);
98-
// mFaceId = 777;
99-
// } catch (InterruptedException e) {
100-
// e.printStackTrace();
101-
// }
102-
// //mFace
103-
// }
104-
// });
105-
// mT.start();
106-
}
107-
108-
public void stopRecognition(Detector.Detections<Face> detectionResults, Map<Face, String> mFaceNameMap)
109-
{
110-
Log.i(TAG, "stopRecognition: ");
111-
// if (mT.isAlive())
112-
// {
113-
// mT.stop();
114-
// }
115-
//mFaceNameMap.remove(fa)
116-
SparseArray<Face> faces = detectionResults.getDetectedItems();
117-
for(int i = 0; i < faces.size(); i++) {
118-
Face f = faces.valueAt(i);
119-
mFaceNameMap.remove(f);
120-
}
121-
}
122-
12398

12499
/**
125100
* Updates the face instance from the detection of the most recent frame. Invalidates the
@@ -128,6 +103,20 @@ public void stopRecognition(Detector.Detections<Face> detectionResults, Map<Face
128103
void updateFace(Face face) {
129104
mFace = face;
130105
postInvalidate();
106+
107+
if (frame_cx > 0) {
108+
frame_cx--;
109+
} else {
110+
if (!IsRecognized && mCustomDetector.recognitionHandler == null) { //one face at time
111+
mCustomDetector.setHandlerListener(this);
112+
113+
int x = (int)face.getPosition().x;
114+
int y = (int)face.getPosition().y;
115+
int w = (int)face.getWidth();
116+
int h = (int)face.getHeight();
117+
mCustomDetector.startRecognition(mFaceId, x, y, w, h);
118+
}
119+
}
131120
}
132121

133122
/**
@@ -140,14 +129,18 @@ public void draw(Canvas canvas) {
140129
return;
141130
}
142131

132+
//Log.e(TAG, "canvas.getHeight() " + canvas.getHeight()); //1440
133+
//Log.e(TAG, "canvas.getWidth() " + canvas.getWidth()); //1080
134+
// 960 720
135+
143136
// Draws a circle at the position of the detected face, with the face's track id below.
144137
float x = translateX(face.getPosition().x + face.getWidth() / 2);
145138
float y = translateY(face.getPosition().y + face.getHeight() / 2);
146139
canvas.drawCircle(x, y, FACE_POSITION_RADIUS, mFacePositionPaint);
147140
canvas.drawText("id: " + mFaceId, x + ID_X_OFFSET, y + ID_Y_OFFSET, mIdPaint);
148-
canvas.drawText("happiness: " + String.format("%.2f", face.getIsSmilingProbability()), x - ID_X_OFFSET, y - ID_Y_OFFSET, mIdPaint);
149-
canvas.drawText("right eye: " + String.format("%.2f", face.getIsRightEyeOpenProbability()), x + ID_X_OFFSET * 2, y + ID_Y_OFFSET * 2, mIdPaint);
150-
canvas.drawText("left eye: " + String.format("%.2f", face.getIsLeftEyeOpenProbability()), x - ID_X_OFFSET*2, y - ID_Y_OFFSET*2, mIdPaint);
141+
//canvas.drawText("happiness: " + String.format("%.2f", face.getIsSmilingProbability()), x - ID_X_OFFSET, y - ID_Y_OFFSET, mIdPaint);
142+
//canvas.drawText("right eye: " + String.format("%.2f", face.getIsRightEyeOpenProbability()), x + ID_X_OFFSET * 2, y + ID_Y_OFFSET * 2, mIdPaint);
143+
//canvas.drawText("left eye: " + String.format("%.2f", face.getIsLeftEyeOpenProbability()), x - ID_X_OFFSET*2, y - ID_Y_OFFSET*2, mIdPaint);
151144

152145
// Draws a bounding box around the face.
153146
float xOffset = scaleX(face.getWidth() / 2.0f);
@@ -160,4 +153,11 @@ public void draw(Canvas canvas) {
160153
}
161154

162155
public native void test();
156+
157+
@Override
158+
public void onRecognized(String str) {
159+
Log.w(TAG, "RRRRRRRRRRRRecognized");
160+
Log.w(TAG, str);
161+
IsRecognized = true;
162+
}
163163
}

0 commit comments

Comments
 (0)