Using Camera LED Flash with OpenCV on Android - java

I have an application using OpenCV for Android and was wondering if it was possible to enable the camera's LED.
Currently my camera is set up using the following code:
camera = new VideoCapture(Highgui.CV_CAP_ANDROID);
All examples I've seen which enable the LED Flash require Camera.Parameters which I don't have access to with this camera setup.
Is there any simple way to enable the LED without switching to using the basic Camera class for my videostream, as this tends to be much slower.
Thanks for any help in advance.

In OpenCV for Android 2.4, you can do this,
mCamera.set(
Highgui.CV_CAP_PROP_ANDROID_FLASH_MODE,
Highgui.CV_CAP_ANDROID_FLASH_MODE_ON
);
Other options are: CV_CAP_ANDROID_FLASH_MODE_AUTO, CV_CAP_ANDROID_FLASH_MODE_OFF, CV_CAP_ANDROID_FLASH_MODE_TORCH andCV_CAP_ANDROID_FLASH_MODE_REDEYE.
However, using this causes the application to automatically close on my tablet (Asus TF101). Hopefully it works on others.

You can use extends JavaCameraView
public class Tutorial2View extends JavaCameraView{
private static final String TAG = "Sample::Tutorial2View";
private Context myreference;
private static boolean isFlashLightON = false;
public Tutorial2View(Context context, AttributeSet attrs) {
super(context, attrs);
this.myreference = context;
}
public List<String> getEffectList() {
return mCamera.getParameters().getSupportedColorEffects();
}
public boolean isEffectSupported() {
return (mCamera.getParameters().getColorEffect() != null);
}
public String getEffect() {
return mCamera.getParameters().getColorEffect();
}
public void setEffect(String effect) {
Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(effect);
mCamera.setParameters(params);
}
public List<Size> getResolutionList() {
return mCamera.getParameters().getSupportedPreviewSizes();
}
public void setResolution(Size resolution) {
disconnectCamera();
mMaxHeight = resolution.height;
mMaxWidth = resolution.width;
connectCamera(getWidth(), getHeight());
}
public Size getResolution() {
return mCamera.getParameters().getPreviewSize();
}
// Setup the camera
public void setupCameraFlashLight() {
Camera camera = mCamera;
if (camera != null) {
Parameters params = camera.getParameters();
if (params != null) {
if (isFlashLightON) {
isFlashLightON = false;
params.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.startPreview();
} else {
isFlashLightON = true;
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
}
}
}
}
}
Call setupCameraFlashLight(); to ON OFF the LED light

It seems there is no easy way to do this. The only option is to use the default Android Camera class and take the slight performance hit.

If you use JavaCameraView you can simply add on the end two methods to your JavaCameraView.java class:
public void turnOffTheFlash() {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(params.FLASH_MODE_OFF);
mCamera.setParameters(params);
}
public void turnOnTheFlash() {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(params.FLASH_MODE_TORCH);
mCamera.setParameters(params);
}
You can run them in your activity as follow:
private JavaCameraView javaCameraView;
javaCameraView.turnOnTheFlash();
javaCameraView.turnOffTheFlash();
Mayby you should use FLASH_MODE_ON rather than FLASH_MODE_TORCH.
It works for my on OpenCV 2.4.9.

Related

How to lock focus on Camera2API app on a service without preview

I am building an app which uses Camera2API to take pictures. The thing is I need the Camera to take a picture without needing a preview. So far, I managed to do it by dumping (and adapting) the code from an activity into a service and it works like a charm, except for the fact that it is not focusing. On previous versions I had a state machine in charge of that focusing on the preview by means of a separate CaptureRequest.Builder, but I can't make it work without creating a new CaptureRequest.Builder on the service.
I followed this topic on the following stackoverflow discussion How to lock focus in camera2 api, android? but I did not manage to make it work.
My code does the following:
First I create a camera session once the camera has been opened.
public void createCameraSession() {
try {
// Here, we create a CameraCaptureSession for camera preview.
cameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
// The camera is already closed
if (null == cameraDevice) {
return;
}
// When the session is ready, we start displaying the preview.
mCaptureSession = cameraCaptureSession;
camera2TakePicture();
}
#Override
public void onConfigureFailed(
#NonNull CameraCaptureSession cameraCaptureSession) {
}
}, null
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
Then on that camera session I call my method "camera2TakePicture()":
protected void camera2TakePicture() {
if (null == cameraDevice) {
return;
}
try {
Surface readerSurface = imageReader.getSurface();
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(readerSurface);
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(readerSurface);
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO);
captureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
//MeteringRectangle meteringRectangle = getAFRegion();
//captureBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[] {meteringRectangle});
/**** TO BE USED ONCE SAMSUNG TABLETS HAVE BEEN REPLACED ****/
boolean samsungReplaced = false;
if(Boolean.parseBoolean(getPreferenceValue(this, "manualCamSettings"))) {
int exposureCompensation = Integer.parseInt(getPreferenceValue(this, "exposureCompensation"));
captureBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, exposureCompensation);
if(samsungReplaced) {
//Exposure
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_OFF);
Float shutterSpeed = 1 / Float.parseFloat(getPreferenceValue(this, "camSSpeed"));
Long exposureTimeInNanoSec = new Long(Math.round(shutterSpeed * Math.pow(10, 9)));
captureBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, exposureTimeInNanoSec);
captureBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 10 * exposureTimeInNanoSec);
//ISO
int ISO = Integer.parseInt(getPreferenceValue(this, "camISO"));
captureBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, ISO);
//Aperture
Float aperture = Float.parseFloat(getPreferenceValue(this, "camAperture"));
captureBuilder.set(CaptureRequest.LENS_APERTURE, aperture);
}
}
// Orientation
WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = window.getDefaultDisplay();
int rotation = display.getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session,
#NonNull CaptureRequest request,
#NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
while(result.get(CaptureResult.CONTROL_AF_STATE) != CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED){
System.out.println("Not focused");
}
System.out.println("Focused");
}
};
mCaptureSession.stopRepeating();
mCaptureSession.abortCaptures();
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
captureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
As you can see, I set the CONTROL_AF_MODE to AUTO then start the AF_TRIGGER and launch the capture. I add a check on onCaptureCompleted() but the AF_STATE never seems to be on FOCUSED_LOCKED. It stays on ACTIVE_SCAN.
What am I doing wrong?
In your code snippet, you've stopped the repeating request, and issue one capture request for the still image, but just one.
Do you then go on to restart the repeating request? If you don't, there are no frames flowing through the camera, and AF cannot make progress.
So if you want to lock AF before you take a picture, you want to
Set AF_TRIGGER to START for a single capture only
Run preview until you get AE_STATE out of ACTIVE_SCAN
Issue single capture for still image.
Being in the background or foreground doesn't really change any of this.

Android take a picture without preview and without interaction

I'm new in android.
I found previous questions, but are quite old, actually I'm using API 23 or higher.
I'm interested in a way to obtaining a picture from a camera, without displaying the preview and without any touch or interaction of the user.
I used an intent to access to a camera app but don't let me to take a picture automatically in the way I need.
This only let me to use camera app.
Intent intentTakePic = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(intentTakePic.resolveActivity(getPackageManager()) != null){
startActivityForResult(intentTakePic, GET_THE_PICTURE);
}
In future I probably need also to record the audio in the same way (without interaction).
Does anyone has suggestion for me ?
You need to use the CameraAPI to take pictures without opening another camera app. https://developer.android.com/guide/topics/media/camera
You'll basically make a camera app.
// in the activity onCreate, but doesn't have to be there
// needs explicit permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[] {Manifest.permission.CAMERA}, 1);
}
}
final Camera camera = Camera.open();
CameraPreview cameraPreview = new CameraPreview(this, camera);
// preview is required. But you can just cover it up in the layout.
FrameLayout previewFL = findViewById(R.id.preview_layout);
previewFL.addView(cameraPreview);
camera.startPreview();
// take picture button
findViewById(R.id.take_picture_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
camera.takePicture(null, null, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// path of where you want to save it
File pictureFile = new File(getFilesDir() + "/images/pic0");
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
});
CameraPreview class
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
e.printStackTrace();
}
}
}
I found these useful guide:
https://zatackcoder.com/android-camera-2-api-example-without-preview/
https://inducesmile.com/android/android-camera2-api-example-tutorial/
https://github.com/googlesamples/android-Camera2Basic

Using ImageReader with older Camera API (To be supported by API <20)

I took the Google example for using ImageReader from here.
The code uses Camera2 API and ImageReader to such that querying image runs in different thread than previewing it.
As I want to target Android KitKat (API 20), I need to modify the code to use older Camera API with keeping the ImageReader part as is.
Here is the part of original code that sets onImageAvailableListener:
/**
* THIS IS CALLED WHEN OPENING CAMERA
* Sets up member variables related to camera.
*
* #param width The width of available size for camera preview
* #param height The height of available size for camera preview
*/
private void setUpCameraOutputs(int width, int height) {
Activity activity = getActivity();
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
// We don't use a front facing camera in this sample.
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
continue;
}
// For still image captures, we use the largest available size.
Size largest = Collections.max(
Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
new CompareSizesByArea());
mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(),
ImageFormat.JPEG, /*maxImages*/2);
mImageReader.setOnImageAvailableListener(
mOnImageAvailableListener, mBackgroundHandler);
.
.
.
.
}
Now I was able to use older Camera API. But I am lost in connecting it with ImageReader. So I don't know how should I set onImageListener so that I can access it once the image is delivered.
Here is my modification :
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mTextureView = (AutoFitTextureView) v.findViewById(R.id.texture);
mTextureView.setSurfaceTextureListener(new SurfaceTextureListener() {
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface,
int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return true;
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface,
int width, int height) {
mCamera = Camera.open();
try {
Camera.Parameters parameters = mCamera.getParameters();
if (getActivity().getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
// parameters.set("orientation", "portrait"); // For
// Android Version 2.2 and above
mCamera.setDisplayOrientation(90);
// For Android Version 2.0 and above
parameters.setRotation(90);
}
mCamera.setParameters(parameters);
mCamera.setPreviewTexture(surface);
} catch (IOException exception) {
mCamera.release();
}
mCamera.startPreview();
setUpCameraOutputs(width, height);
tfPreviewListener.initialize(getActivity().getAssets(), scoreView);
}
});
}
My question is how should I add ImageReader in the code above to make it work properly?
Thanks in advance.

how to get byte array from camera preview in java android?

I'm a complete noob . I've managed to write and understand this code after reading this http://developer.android.com/guide/topics/media/camera.html .
But now i want to get the byte array for preview and then convert it to bitmap . But i want to do this in real time without be forced to save a picture file in storage . Please , help!
Here is my program code.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
String TAG = null;
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
mCamera.setDisplayOrientation(90);
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
String TAG = null;
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
private PictureCallback mPicture = new PictureCallback(){
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
// TODO: Implement this method
}
};
}
And main activity :
public class MainActivity extends Activity
{ private Camera mCamera;
private CameraPreview mPreview;
int i;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.frame);
preview.addView(mPreview);
}
public static Camera getCameraInstance()
{
Camera c = null;
try
{
c = Camera.open();}
catch (Exception e)
{ System.out.println("blamjjjh");}
return c;
}
public void releasec(){
mCamera.release();
}
#Override
protected void onStop()
{
super.onStop();
releasec();
}
}
As detailed in the Android Developer docs here (which you might have already read), add an implementation of the PictureCallback interface (see the example below) to your Activity. Also you can use BitmapFactory to then convert the byte array that gets passed back to a Bitmap. Then you can use this as required.
NOTE:
I would also read the docs here on handling Bitmaps efficiently in relation to memory as you might get OutOfMemory errors if you're manipulating Bitmaps.
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
//create a Bitmap from the byte array
Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data.length);
//use your Bitmap
}
};
You then need to pass this into the takePicture() method against your camera instance e.g.
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
Hope this helps! :-)

Exception on camera.setPreviewDisplay(SurfaceHolder)

New to Android programming here.
I have had a look around and have found this to be a common issue, but I don't really see an easy fix... I am trying to run the following code on a Nexus 7 (have tried AVD & physical device) with no luck whatsoever. It seems to be the:
camera.setPreviewDisplay(SurfaceHolder);
But I could be wrong. Here is the current code:
public class MainActivity extends Activity implements SurfaceHolder.Callback{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cameralayout);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
}
public void onClick() {
// TODO Auto-generated method stub
if(!previewing){
camera = Camera.open();
if (camera != null){
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Any ideas folks? Thank you for your help!
From android documentation about Camera.open()
Creates a new Camera object to access the first back-facing camera on
the device. If the device does not have a back-facing camera, this
returns null.
It gives you only an access to back-facing Camera.
I am trying to run the following code on a Nexus 7
Camera.open() returns null because Nexus 7 doesn't have a back camera, only a front camera.
You could try this method
public Camera getCamera()
{
for(int i = 0; i < Camera.getNumberOfCameras(); i++)
return Camera.open(i);
return null;
}
To apply,
camera = getCamera();

Categories