在Samsung J6设备上使用Camera2 API并将ImageReader添加到照相机输出时,预览会倾斜,并且在ImageReader.onImageAvailable中获取的图像也会倾斜。
例如,如果我使用960x720作为预览的分辨率(屏幕尺寸为1:1像素比例),对于ImageReader使用960x720,则没有问题,所有图像看起来都不错,并且人脸检测也可以。但是,如果将ImageReader分辨率设置为2048x1536(以获得更好的处理质量),则预览图像看起来像裁剪为16:9,然后扩展回4:3以匹配预览尺寸。与ImageReader.onImageAvailable中的图像相同。
https://i.ibb.co/zPbTGJ3/ss1.jpg https://i.ibb.co/McbL93k/ss2.jpg
人脸检测似乎也是错误的,因为它返回的最大坐标是人脸仅位于视图的中心(SENSOR_INFO_ACTIVE_ARRAY_SIZE为4144x3106)。
https://i.ibb.co/6wtP5qS/ss3.jpg
这在Galaxy S7,S8,S9,A8等更高规格的设备上正常运行,但我注意到它在Samsung J5或J6设备上无法正常工作。
这是我的SurfaceTextureListener代码:
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
try {
if(useCamera2API) {
mCameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE);
String[] cameraList = mCameraManager.getCameraIdList();
if(cameraList.length == 0) {
return;
}
mCameraCharacteristics = mCameraManager.getCameraCharacteristics(cameraList[0]);
mMaxCameraSize = new Rectangle(mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)).size;
nativeRatio = mMaxCameraSize.width / mMaxCameraSize.height;
height = (int)(width * nativeRatio);
VCamera.getLayoutParams().height = height;
mScreenSize = new Size(height, width);
StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map != null) {
Size[] previewSizes = Size.castSizes(map.getOutputSizes(SurfaceTexture.class));
Size[] yuvSizes = Size.castSizes(map.getOutputSizes(ImageFormat.YUV_420_888));
// this gets the smallest size closest to maximum camera size ratio while keeping both dimensions above 1000 pixels
mCameraSize = Helper.getSmallestSize(yuvSizes, 1000, nativeRatio);
// this gets size that is closest to 1:1 pixel ratio to screen
mPreviewSize = Helper.getOptimalPreviewSize(previewSizes, height, width);
log(String.format("%d %d, %d %d", (int) mCameraSize.width, (int) mCameraSize.height, (int) mPreviewSize.width, (int) mPreviewSize.height));
supportsAEAreas = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE) > 0;
supportsAFAreas = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF) > 0;
mPreviewImageReader = ImageReader.newInstance((int) mCameraSize.getWidth(), (int) mCameraSize.getHeight(), ImageFormat.YUV_420_888, 1);
和CameraDevice.StateCallback代码:
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
Log.d(LOG_TAG, "Camera opened.");
mCameraDevice = camera;
SurfaceTexture texture = VCamera.getSurfaceTexture();
if (texture == null) {
return;
}
texture.setDefaultBufferSize((int) mPreviewSize.getWidth(), (int) mPreviewSize.getHeight());
Surface surface = new Surface(texture);
try {
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
List<Surface> surfaces = new ArrayList<>();
mPreviewBuilder.addTarget(surface);
surfaces.add(surface);
mPreviewBuilder.addTarget(mPreviewImageReader.getSurface());
surfaces.add(mPreviewImageReader.getSurface());
backgroundThread = new HandlerThread("CameraPreview");
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
mPreviewImageReader.setOnImageAvailableListener(mImageAvailableListener, backgroundHandler);
mCameraDevice.createCaptureSession(surfaces, previewStateCallback, null);
if(mode == CameraRequestMode.BARCODE_CONTINUOUS) {
delegate.cameraContinuousStarted();
}
我希望至少预览看起来正常。我缺少任何配置吗?我在某些设备上看到了Camera2 API刚刚损坏的信息。如果可以得到比预览更高分辨率的帧,我将退回到旧的Camera API(可能是,但不是那么容易实现)。我是否仅使用960x720作为处理图像的分辨率?