2015-01-17 13 views
11

Was ich erreichen möchte, ist ein Bild ohne Vorschau zu erfassen, Senden Sie die Ausgabe direkt an eine ImageReader. Ich habe die Camera2Basic example als Ausgangspunkt verwendet. Der Rückruf von meinem ImageReader wird jedoch nie aufgerufen, daher wird kein Bild an seine Surface gesendet. Muss ich wirklich zuerst eine Vorschau anzeigen?Capture Bild ohne Vorschau mit Kamera2 API

Dies ist die Kamera-Code, der nach dem Fluss der asynchronen Rückrufe bestellt:

private ImageReader imageReader; 
private Handler backgroundHandler; 
private HandlerThread backgroundThread; 
private String cameraId; 
private CameraDevice cameraDevice; 
private CameraCaptureSession cameraCaptureSession; 
    @Override 
    public void onCreate() { 
     setupCamera2(); 
    } 

    private void setupCamera2() { 
     CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 

     try { 

      for (String cameraId : manager.getCameraIdList()) { 
      CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); 

      if (characteristics.get(CameraCharacteristics.LENS_FACING) != CameraCharacteristics.LENS_FACING_FRONT) { 
       continue; 
      } 

      this.cameraId = cameraId; 

      int[] picSize = Settings.getPictureSize(); 
      int picWidth = picSize[0]; 
      int picHeight = picSize[1]; 

      imageReader = ImageReader.newInstance(picWidth, picHeight, ImageFormat.JPEG, 2); 
      imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler); 
      } 

     } catch (CameraAccessException | NullPointerException e) { 
      e.printStackTrace(); 
     } 
    } 


    private void openCamera2() { 
     CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
     try { 

      manager.openCamera(cameraId, cameraStateCallback, backgroundHandler); 

     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 



    private final CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() { 
     @Override 
     public void onOpened(CameraDevice device) { 
      cameraDevice = device; 
      createCameraCaptureSession(); 
     } 

     @Override 
     public void onDisconnected(CameraDevice cameraDevice) {} 

     @Override 
     public void onError(CameraDevice cameraDevice, int error) {} 
    }; 



    private void createCaptureSession() { 
     List<Surface> outputSurfaces = new LinkedList<>(); 
     outputSurfaces.add(imageReader.getSurface()); 

     try { 

      cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { 
       @Override 
       public void onConfigured(CameraCaptureSession session) { 
        cameraCaptureSession = session; 
       } 

       @Override 
       public void onConfigureFailed(CameraCaptureSession session) {} 
      }, null); 

     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 


    private final ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() { 
     @Override 
     public void onImageAvailable(ImageReader reader) { 
      createCaptureRequest(); 
     } 
    }; 


    private void createCaptureRequest() { 
     try { 

      CaptureRequest.Builder requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
      requestBuilder.addTarget(imageReader.getSurface()); 

      // Focus 
      requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 

      // Orientation 
      int rotation = windowManager.getDefaultDisplay().getRotation(); 
      requestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); 

      cameraCaptureSession.capture(requestBuilder.build(), camera2Callback, null); 

     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 
+2

Haben Sie es jemals ohne die Vorschau funktioniert? –

+0

@KimHJ ja, überprüfen Sie meine Antwort unten :) – Mitchapp

Antwort

15

Sie sollten Fotos erfassen in „onConfigured“ Funktion aber nicht onImageAvailable.

public void onConfigured(CameraCaptureSession session) { 
      cameraCaptureSession = session; 
      createCaptureRequest(); 
     } 

In dieser Funktion "onImageAvailable", sollten Sie Bilder speichern,

Image image = mImageReader.acquireLatestImage(); 
ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
byte[] bytes = new byte[buffer.remaining()]; 
buffer.get(bytes); 
try { 
    save(bytes, file); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
image.close(); 

"onImageAvailable" -Funktion wird nach session.capture aufgerufen werden().

+0

Danke, es funktioniert. Eine Frage ein wenig abseits vom Thema: Was denkst du ist das beste Bildformat für den ImageReader? –

+2

YUV. Es ist mühsam, RGB zu konvertieren, aber die Qualität ist schwer zu erreichen. – Sipty

12

Da ich viel Mühe hatte, herauszufinden, wie das funktioniert, hier ist ein minimal funktionierender Android Service, der Bilddaten verarbeiten kann. Es braucht wahrscheinlich einige Zeit nach dem Erstellen, bevor Sie den Dienst starten können, obwohl!

import android.app.Service; 
import android.content.Intent; 
import android.graphics.ImageFormat; 
import android.hardware.camera2.CameraAccessException; 
import android.hardware.camera2.CameraCaptureSession; 
import android.hardware.camera2.CameraCharacteristics; 
import android.hardware.camera2.CameraDevice; 
import android.hardware.camera2.CameraManager; 
import android.hardware.camera2.CaptureRequest; 
import android.media.Image; 
import android.media.ImageReader; 
import android.os.IBinder; 
import android.util.Log; 

import java.util.Arrays; 

public class VideoProcessingService extends Service { 
    private static final String TAG = "VideoProcessing"; 
    private static final int CAMERA = CameraCharacteristics.LENS_FACING_FRONT; 
    private CameraDevice camera; 
    private CameraCaptureSession session; 
    private ImageReader imageReader; 

    private CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() { 
     @Override 
     public void onOpened(CameraDevice camera) { 
      VideoProcessingService.this.camera = camera; 
     } 

     @Override 
     public void onDisconnected(CameraDevice camera) {} 

     @Override 
     public void onError(CameraDevice camera, int error) {} 
    }; 

    private CameraCaptureSession.StateCallback sessionStateCallback = new CameraCaptureSession.StateCallback() { 
     @Override 
     public void onConfigured(CameraCaptureSession session) { 
      VideoProcessingService.this.session = session; 
      try { 
       session.setRepeatingRequest(createCaptureRequest(), null, null); 
      } catch (CameraAccessException e){ 
       Log.e(TAG, e.getMessage()); 
      } 
     } 

     @Override 
     public void onConfigureFailed(CameraCaptureSession session) {} 
    }; 

    private ImageReader.OnImageAvailableListener onImageAvailableListener = new ImageReader.OnImageAvailableListener() { 
     @Override 
     public void onImageAvailable(ImageReader reader){ 
      Image img = reader.acquireLatestImage(); 
      processImage(img); 
      img.close(); 
     } 
    }; 

    @Override 
    public void onCreate() { 
     CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE); 
     try { 
      manager.openCamera(getCamera(manager), cameraStateCallback, null); 
      imageReader = ImageReader.newInstance(320, 240, ImageFormat.YUV_420_888, 30 * 600); //fps * 10 min 
      imageReader.setOnImageAvailableListener(onImageAvailableListener, null); 
     } catch (CameraAccessException e){ 
      Log.e(TAG, e.getMessage()); 
     } 
    } 

    /** 
    * Return the Camera Id which matches the field CAMERA. 
    */ 
    public String getCamera(CameraManager manager){ 
     try { 
      for (String cameraId : manager.getCameraIdList()) { 
       CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); 
       int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING); 
       if (cOrientation == CAMERA) { 
        return cameraId; 
       } 
      } 
     } catch (CameraAccessException e){ 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     try { 
      camera.createCaptureSession(Arrays.asList(imageReader.getSurface()), sessionStateCallback, null); 
     } catch (CameraAccessException e){ 
      Log.e(TAG, e.getMessage()); 
     } 
     return super.onStartCommand(intent, flags, startId); 
    } 

    @Override 
    public void onDestroy() { 
     try { 
      session.abortCaptures(); 
     } catch (CameraAccessException e){ 
      Log.e(TAG, e.getMessage()); 
     } 
     session.close(); 
    } 

    /** 
    * Process image data as desired. 
    */ 
    private void processImage(Image image){ 
     //Process image data 
    } 

    private CaptureRequest createCaptureRequest() { 
     try { 
      CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); 
      builder.addTarget(imageReader.getSurface()); 
      return builder.build(); 
     } catch (CameraAccessException e) { 
      Log.e(TAG, e.getMessage()); 
      return null; 
     } 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 
} 
+3

Hat eine Ausnahme 'verursacht durch: java.lang.NullPointerException: Versuch, virtuelle Methode aufzurufen 'void android.hardware.camera2.CameraDevice.createCaptureSession (java.util.List, android.hardware.camera2.CameraCaptureSession $ StateCallback, android.os .Handler) 'auf einer Null-Objektreferenz' – iMom0

+1

Beim Erstellen von ImageReader müssen Sie max. Bilder nicht auf 30 * 600 setzen. Die Puffer werden wiederverwendet. Sie müssen nur das Image von ImageReader schließen. – alexhilton

+0

Kleine Fehler gibt: 'if (cOrientation == CameraCharacteristics.LENS_FACING_BACK) {' statt 'if (cOrientation == CAMERA) {' – RenaudBlue

4

Seit ich mit KAMERA2 API für eine lange Zeit zu kämpfen, suchen, wie Bilder machen ohne Vorschau von alle verfügbaren Kameras auf dem Gerät, habe ich ein Projekt auf GitHub geschaffen, tut genau das, was Sie wollen (und vielleicht auch mehr) https://github.com/hzitoun/android-camera2-secret-picture-taker

enter image description here

Hoffnung, die dazu beigetragen :)

+0

Wo ist der Abhängigkeitslink für diese Bibliothek bro. – viper

+0

@viper gibt es keine Bibliothek bro. Sie müssen nur den CaptureService https://github.com/hzitoun/android-camera2-secret-picture-taker/tree/master/app/src/main/java/com/hzitoun/camera2SecretPictureTaker/services kopieren – Mitchapp