安卓开发摄像头预览后获取实时帧数据出错
摄像头预览功能已经完成且成功开启,在获取帧图像时出现错误,这里设置了一个点击按钮,点击后获取帧图像并展示在imagevie上,但是实操下来点击按钮直接退出

这是点击按钮后的事件函数
设置imagReader函数

detect函数

最后是yuv格式数据转换为bitmap类型

安卓开发摄像头预览后获取实时帧数据出错
摄像头预览功能已经完成且成功开启,在获取帧图像时出现错误,这里设置了一个点击按钮,点击后获取帧图像并展示在imagevie上,但是实操下来点击按钮直接退出




关注引自免费微信小程序:皆我百晓生
根据您提供的代码片段,我发现了一些可能的问题所在,并为您提供相应的修复建议。
首先,让我们查看convertImageToBitmap()方法中的错误。当从YUV格式转换为Bitmap时,我们应确保正确处理YUV数据。以下是修复过的convertImageToBitmap()方法:
private Bitmap convertImageToBitmap(Image image) {
if (image == null) {
return null;
}
Image.Plane[] planes = image.getPlanes();
ByteBuffer byteBuffer = planes[0].getBuffer();
int ySize = byteBuffer.remaining();
// NV21 format requires a buffer for U and V data, which is half the size of Y data.
int uvSize = ySize / 2;
byte[] nv21Bytes = new byte[ySize + uvSize];
// Copy Y plane to the beginning of the NV21 buffer.
byteBuffer.get(nv21Bytes, 0, ySize);
// Prepare UV planes.
byteBuffer.position(ySize);
byte[] uData = Arrays.copyOfRange(nv21Bytes, ySize, ySize + uvSize / 2);
byte[] vData = Arrays.copyOfRange(nv21Bytes, ySize + uvSize / 2, ySize + uvSize);
byte[] uvData = new byte[uData.length + vData.length];
System.arraycopy(uData, 0, uvData, 0, uData.length);
System.arraycopy(vData, 0, uvData, uData.length, vData.length);
// Combine Y and UV planes into one buffer.
byte[] combinedData = new byte[ySize + uvSize];
System.arraycopy(nv21Bytes, 0, combinedData, 0, ySize);
System.arraycopy(uvData, 0, combinedData, ySize, uvData.length);
YuvImage yuvImage = new YuvImage(combinedData, ImageFormat.NV21, image.getWidth(), image.getHeight(), null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, image.getWidth(), image.getHeight()), 100, baos);
byte[] jpegByteArray = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length);
return bitmap;
}
接下来,检查您的setupImageReader()方法,确保maxImages参数设置正确。将maxImages:2改为maxImages:1,因为我们需要立即处理最新的一张图片,而不是等待多张图片累积在一起。
private void setupImageReader() {
capturesize = chooseOptimalSize(cameraManager.getAvailablePreviewSizes());
imageReader = ImageReader.newInstance(capturesize.getWidth(), capturesize.getHeight(), ImageFormat.JPEG, 1); // Change maxImages from 2 to 1
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
backgroundHandler.post(new ImageDetection(reader.acquireLatestImage()));
}, backgroundHandler);
}
然后,检查一下您的capture()方法,确保在捕获回调中没有忘记调用startRepeating()来重新启动捕获会话。这样可以防止在捕获单张照片后停止捕获会话,导致无法继续接收新的图像。
private void capture(View view) {
try {
CaptureRequest.Builder cameraBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
cameraBuilder.addTarget(imageReader.getSurface());
int rotation =getWindowManager().getDefaultDisplay().getRotation();
CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull Totalt result) {
Toast.makeText(getApplicationContext(), "已获取帧图像", Toast.LENGTH_LONG).show();
// unlockFocus();
super.onCaptureCompleted(session, request, result);
}
};
cameraBuilder.set(CaptureRequest.JPEG_ORIENTATION, (Integer) ORIENTATION.get(rotation));
cameraCaptureSessions.stopRepeating(); // 停止当前重复的捕获
cameraCaptureSessions.capture(cameraBuilder.build(), captureCallback, backgroundHandler);
// 在捕获完成后重启捕获会话
startRepeatingCapture();
} catch (CameraAccessException e){
throw new RuntimeException(e);
}
}
private void startRepeatingCapture() {
// 如果捕获会话尚未准备就绪,则等待其准备完成
if (!cameraCaptureSessions.isConfigured()) {
Log.w("CameraApp", "Capture sessions not configured yet");
return;
}
try {
cameraCaptureSessions.setRepeatingRequest(cameraBuilder.build(), captureCallback, backgroundHandler);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
最后,确保您已经在初始化相机设备和捕获会话的地方添加了必要的代码。如果您还没有这样做,请参考以下代码:
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
// 初始化相机设备和捕获会话
private void openCamera() {
// ... 其他代码 ...
cameraManager.openCamera(deviceId, stateCallback, backgroundHandler);
}
private CameraCaptureSession.StateCallback stateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
cameraCaptureSessions = session;
startRepeatingCapture();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
// Handle configuration failure
}
};
// ... 其他代码 ...
按照这些更改,应该能解决您在获取实时帧数据时遇到的问题。记得在应用中实施上述修改,并确保其他相关部分(例如初始化相机、设置预览等)也正确配置。如果还有任何问题,请随时告诉我。