Attualmente sto lavorando con camera2Basic e sto provando a ottenere i dati di ogni frame per eseguire un po 'di elaborazione dell'immagine. Sto usando l'API di Camera2 in Android5.0, tutto è perfetto quando si fa solo l'anteprima della fotocamera ed è fluido. Ma l'anteprima si blocca quando uso il callback ImageReader.OnImageAvailableListener
per ottenere ogni frame di dati, questo causa una cattiva esperienza utente. il seguente è i miei codici correlati:Come ottenere ciascun frame utilizzando l'API camera2 in Android5.0 in tempo reale
Questa è la configurazione per fotocamera e ImageReader, ho impostato il formato di immagine è YUV_420_888
public<T> Size setUpCameraOutputs(CameraManager cameraManager,Class<T> kClass, int width, int height) {
boolean flagSuccess = true;
try {
for (String cameraId : cameraManager.getCameraIdList()) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
// choose the front or back camera
if (FLAG_CAMERA.BACK_CAMERA == mChosenCamera &&
CameraCharacteristics.LENS_FACING_BACK != characteristics.get(CameraCharacteristics.LENS_FACING)) {
continue;
}
if (FLAG_CAMERA.FRONT_CAMERA == mChosenCamera &&
CameraCharacteristics.LENS_FACING_FRONT != characteristics.get(CameraCharacteristics.LENS_FACING)) {
continue;
}
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size largestSize = Collections.max(
Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)),
new CompareSizesByArea());
mImageReader = ImageReader.newInstance(largestSize.getWidth(), largestSize.getHeight(),
ImageFormat.YUV_420_888, 3);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
...
mCameraId = cameraId;
}
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (NullPointerException e) {
}
......
}
Quando la fotocamera ha aperto con successo, a creare un CameraCaptureSession per la macchina fotografica anteprima
private void createCameraPreviewSession() {
if (null == mTexture) {
return;
}
// We configure the size of default buffer to be the size of camera preview we want.
mTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
// This is the output Surface we need to start preview
Surface surface = new Surface(mTexture);
// We set up a CaptureRequest.Builder with the output Surface.
try {
mPreviewRequestBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
mPreviewRequestBuilder.addTarget(surface);
// We create a CameraCaptureSession for camera preview
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
if (null == mCameraDevice) {
return;
}
// when the session is ready, we start displaying the preview
mCaptureSession = session;
// Finally, we start displaying the camera preview
mPreviewRequest = mPreviewRequestBuilder.build();
try {
mCaptureSession.setRepeatingRequest(mPreviewRequest,
mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
l'ultimo è il ImageReader.OnImageAvailableListener
richiamata
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Log.d(TAG, "The onImageAvailable thread id: " + Thread.currentThread().getId());
Image readImage = reader.acquireLatestImage();
readImage.close();
}
};
Forse faccio la configurazione sbagliata ma provo più volte e non funziona. Forse c'è un altro modo per ottenere i dati del frame piuttosto che ImageReader, ma non lo so. Qualcuno sa come ottenere i dati di ogni frame in tempo reale?
Che tipo di elaborazione stai cercando di fare? Penso che se si desidera salvare l'immagine, utilizzare un ImageReader, ma se si desidera eseguire un'elaborazione in tempo reale efficiente, è necessario inviare i dati al buffer di Surface associato a un'allocazione. – rcsumner
@ Sumner, voglio ottenere ogni fotogramma dalla fotocamera e fare il rilevamento del volto piuttosto che salvare l'immagine. Sembra che la soluzione che offri sia buona, puoi fornire maggiori dettagli? – CJZ
... non hahaha davvero, mi dispiace. Solitamente, salvo solo le immagini per i miei scopi. So che implica l'uso di RenderScript, però. Guarda la documentazione della classe di allocazione. – rcsumner