首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android Camera2预览已经扩展。

Android Camera2预览已经扩展。
EN

Stack Overflow用户
提问于 2020-09-13 07:18:52
回答 2查看 1K关注 0票数 2

我正在努力学习Camera2的API,我已经建立了一个简单的相机应用程序,只是为了拍照,但我面临的问题是,预览是延伸到一些分辨率。我浏览了许多不同的帖子,所有这些都表明我的纵横比可能是错误的,但我使用了谷歌推荐的AutoFitTextureView和正确的纵横比,但我的预览是拉伸的。我从playstore下载了一些开源的相机应用程序,其中一些也和我的前置摄像头有同样的问题(除了开着的摄像头),但有趣的是,我在另一个设备上使用了相同的应用程序,而且预览是绝对完美的。最后,我决定用不同的分辨率测试我的应用程序,并观察结果,但是我找不到任何模式,有人能帮我理解一下吗?

代码语言:javascript
复制
my device display size is 720x1280
Front camera results: 
SurfaceTexture        AutoFitTextureView         Result
buffer size           size       
2576x1932             720x960                    Normal
2560x1440             720x1280                   Normal
2048x1536             720x960                    Normal
2048x1152             720x1280                   Normal
1920x1920             720x720                    Normal
1920x1080             720x1280                   Normal
1440x1080             720x960                    Horizontally Stretched
1280x720              720x1280                   Horizontally Stretched
1072x1072             720x720                    Normal
960x720               720x960                    Normal
720x480               720x1080                   Horizontally Stretched
640x480               720x960                    Horizontally Stretched
352x288               720x880                    Normal
320x240               720x960                    Normal
256x144               720x1280                   Horizontally Stretched
176x144               720x880                    Normal
EN

回答 2

Stack Overflow用户

发布于 2021-01-29 20:15:10

它们的关键是在您呈现预览的TextureView上设置正确的转换。“纺织品视图”的宽度和高度设置为与其父布局相匹配。

代码语言:javascript
复制
TextureView textureView;

void setTextureTransform(CameraCharacteristics characteristics) {
    Size previewSize = getPreviewSize(characteristics);
    int width = previewSize.getWidth();
    int height = previewSize.getHeight();
    int sensorOrientation = getCameraSensorOrientation(characteristics);
    // Indicate the size of the buffer the texture should expect
    textureView.getSurfaceTexture().setDefaultBufferSize(width, height);
    // Save the texture dimensions in a rectangle
    RectF viewRect = new RectF(0,0, textureView.getWidth(), textureView.getHeight());
    // Determine the rotation of the display
    float rotationDegrees = 0;
    try {
        rotationDegrees = (float)getDisplayRotation();
    } catch (Exception ignored) {
    }
    float w, h;
    if ((sensorOrientation - rotationDegrees) % 180 == 0) {
        w = width;
        h = height;
    } else {
        // Swap the width and height if the sensor orientation and display rotation don't match
        w = height;
        h = width;
    }
    float viewAspectRatio = viewRect.width()/viewRect.height();
    float imageAspectRatio = w/h;
    final PointF scale;
    // This will make the camera frame fill the texture view, if you'd like to fit it into the view swap the "<" sign for ">"
    if (viewAspectRatio < imageAspectRatio) {
        // If the view is "thinner" than the image constrain the height and calculate the scale for the texture width
        scale = new PointF((viewRect.height() / viewRect.width()) * ((float) height / (float) width), 1f);
    } else {
        scale = new PointF(1f, (viewRect.width() / viewRect.height()) * ((float) width / (float) height));
    }
    if (rotationDegrees % 180 != 0) {
        // If we need to rotate the texture 90º we need to adjust the scale
        float multiplier = viewAspectRatio < imageAspectRatio ? w/h : h/w;
        scale.x *= multiplier;
        scale.y *= multiplier;
    }

    Matrix matrix = new Matrix();
    // Set the scale
    matrix.setScale(scale.x, scale.y, viewRect.centerX(), viewRect.centerY());
    if (rotationDegrees != 0) {
        // Set rotation of the device isn't upright
        matrix.postRotate(0 - rotationDegrees, viewRect.centerX(), viewRect.centerY());
    }
    // Transform the texture
    textureView.setTransform(matrix);
}

int getDisplayRotation() {
    switch (textureView.getDisplay().getRotation()) {
        case Surface.ROTATION_0:
        default:
            return 0;
        case Surface.ROTATION_90:
            return  90;
        case Surface.ROTATION_180:
            return  180;
        case Surface.ROTATION_270:
            return 270;
    }
}

Size getPreviewSize(CameraCharacteristics characteristics) {
    StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
    Size[] previewSizes = map.getOutputSizes(SurfaceTexture.class);
    // TODO: decide on which size fits your view size the best
    return previewSizes[0];
}

int getCameraSensorOrientation(CameraCharacteristics characteristics) {
    Integer cameraOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
    return (360 - (cameraOrientation != null ? cameraOrientation : 0)) % 360;
}
票数 3
EN

Stack Overflow用户

发布于 2020-10-05 00:13:22

实际上,这可能是一个设备缺陷-相机实现是从整个传感器的大小不正确地缩放。这种情况通常发生在大多数应用程序不使用的不寻常大小上。

在您的例子中,可能是1440x1080被摄像机管道的某个部分处理得像1920x1080,从而导致拉伸。有时,可以通过添加另一个不同分辨率的输出(例如JPEG)来“修正”(有时甚至添加相同的输出)。

当然,您的代码(或AutoFitTextureView中)仍然可能存在逻辑错误。但这些都很难给出有用的建议,因为--这是一个逐步检查所有布局和缩放数学的问题。

你也可以尝试谷歌的官方相机支持库CameraX。它处于beta版,对于预览、仍然捕获和图像分析等基本用例来说,效果很好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63868197

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档