android image-processing camera preview android-5.0-lollipop

Procesamiento de datos de imagen de vista previa de cámara con Android L y Camera2 API



image-processing preview (5)

Combinando unas pocas respuestas en una más digerible porque la respuesta de @ VP, aunque técnicamente clara, es difícil de entender si es la primera vez que te mueves de la Cámara a la Cámara2:

Usando https://github.com/googlesamples/android-Camera2Basic como punto de partida, modifique lo siguiente:

En createCameraPreviewSession() init una nueva Surface desde mImageReader

Surface mImageSurface = mImageReader.getSurface();

Agregue esa nueva superficie como un objetivo de salida de su variable CaptureRequest.Builder . Usando la muestra Camera2Basic, la variable será mPreviewRequestBuilder

mPreviewRequestBuilder.addTarget(mImageSurface);

Aquí está el fragmento con las nuevas líneas (ver mis comentarios de @AngeloS):

private void createCameraPreviewSession() { try { SurfaceTexture texture = mTextureView.getSurfaceTexture(); assert texture != null; // 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); //@AngeloS - Our new output surface for preview frame data Surface mImageSurface = mImageReader.getSurface(); // We set up a CaptureRequest.Builder with the output Surface. mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); //@AngeloS - Add the new target to our CaptureRequest.Builder mPreviewRequestBuilder.addTarget(mImageSurface); mPreviewRequestBuilder.addTarget(surface); ...

A continuación, en setUpCameraOutputs() , cambie el formato de ImageFormat.JPEG a ImageFormat.YUV_420_888 cuando ImageFormat.YUV_420_888 su ImageReader . (PD, también recomiendo bajar el tamaño de vista previa para una operación más suave, una buena característica de Camera2)

mImageReader = ImageReader.newInstance(largest.getWidth() / 16, largest.getHeight() / 16, ImageFormat.YUV_420_888, 2);

Finalmente, en su método onImageAvailable() de ImageReader.OnImageAvailableListener , asegúrese de usar la sugerencia de @ Kamala porque la vista previa se detendrá después de unos pocos cuadros si no la cierra

@Override public void onImageAvailable(ImageReader reader) { Log.d(TAG, "I''m an image frame!"); Image image = reader.acquireNextImage(); ... if (image != null) image.close(); }

Estoy trabajando en una aplicación de Android que está procesando la imagen de entrada de la cámara y se la muestra al usuario. Esto es bastante simple, registro una PreviewCallback en el objeto de la cámara con setPreviewCallbackWithBuffer . Esto es fácil y funciona sin problemas con la antigua API de la cámara

public void onPreviewFrame(byte[] data, Camera cam) { // custom image data processing }

Intento portar mi aplicación para aprovechar la nueva API de Camera2 y no estoy seguro de cómo debo hacerlo. Seguí Camera2Video en L Vista previa de muestras que permite grabar un video. Sin embargo, no hay transferencia directa de datos de imagen en la muestra, por lo que no entiendo exactamente dónde obtendré los datos de píxeles de la imagen y cómo procesarlos.

¿Alguien podría ayudarme o sugerir la forma en que uno puede obtener la funcionalidad de PreviewCallback en Android L, o cómo es posible procesar los datos de la vista previa de la cámara antes de mostrarla en la pantalla? (no hay devolución de llamada previa en el objeto de la cámara)

¡Gracias!


Como la API de Camera2 es muy diferente de la API de la Camera actual, podría ser útil revisar la documentación.

Un buen punto de partida es el ejemplo de camera2basic . Demuestra cómo usar Camera2 API y configurar ImageReader para obtener imágenes JPEG y registrar ImageReader.OnImageAvailableListener para recibir esas imágenes

Para recibir marcos de vista previa, debe agregar la superficie de su ImageReader a setRepeatingRequest ''s CaptureRequest.Builder .

Además, debe establecer el formato de ImageReader en YUV_420_888 , que le dará 30 fps en 8MP (la documentación garantiza 30 fps en 8MP para Nexus 5).


En la clase ImageReader.OnImageAvailableListener, cierre la imagen después de leer, como se muestra a continuación (esto liberará el buffer para la siguiente captura). Deberá manejar la excepción al cerrar

Image image = imageReader.acquireNextImage(); ByteBuffer buffer = image.getPlanes()[0].getBuffer(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); image.close();


Es mejor iniciar ImageReader con el búfer de imagen máximo es 2 luego usar reader.acquireLatestImage() dentro onImageAvailable() .

Porque acquireLatestImage() adquirirá la última imagen de la cola del ImageReader, soltando la anterior. Se recomienda utilizar esta función sobre acquireNextImage() para la mayoría de los casos de uso, ya que es más adecuada para el procesamiento en tiempo real. Tenga en cuenta que el buffer de imagen máximo debe ser de al menos 2 .

Y recuerde close() su imagen después del procesamiento.


Necesitaba lo mismo, así que usé su ejemplo y agregué una llamada a una nueva función cuando la cámara está en el estado de vista previa.

private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() private void process(CaptureResult result) { switch (mState) { case STATE_PREVIEW: { if (buttonPressed){ savePreviewShot(); } break; }

savePreviewShot() es simplemente una versión reciclada del original captureStillPicture() adaptado para usar la plantilla de vista previa.

private void savePreviewShot(){ try { final Activity activity = getActivity(); if (null == activity || null == mCameraDevice) { return; } // This is the CaptureRequest.Builder that we use to take a picture. final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureBuilder.addTarget(mImageReader.getSurface()); // Orientation int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation)); CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss:SSS"); Date resultdate = new Date(System.currentTimeMillis()); String mFileName = sdf.format(resultdate); mFile = new File(getActivity().getExternalFilesDir(null), "pic "+mFileName+" preview.jpg"); Log.i("Saved file", ""+mFile.toString()); unlockFocus(); } }; mCaptureSession.stopRepeating(); mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null); } catch (Exception e) { e.printStackTrace(); } };