après plusieurs tutoriels et exemples, j'ai proposé l'algorithme suivant pour définir la mise au point de la caméra sur un point spécifique. Le problème est que la caméra ignore complètement le point et effectue une mise au point globale normale au lieu de la zone rect que j'ai spécifiée. Y a-t-il autre chose qui me manque dans l'algorithme? Ceci a été testé sur plusieurs téléphones, tous équipés d'Android 4.0 ou version ultérieure, de sorte que l'API de zone de focus est prise en charge sur ces appareils. Remarque, l'application que je suis en train d'écrire ne fonctionne qu'en mode paysage.
@Override
public boolean onTouchEvent(final MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_UP)
{
float x = event.getX();
float y = event.getY();
float touchMajor = event.getTouchMajor();
float touchMinor = event.getTouchMinor();
Rect touchRect = new Rect((int)(x - touchMajor / 2), (int)(y - touchMinor / 2), (int)(x + touchMajor / 2), (int)(y + touchMinor / 2));
this.submitFocusAreaRect(touchRect);
}
}
private void submitFocusAreaRect(final Rect touchRect)
{
Camera.Parameters cameraParameters = camera.getParameters();
if (cameraParameters.getMaxNumFocusAreas() == 0)
{
return;
}
// Convert from View's width and height to +/- 1000
Rect focusArea = new Rect();
focusArea.set(touchRect.left * 2000 / cameraSurfaceView.getWidth() - 1000,
touchRect.top * 2000 / cameraSurfaceView.getHeight() - 1000,
touchRect.right * 2000 / cameraSurfaceView.getWidth() - 1000,
touchRect.bottom * 2000 / cameraSurfaceView.getHeight() - 1000);
// Submit focus area to camera
ArrayList<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
focusAreas.add(new Camera.Area(focusArea, 1000));
cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
cameraParameters.setFocusAreas(focusAreas);
camera.setParameters(cameraParameters);
// Start the autofocus operation
camera.autoFocus(this);
}
ce travail pour moi se concentrer sur la caméra 1 Api
@Override
public boolean onTouchEvent(MotionEvent event) {
//variable for storing the time of first click
//constant for defining the time duration between the click that can be considered as double-tap
final int MAX_DURATION = 200;
// handle single touch events
if (action == MotionEvent.ACTION_UP) {
handleFocus(event, params);
startTime = System.currentTimeMillis();
}
else if (event.getAction() == MotionEvent.ACTION_DOWN) {
if(System.currentTimeMillis() - startTime <= MAX_DURATION)
{
//capture image on Double Tap
mCamera.autoFocus(ShotActivity_CameraActivity.this);
}
}
}
return true;
}
alors cette méthode pour gérer la zone de mise au point tactile
public void handleFocus(MotionEvent event, Camera.Parameters params) {
int pointerId = event.getPointerId(0);
int pointerIndex = event.findPointerIndex(pointerId);
// Get the pointer's current position
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);
Rect touchRect = new Rect(
(int) (x - 100),
(int) (y - 100),
(int) (x + 100),
(int) (y + 100) );
final Rect targetFocusRect = new Rect(
touchRect.left * 2000/mTextureView.getWidth() - 1000,
touchRect.top * 2000/mTextureView.getHeight() - 1000,
touchRect.right * 2000/mTextureView.getWidth() - 1000,
touchRect.bottom * 2000/mTextureView.getHeight() - 1000);
List<String> supportedFocusModes = params.getSupportedFocusModes();
if (supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
try {
List<Camera.Area> focusList = new ArrayList<Camera.Area>();
Camera.Area focusArea = new Camera.Area(targetFocusRect, 1000);
focusList.add(focusArea);
params.setFocusAreas(focusList);
params.setMeteringAreas(focusList);
mCamera.setParameters(params);
/* mCamera.autoFocus(this);*/
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "Unable to autofocus");
}
}
}
j'espère que cette aide
before cameraParameters.setFocusAreas (focusAreas) ;, vous devriez ajouter ceci:
cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
ce n'est pas mon code, mais vous pouvez l'essayer. Tous les crédits vont aux gars qui ont fait l'exemple ici Touchez pour sélectionner la zone de mise au point et de mesure
J'ai aussi contribué au code avec une petite ligne parce que lorsque je cliquais une seconde fois sur la vue en surface, l'application était écrasante. Veuillez donc utiliser la classe ("AndroidCamera") ci-dessous:
import Java.io.FileNotFoundException;
import Java.io.IOException;
import Java.io.OutputStream;
import Java.util.ArrayList;
import Java.util.List;
import Java.util.concurrent.Executors;
import Java.util.concurrent.ScheduledExecutorService;
import Java.util.concurrent.TimeUnit;
import Android.app.Activity;
import Android.content.ContentValues;
import Android.content.Context;
import Android.content.pm.ActivityInfo;
import Android.graphics.Canvas;
import Android.graphics.Color;
import Android.graphics.Paint;
import Android.graphics.PixelFormat;
import Android.graphics.Rect;
import Android.hardware.Camera;
import Android.hardware.Camera.AutoFocusCallback;
import Android.hardware.Camera.Face;
import Android.hardware.Camera.FaceDetectionListener;
import Android.hardware.Camera.Parameters;
import Android.hardware.Camera.PictureCallback;
import Android.hardware.Camera.ShutterCallback;
import Android.net.Uri;
import Android.os.Bundle;
import Android.provider.MediaStore.Images.Media;
import Android.view.LayoutInflater;
import Android.view.SurfaceHolder;
import Android.view.View;
import Android.view.ViewGroup.LayoutParams;
import Android.widget.Button;
import Android.widget.TextView;
public class AndroidCamera extends Activity implements SurfaceHolder.Callback{
Camera camera;
CameraSurfaceView cameraSurfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
Button buttonTakePicture;
TextView Prompt;
DrawingView drawingView;
Face[] detectedFaces;
final int RESULT_SAVEIMAGE = 0;
private ScheduledExecutorService myScheduledExecutorService;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().setFormat(PixelFormat.UNKNOWN);
cameraSurfaceView = (CameraSurfaceView)findViewById(R.id.camerapreview);
surfaceHolder = cameraSurfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);
drawingView = new DrawingView(this);
LayoutParams layoutParamsDrawing
= new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
this.addContentView(drawingView, layoutParamsDrawing);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.control, null);
LayoutParams layoutParamsControl
= new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
buttonTakePicture = (Button)findViewById(R.id.takepicture);
buttonTakePicture.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
camera.takePicture(myShutterCallback,
myPictureCallback_RAW, myPictureCallback_JPG);
}});
/*
LinearLayout layoutBackground = (LinearLayout)findViewById(R.id.background);
layoutBackground.setOnClickListener(new LinearLayout.OnClickListener(){
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
buttonTakePicture.setEnabled(false);
camera.autoFocus(myAutoFocusCallback);
}});
*/
Prompt = (TextView)findViewById(R.id.Prompt);
}
public void touchFocus(final Rect tfocusRect){
buttonTakePicture.setEnabled(false);
camera.stopFaceDetection();
//Convert from View's width and height to +/- 1000
final Rect targetFocusRect = new Rect(
tfocusRect.left * 2000/drawingView.getWidth() - 1000,
tfocusRect.top * 2000/drawingView.getHeight() - 1000,
tfocusRect.right * 2000/drawingView.getWidth() - 1000,
tfocusRect.bottom * 2000/drawingView.getHeight() - 1000);
final List<Camera.Area> focusList = new ArrayList<Camera.Area>();
Camera.Area focusArea = new Camera.Area(targetFocusRect, 1000);
focusList.add(focusArea);
Parameters para = camera.getParameters();
para.setFocusAreas(focusList);
para.setMeteringAreas(focusList);
camera.setParameters(para);
camera.autoFocus(myAutoFocusCallback);
drawingView.setHaveTouch(true, tfocusRect);
drawingView.invalidate();
camera.startFaceDetection();
}
FaceDetectionListener faceDetectionListener
= new FaceDetectionListener(){
@Override
public void onFaceDetection(Face[] faces, Camera tcamera) {
if (faces.length == 0){
//Prompt.setText(" No Face Detected! ");
drawingView.setHaveFace(false);
}else{
//Prompt.setText(String.valueOf(faces.length) + " Face Detected :) ");
drawingView.setHaveFace(true);
detectedFaces = faces;
//Set the FocusAreas using the first detected face
List<Camera.Area> focusList = new ArrayList<Camera.Area>();
Camera.Area firstFace = new Camera.Area(faces[0].rect, 1000);
focusList.add(firstFace);
Parameters para = camera.getParameters();
if(para.getMaxNumFocusAreas()>0){
para.setFocusAreas(focusList);
}
if(para.getMaxNumMeteringAreas()>0){
para.setMeteringAreas(focusList);
}
camera.setParameters(para);
buttonTakePicture.setEnabled(false);
//Stop further Face Detection
camera.stopFaceDetection();
buttonTakePicture.setEnabled(false);
/*
* Allways throw Java.lang.RuntimeException: autoFocus failed
* if I call autoFocus(myAutoFocusCallback) here!
*
camera.autoFocus(myAutoFocusCallback);
*/
//Delay call autoFocus(myAutoFocusCallback)
myScheduledExecutorService = Executors.newScheduledThreadPool(1);
myScheduledExecutorService.schedule(new Runnable(){
public void run() {
camera.autoFocus(myAutoFocusCallback);
}
}, 500, TimeUnit.MILLISECONDS);
}
drawingView.invalidate();
}};
AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback(){
@Override
public void onAutoFocus(boolean arg0, Camera arg1) {
// TODO Auto-generated method stub
if (arg0){
buttonTakePicture.setEnabled(true);
camera.cancelAutoFocus();
}
float focusDistances[] = new float[3];
arg1.getParameters().getFocusDistances(focusDistances);
Prompt.setText("Optimal Focus Distance(meters): "
+ focusDistances[Camera.Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX]);
}};
ShutterCallback myShutterCallback = new ShutterCallback(){
@Override
public void onShutter() {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_RAW = new PictureCallback(){
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_JPG = new PictureCallback(){
@Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
/*Bitmap bitmapPicture
= BitmapFactory.decodeByteArray(arg0, 0, arg0.length); */
Uri uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues());
OutputStream imageFileOS;
try {
imageFileOS = getContentResolver().openOutputStream(uriTarget);
imageFileOS.write(arg0);
imageFileOS.flush();
imageFileOS.close();
Prompt.setText("Image saved: " + uriTarget.toString());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();
camera.startFaceDetection();
}};
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
if(previewing){
camera.stopFaceDetection();
camera.stopPreview();
previewing = false;
}
if (camera != null){
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
Prompt.setText(String.valueOf(
"Max Face: " + camera.getParameters().getMaxNumDetectedFaces()));
camera.startFaceDetection();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
camera.setFaceDetectionListener(faceDetectionListener);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera.stopFaceDetection();
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
private class DrawingView extends View{
boolean haveFace;
Paint drawingPaint;
boolean haveTouch;
Rect touchArea;
public DrawingView(Context context) {
super(context);
haveFace = false;
drawingPaint = new Paint();
drawingPaint.setColor(Color.GREEN);
drawingPaint.setStyle(Paint.Style.STROKE);
drawingPaint.setStrokeWidth(2);
haveTouch = false;
}
public void setHaveFace(boolean h){
haveFace = h;
}
public void setHaveTouch(boolean t, Rect tArea){
haveTouch = t;
touchArea = tArea;
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
if(haveFace){
// Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
// UI coordinates range from (0, 0) to (width, height).
int vWidth = getWidth();
int vHeight = getHeight();
for(int i=0; i<detectedFaces.length; i++){
if(i == 0){
drawingPaint.setColor(Color.GREEN);
}else{
drawingPaint.setColor(Color.RED);
}
int l = detectedFaces[i].rect.left;
int t = detectedFaces[i].rect.top;
int r = detectedFaces[i].rect.right;
int b = detectedFaces[i].rect.bottom;
int left = (l+1000) * vWidth/2000;
int top = (t+1000) * vHeight/2000;
int right = (r+1000) * vWidth/2000;
int bottom = (b+1000) * vHeight/2000;
canvas.drawRect(
left, top, right, bottom,
drawingPaint);
}
}else{
canvas.drawColor(Color.TRANSPARENT);
}
if(haveTouch){
drawingPaint.setColor(Color.BLUE);
canvas.drawRect(
touchArea.left, touchArea.top, touchArea.right, touchArea.bottom,
drawingPaint);
}
}
}
}
Tout ce que j'ai fait était d'ajouter camera.startFaceDetection();
après drawingView.invalidate();
P.S. Sur ce site se trouve un lien pour télécharger le projet entier!