onFaceDetection(Camera.Face[] faces, Camera camera) keeps on executing continuously - android

I am creating an application capture image as it detect the face and I am able to achieve that, but only one issue the OnFaceDetection function of FaceDetectionListener is keep on executing even if there is no face in-front of camera. I am pasting my code.
mCamera.setFaceDetectionListener(new Camera.FaceDetectionListener() {
#Override
public void onFaceDetection(Camera.Face[] faces, Camera camera) {
try {
if (lastCaptureTiume + 10000 <= System.currentTimeMillis() || !faceCaptured) {
mCamera.takePicture(null, null, jpegCallback);
lastCaptureTiume = System.currentTimeMillis();
faceCaptured = true;
}
}
catch (Exception e) {
}
}
});
The issue is it is keep on takeing picture although there is no face in front of camera.

This behavior is different for different devices For my Note 3 onFaceDetection keeps on executing even without face and for nexus phone its performing perfectly.
Well I didn't got any other solution so I put a face check condition.
if (faces != null && faces.length > 0) {
//Do code here
}

Related

Tracking Android device in space using device camera

I am looking to get device position (x, y, and z) in space in the most efficient way possible. Currently I am using ArSceneView (ArCore) to get the cameras pose as it updates.
The problem is that ArSceneView or the class it extends from seems to have a memory leak that eventually crash my app. I have tried forcing garbage collection and increasing the heap size but the app is still crashing.
I do not need view to display the camera stream so a class with a view is not necessary, I just need a way to get the mobiles x y and z coordinates. Does anyone know of a way to get these using MLKit or pure ArCore (no view)?
Side note: my app does not crash when the android studio profiler is on... anyone know why?
WHERE I START AND STOP AR MODULE:
public void initializeSession() {
if (sessionInitializationFailed) {
return;
}
UnavailableException sessionException;
try {
session = new Session(context);
Config config = new Config(session);
config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
setupSession(session);
session.configure(config);
return;
} catch (Exception e) {
e.printStackTrace();
sessionException = new UnavailableException();
sessionException.initCause(e);
}
sessionInitializationFailed = true;
}
void start() {
System.gc();
if (isStarted) {
return;
}
isStarted = true;
try {
initializeSession();
this.resume();
} catch (CameraNotAvailableException ex) {
sessionInitializationFailed = true;
}
}
void stop() {
if (!isStarted) {
return;
}
isStarted = false;
this.pause();
this.stop();
System.gc();
}
WHERE I LISTEN FOR CHANGES:
public void onUpdate(FrameTime frameTime) {
if (arModule == null) {
return;
}
Frame frame = arModule.getArFrame();
if (frame == null) {
return;
}
Camera camera = frame.getCamera();
Pose pose = camera.getPose();
TrackingState trackingState = camera.getTrackingState();
if (trackingState == TrackingState.TRACKING) {
float x = pose.tx();
float y = pose.ty();
float z = pose.tz();
}
}
In the HelloAR sample app, you can clearly see that they are getting the pose of the camera. Their app does not crash, so it is not a bug. It's hard to tell from your code whether you are getting a memory leak somewhere else. Just add the bit about storing camera pose inside the HelloAR sample app.

Burst capture at 10 FPS with preview without lag

I need to do an application with an activity wich captures images in burst mode at 10 FPS.
My problem is that I'm able to capture very fast pictures with the burst mode, but it seems that my buffer of images is full before I can have the time to treat them (I just want to put my images into an ArrayList).
So my buffer is full and my app crashes.
The size of the buffer that I've choose is 50 (I cannot take too much memory).
It seems that my burst mode can take 30 FPS, but I'm able to treat my images at 10 FPS.
So, I want to slow down my capturing, but when I do that (by waiting before repeat another capture), it slows down my preview too. So I have a lag in my preview.
I don't want to save my images, I just want to stock them in order to treat them later (in an other activity).
Do you have any idea, maybe to slow down my capturing, or maybe to speed up my treatment.
Code ::
My code is based on the sample Camera2Basic.
private void captureStillPicture() {
try {
final Activity activity = getActivity();
if (null == activity || null == mCameraDevice) {
return;
}
mPreviewRequestBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_OFF);
mPreviewRequestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON);
mPreviewRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
mPreviewRequestBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, true);
mCaptureSession.stopRepeating();
mCaptureSession.abortCaptures();
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
mCaptureSession.capture(mPreviewRequestBuilder.build(), captureCallback, null);
mPreviewRequestBuilder.removeTarget(mImageReader.getSurface());
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
blockCapture() permits to wait 100 ms between captures.
private void blockCapture() {
mPreviewRequestBuilder.removeTarget(mImageReader.getSurface());
while(Math.abs(timerBurst - System.currentTimeMillis()) < 1000){}
System.out.println("ELAPSED :::::::: " + Math.abs(timerBurst - System.currentTimeMillis()));
timerBurst = System.currentTimeMillis();
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
for(int i =0; i< NB_BURST; i++){captureList.add(mPreviewRequestBuilder.build());}
}
private final CameraCaptureSession.CaptureCallback captureCallback
= new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session,
#NonNull CaptureRequest request,
#NonNull TotalCaptureResult result) {
showToast("Saved: " + mFile);
Log.d(TAG,"Saved: " + mFile);
mCounterImageForSave ++;
mCounterBurst++;
if(mCounterImageForSave <= 1) {
timerBurst = System.currentTimeMillis();
}
if(mCounterBurst >= NB_BURST && isPlayed) {
mCounterBurst = 0;
try {
blockCapture();
mCaptureSession.capture(mPreviewRequestBuilder.build(),captureCallback,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
if (mCounterBurst >= NB_BURST || !isPlayed)
unlockFocus();
}
};
I have tried to capture YUV_420_888 images instead of JPEG, but my images where all black, and I cannot convert them.
Sorry if I'd make mistakes with my english ...

Android Camera2, take picture continuously

I need to take pictures continuously with Camera2 API. It works fine on high end devices (for instance a Nexus 5X), but on slower ones (for instance a Samsung Galaxy A3), the preview freezes.
The code is a bit long, so I post only the most relevant parts:
Method called to start my preview:
private void startPreview() {
SurfaceTexture texture = mTextureView.getSurfaceTexture();
if(texture != null) {
try {
// We configure the size of default buffer to be the size of camera preview we want.
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
// This is the output Surface we need to start preview.
Surface surface = new Surface(texture);
// We set up a CaptureRequest.Builder with the output Surface.
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
// Here, we create a CameraCaptureSession for camera preview.
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
// If the camera is already closed, return:
if (mCameraDevice == null) { return; }
// When the session is ready, we start displaying the preview.
mCaptureSession = cameraCaptureSession;
// Auto focus should be continuous for camera preview.
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewRequest = mPreviewRequestBuilder.build();
// Start the preview
try { mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mPreviewBackgroundHandler); }
catch (CameraAccessException e) { e.printStackTrace(); }
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Log.e(TAG, "Configure failed");
}
}, null
);
}
catch (CameraAccessException e) { e.printStackTrace(); }
}
}
Method called to take a picture:
private void takePicture() {
try {
CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mImageReader.getSurface());
mCaptureSession.capture(captureBuilder.build(), null, mCaptureBackgroundHandler);
}
catch (CameraAccessException e) { e.printStackTrace(); }
}
And here is my ImageReader:
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(final ImageReader reader) {
mSaveBackgroundHandler.post(new Runnable() {
#Override
public void run() {
// Set the destination file:
File destination = new File(getExternalFilesDir(null), "image_" + mNumberOfImages + ".jpg");
mNumberOfImages++;
// Acquire the latest image:
Image image = reader.acquireLatestImage();
// Save the image:
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
FileOutputStream output = null;
try {
output = new FileOutputStream(destination);
output.write(bytes);
}
catch (IOException e) { e.printStackTrace(); }
finally {
image.close();
if (null != output) {
try { output.close(); }
catch (IOException e) { e.printStackTrace(); }
}
}
// Take a new picture if needed:
if(mIsTakingPictures) {
takePicture();
}
}
});
}
};
I have a button that toggle the mIsTakingPictures boolean, and makes the first takePicture call.
To recap, I'm using 3 threads:
one for the preview
one for the capture
one for the image saving
What can be the cause of this freeze?
It's impossible to avoid framing lost in your preview when you are taking images all time on weak devices. The only way to avoid this is on devices which support TEMPLATE_ZERO_SHUTTER_LAG and using a reprocessableCaptureSession. The documentation about this is pretty horrible and find a way to implement it can be a odyssey. I have this problem a few months ago and finally I found the way to implement it:
How to use a reprocessCaptureRequest with camera2 API
In that answer you can also find some Google CTS test's which also implements ReprocessableCaptureSession and shoot some burst captures with ZSL template.
Finally, you can also use a CaptureBuilder with your preview surface and the image reader surface attached, in that case your preview will continue working all time and also you will save each frame as a new picture. But you will still having the freeze problem.
I also tried implement a burst capture using a handler which dispatch a new capture call each 100 milliseconds, this second option was pretty good in performance and avoiding frame rate lost, but you will not get as many captures per second like the two ImageReader option.
Hope that my answer will help you a bit, API 2 still being a bit complex and there's not so many examples or information about it.
One thing I noticed on low end devices: the preview stops after a capture, even when using camera 1 api, so it has to be restarted manually, thus producing a small preview freeze when capturing a high resolution picture.
But the camera 2 api provides the possibility to get raw image when taking a still capture (that wasn't possible on the devices I have when using camera 1 (Huawei P7, Sony Xperia E5, wiko UFeel)). Using this feature is much faster than capturing a JPEG (maybe due to JPEG compression), so the preview can be restarted earlier, and the preview freeze is shorter. Of course using this solution you'll have to convert the picture from YUV to JPEG in a background task..

JavaCV Stream-Test code giving Error

I'm hoping someone might be able to tell me what I'm doing wrong here. I downloaded vanevery's GitHub project “JavaCV-0.5-Stream-Test" which is a couple of years old so I updated to the latest JavaCV version 0.11. But Android Studio is returning the error...
Error:
"record(org.bytedeco.javacpp.Frame) in FFmpegFrameRecorder cannot be
applied to (org.bytedeco.javacpp.opencv_core.lplimage)" for the line
of code which reads recorder.record(yuvIplimage), under
onPreviewFrame.
Here is my code:
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (yuvIplimage != null && recording) {
videoTimestamp = 1000 * (System.currentTimeMillis() - startTime);
// Put the camera preview frame right into the yuvIplimage object
yuvIplimage.getByteBuffer().put(data);
try {
// Get the correct time
recorder.setTimestamp(videoTimestamp);
// Record the image into FFmpegFrameRecorder
recorder.record(yuvIplimage);
} catch (FFmpegFrameRecorder.Exception e) {
Log.v(LOG_TAG,e.getMessage());
e.printStackTrace();
}
}
}

When Setting Flash Mode for Camera Paramters in zxing set Parameters failed exception in android

I am integrating barcode scanning functionality using zxing in android, my app includes turn on/off flash light functionality by button press.
When the flash button is pressed it sets the flash to mode torch and that parameter is set to be a camera parameter. I got an exception: Set Paramters failed exception.
Here is my code.
Parameters p = camera.getParameters();
List<String> supportedFlashModes =p.getSupportedFlashModes();
if (active)
{
if(supportedFlashModes!= null)
{
if(supportedFlashModes.contains(Parameters.FLASH_MODE_TORCH))
{
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
}
}
CaptureActivity.flashLightON=true;
}
else
{
p.setFlashMode(Parameters.FLASH_MODE_OFF);
}
camera.setParameters(p);
I got the following exception:
06-07 12:15:26.107: E/AndroidRuntime(24642): FATAL EXCEPTION: main
06-07 12:15:26.107: E/AndroidRuntime(24642): java.lang.RuntimeException:
setParameters failed
06-07 12:15:26.107: E/AndroidRuntime(24642): at
android.hardware.Camera.native_setParameters(Native Method)
Please advice me how to resolve this issue?
I had the same problem with my Google Nexus One.
The problem was solved for me by canceling autofocus, set parameters and then reset autofocus
camera.cancelAutoFocus();
camera.setParameters(parameters);
camera.autoFocus(autoFocusCallback);
Unfortunately its not an universal workaround since it does not work for S3 or Galaxy Nexus who totally loses it...
S-G starts to flashes and S3 stop autofocus.
I solved the issue for S3 by stoping preview and then restarting after the parameters were set
I had the same problem, turning the flaslight with the camera on causes some autofocus collision, when setting the parameters at the same time (especially when your autofocus interval is low).
Paste this right before enabling/disabling the flashlight, it will slow down the enabling event, but hey, no crash (not 100% crash proof though).
//sleep time should be long, 3000ms should be enough to prevent crash on some devices, 2000 may by to little (still crashes on Sony Xperia devices) - I have no idea wy this works that way :D
try {
Thread.currentThread().sleep(3000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
Edit:
Better way to solve this problem, is to put your setParameters method in a loop, and catch runtime exception everytime. Exit the loop when there is no exception, or when your (optional) loop counter reaches max value.
final int MAX_TRIES = 100;
boolean success = false;
int triesCounter = 0;
while (!success) {
try {
triesCounter++;
if (triesCounter > MAX_TRIES) {
success = true;
}
parameters = camera.getParameters();
if (parameters != null) {
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
}
success = true;
} catch (Exception exception) {
}
}
Some of the devices do not support and gives such problems. You can refer the link bellow, so that you can get a clear idea about it.
How to turn on camera flash light programmatically in Android?
One solution that works is to create a queue of camera parameters. Setting the torch would add a torch parameter to the queue.
Inside the onAutoFocus callback, call a function that iterates through all of the queue items and commits them. This way you are guaranteed that you are not autofocusing.
turning the flaslight with the camera on/trouch (FLASH_MODE_TORCH)
causes some autofocus collision, when setting the parameters at the
same time (especially when your autofocus interval is low).
I don't like the thread workaround. So I fixed it like this
...
private Boolean _flashOn = null;
...
private Runnable doAutoFocus = new Runnable() {
public void run() {
if (previewing) {
if (_flashOn != null) {
Parameters p = mCamera.getParameters();
if (_flashOn) {
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
}else{
p.setFlashMode(Parameters.FLASH_MODE_OFF);
}
mCamera.setParameters(p);
_flashOn = null;
}
mCamera.autoFocus(autoFocusCB);
}
}
};
No RuntimeException now.
But still has FLASH_MODE_TORCH + autoFocus bug on some adroid devices, e.g. Motorala Milestone/Samsun I9100G/Blahblah...
See also a declined issue for Android: https://code.google.com/p/android/issues/detail?id=14360
BTW. ZBar is faster than ZXing :)
I wanted to start the flash light at the start of scanning and solve it with this.
I have changed in com.google.zxing.client.android.camera method openDriver
Camera theCamera = camera;
if (theCamera == null) {
theCamera = Camera.open();
if (theCamera == null) {
throw new IOException();
}
final Parameters p = theCamera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
theCamera.setParameters(p);
camera = theCamera;
}
than I have removed from com.google.zxing.client.android.camera.CameraConfigurationManager
initializeTorch(parameters, prefs);
finaly I have changed AndroidManifest.xml
<uses-feature android:name="android.hardware.camera.flash" android:required="true"/>
Try out this code. It worked fine with me.
private void turnOnFlashLight(){
if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA))
{
//Check for Device Camera
Toast.makeText(this, getString(R.string.no_device_camera_msg), Toast.LENGTH_SHORT).show();
flashLightControl.setChecked(false);
return;
}else if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH))
{
//Check for Camera flash
Toast.makeText(this, getString(R.string.no_camera_flash), Toast.LENGTH_SHORT).show();
flashLightControl.setChecked(false);
return;
}else
{
//BIG ISSUE Fash mode is device specific
//Turn On Flash
String _model = android.os.Build.MODEL;
String _manufaturer = android.os.Build.MANUFACTURER;
if((_model.contains("GT-S5830") && _manufaturer.contains("samsung"))) //|| (_manufaturer.contains("lge")))
{
new Thread(new Runnable()
{
#Override
public void run()
{
// TODO Auto-generated method stub
Log.d(TAG, "From TimerTask..!!!");
cameraParams = CameraManager.camera.getParameters();
//cameraParams.setFlashMode(Parameters.FLASH_MODE_TORCH);
cameraParams.set("flash-mode", "on");
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
isFlash_On_Mode_Device = true;
isLightOn = true;
try{
Thread.sleep(2000);
Log.d(TAG, "From TimerTask After sleep!!!");
cameraParams = CameraManager.camera.getParameters();
cameraParams.setFlashMode(Parameters.FLASH_MODE_OFF);
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
isLightOn = true;
}
catch(Exception e){}
}
}).start();
}else if(_manufaturer.contains("lge"))
{
//Log.d(TAG, "From LG");
cameraParams = CameraManager.camera.getParameters();
cameraParams.setFlashMode(Parameters.FLASH_MODE_ON);
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
isLightOn = true;
}
else if(CameraManager.camera != null)
{
cameraParams = CameraManager.camera.getParameters();
//cameraParams.setFlashMode(Parameters.FLASH_MODE_TORCH);
cameraParams.set("flash-mode", "torch");
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
isLightOn = true;
}
}
private void turnOffFlashLight()
{
if (isLightOn)
{
if(CameraManager.camera != null)
{
if(isFlash_On_Mode_Device)
{
CameraManager.get().closeDriver();
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface)
{
initCamera(surfaceHolder);
if(CameraManager.camera != null)
CameraManager.camera.startPreview();
}
//Log.d(TAG, "Stopping camera..!!!");
}else
{
cameraParams = CameraManager.camera.getParameters();
cameraParams.setFlashMode(Parameters.FLASH_MODE_OFF);
CameraManager.camera.setParameters(cameraParams);
CameraManager.camera.startPreview();
}
isLightOn = false;
isFlash_On_Mode_Device = false;
}
}
}

Categories

Resources