如何让 CameraX 预览在拍照时冻结?

2024-04-04

我的自定义 CameraX 流程如下:

  • 打开相机预览(实时)
  • 点击按钮拍照
  • 单击该按钮时有一个过程(将路径转换为位图、旋转图像、自动裁剪图像、保存到设备中)
  • 运行所有进程并成功后,将图像发送到其他Fragment并将其显示为glide

问题是何时running all the process (in step 3) have a delayed 2 seconds并且相机预览仍然live (not freeze or lock)。怎么做camera preview freeze or lock when running the process?

这是我在 Camera X 中运行相机预览的代码:

class CameraFragment : Fragment() {

        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_camera, container, false)
        }

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)

            viewFinder.post { setupCamera() }
        }

        private fun setupCamera() {
            CameraX.unbindAll()
            CameraX.bindToLifecycle(
                this,
                buildPreviewUseCase(),
                buildImageCaptureUseCase()
            )
        }

        private fun buildPreviewUseCase(): Preview {
            val preview = Preview(
                UseCaseConfigBuilder.buildPreviewConfig(
                    viewFinder.display
                )
            )
            preview.setOnPreviewOutputUpdateListener { previewOutput ->
                updateViewFinderWithPreview(previewOutput)
                correctPreviewOutputForDisplay(previewOutput.textureSize)
            }
            return preview
        }

        private fun buildImageCaptureUseCase(): ImageCapture {
            val capture = ImageCapture(
                UseCaseConfigBuilder.buildImageCaptureConfig(
                    viewFinder.display
                )
            )
            cameraCaptureImageButton.setOnClickListener {
                capture.takePicture(
                    FileCreator.createTempFile(JPEG_FORMAT),
                    Executors.newSingleThreadExecutor(),
                    object : ImageCapture.OnImageSavedListener {
                        override fun onImageSaved(file: File) {
                            // I want make a freeze camera preview when execute this before launch *launchGalleryFragment(path)*
                            val bitmap = BitmapFactory.decodeFile(file.absolutePath)
                            val rotatedBitmap = bitmap.rotate(90)
                            val croppedImage = cropImage(rotatedBitmap, viewFinder, rectangle)
                            val path = saveImage(croppedImage)
                            requireActivity().runOnUiThread {
                                launchGalleryFragment(path)
                            }
                        }

                        override fun onError(
                            imageCaptureError: ImageCapture.ImageCaptureError,
                            message: String,
                            cause: Throwable?
                        ) {
                            Toast.makeText(requireContext(), "Error: $message", Toast.LENGTH_LONG)
                                .show()
                            Log.e("CameraFragment", "Capture error $imageCaptureError: $message", cause)
                        }
                    })
            }
            return capture
        }

        private fun launchGalleryFragment(path: String) {
            val action = CameraFragmentDirections.actionLaunchGalleryFragment(path)
            findNavController().navigate(action)
        }

    }

也许您可以尝试解除预览用例的绑定:

版本1.0.0-alpha06:CameraX.unbind(preview);

版本 > 1.0.0-alpha07:cameraProvider.unbind(preview);

在您的情况下,您需要将预览用例保存到变量中,然后取消绑定:

// Declare the preview use case variable (as in the CameraXBasic example)
private var preview: Preview? = null

然后实例化变量(就像你所做的那样):

private fun buildPreviewUseCase(): Preview {
    preview = Preview(
        UseCaseConfigBuilder.buildPreviewConfig(
            viewFinder.display
        )
    )
    preview.setOnPreviewOutputUpdateListener { previewOutput ->
        updateViewFinderWithPreview(previewOutput)
        correctPreviewOutputForDisplay(previewOutput.textureSize)
    }
    return preview
}

然后,当您想要冻结预览时,只需取消绑定用例即可:

CameraX.unbind(preview);

EDIT正如@Billda 在这篇文章中所说: :

要冻结预览,您不应取消预览用例的绑定。也许有 将来会使用 API,但目前推荐的方法是 存储来自 ImageAnalysis 的最新帧并将其放入 ImageView 重叠预览。

因此,我决定更新我的答案,提供另一个使用 ImageAnalysis 实现分析器的解决方案(1.0.0-beta02)。

1- 创建 FreezeAnalyzer 类:

class FreezeAnalyzer(private val callback: FreezeCallback) : ImageAnalysis.Analyzer {
    private var flag = false

    override fun analyze(image: ImageProxy) {
        if(flag){
            flag = false
            val bitmap = toBitmap(image)
            callback.onLastFrameCaptured(bitmap)
        }
        image.close()
    }

    fun freeze(){
        flag = true
    }

    private fun toBitmap(image: ImageProxy): Bitmap {
        // Convert the imageProxy to Bitmap
        // ref https://stackoverflow.com/questions/56772967/converting-imageproxy-to-bitmap
        // ISSUE, on my android 7 when converting the imageProxy to Bitmap I have a problem with the colors...
        var bitmap = ...

        // Rotate the bitmap
        val rotationDegrees = image.imageInfo.rotationDegrees.toFloat()
        if (rotationDegrees != 0f) {
            val matrix = Matrix()
            matrix.postRotate(rotationDegrees)
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
        }
        return bitmap
    }
}

2- XML

<androidx.camera.view.PreviewView
    android:id="@+id/preview_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
<ImageView
    android:id="@+id/image_view"
    android:visibility="invisible"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

3-初始化图像分析器

val resolutionSize = Size(preview_view.width, preview_view.height)

// Set up analyser
imageAnalysis = ImageAnalysis.Builder().apply {
    setTargetResolution(resolutionSize)
    setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
}.build()

val analyzer = FreezeAnalyzer(object : FreezeCallback {
    override fun onLastFrameCaptured(bitmap: Bitmap) {
        runOnUiThread {
            preview_view.visibility = View.INVISIBLE
            image_view.visibility = View.VISIBLE
            image_view.setImageBitmap(bitmap)
        }
    }
})
imageAnalysis.setAnalyzer(executor, analyzer)

4- 绑定 imageAnalysis 用例

try {
    val camera = cameraProvider.bindToLifecycle(
        this,
        cameraSelector,
        preview,
        imageAnalysis,
        imageCapture
    )
    preview.setSurfaceProvider(preview_view.createSurfaceProvider(camera.cameraInfo))
}

5-拍摄照片

btn_capture.setOnClickListener {
    file = File(externalMediaDirs.first(), "${System.currentTimeMillis()}.jpg")
    val outputFileOptions: ImageCapture.OutputFileOptions =
        ImageCapture.OutputFileOptions.Builder(file!!).build()
    analyzer.freeze()
    imageCapture.takePicture(outputFileOptions, executor, onImageSavedCallback)
}

6-释放

btn_release.setOnClickListener {
    preview_view.visibility = View.VISIBLE
    image_view.visibility = View.INVISIBLE
}

我希望它有所帮助,我不是专家,所以如果您有一些改进,欢迎您!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让 CameraX 预览在拍照时冻结? 的相关文章

随机推荐

  • 在Azure函数中设置cors标头

    在我的 Azure 函数中 我尝试设置 cors 标头 var response req CreateResponse HttpStatusCode OK response Content new ObjectContent
  • 使用返回 Future 的函数映射 Stream

    有时我发现自己处于这样的境地 Stream X and a function X gt Future Y 我想组合成一个Future Stream Y 而且我似乎找不到办法做到这一点 例如 我有 val x 1 until 10 toStr
  • 如何删除 Apache Mesos 中的孤立任务?

    该问题可能是由 Mesos 和 Marathon 引起的不同步 https github com mesosphere marathon issues 616 但是 GitHub 上提到的解决方案对我不起作用 当我发现孤立任务时 我所做的是
  • 构建成功时 Eclipse (CDT) 中出现可疑错误消息

    使用面向 C C Linux 开发人员的 Eclipse IDE 版本 Indigo释放 与克 4 1 2 on 科学 Linux CERN 5 RHEL 5 我目前正在开发一个项目 其中使用Qt4GUI 以及 Apache 的log4cx
  • Android应用程序架构——MVVM还是MVC?

    我有一个正在开始处理的 android 项目 我希望它的结构尽可能健壮 我有 WPF MVVM 背景 并且阅读了一些有关 Android 应用程序架构的内容 但我找不到关于我应该使用哪种架构的直接明确的答案 有些人建议使用 MVVM htt
  • 如何在 JavaScript 中使用五位数长的 Unicode 字符

    在 JavaScript 中我可以这样做 foo u2669 1 4 note 但我不能这样做 foo u1D15D full note five hex digits 它将被解释为 u1D15 后跟 D 有没有解决方法 2012 年 7
  • Android 在自定义项目上应用主题

    我可以声明一个主题和一个特定的按钮设计 问题是这种样式适用于所有按钮 我想声明一个具有自己风格的特定按钮 独立于其他按钮更改每个主题 类似于 保存 按钮 任何想法 我尝试了以下方法
  • 查看 Windows 上进程的打开文件处理程序

    我想查看 Windows 上进程的打开文件处理程序 以验证读取了正确的配置文件 ProcMon 和其他工具显示引用的模块 dll 我需要查看所有文件 例如 xml txt 等 的打开文件句柄 流程浏览器 http technet micro
  • pyfacebook 中是否存在 Graph Api 模块

    我已经安装了 pyfacebook 以及 python sdk 即使我收到如下错误 使用此代码时 import facebook token my token graph facebook GraphAPI token profile gr
  • 如何将Android应用程序的方向锁定为手机中的纵向和平板电脑中的横向?

    我正在开发一个 Android 应用程序 当用户旋转设备时 我不希望其方向更改为横向模式 另外 我希望锁定方向在手机上为纵向模式 在平板电脑上为横向模式 这可以实现吗 如果可以 如何实现 谢谢 您只需在以下内容中定义以下属性activity
  • 为什么 C++ 需要通过标头或语句进行前向声明,而 Java 不需要? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如果你不转发声明你的函数 Java 不会抱怨 而 C 会抱怨 我知道 C 涉及预处理 但我想了解更多 目标文件 Java 编译器依赖于
  • 替代嵌套在另一个表单中的 Ajax 上传表单

    我有一个 HTML 表单来编辑我工作地点的数据库系统中人员的详细信息 表单的一部分允许用户上传该人的照片 然而 这给我带来了麻烦 因为我试图让用户上传图片并在提交要保存的人员详细信息之前看到它已成功上传 从而使表单更加 Ajax y 给我带
  • 如何将 SketchUp 模型导出到 Three.js?

    我通过谷歌创建了一个模型SketchUp 我想将其导出到three js节省一些时间 因为我想使用SketchUp比three js 那么有人可以告诉我该怎么做吗 非常感谢 您可以从 SketcUp 导出 collada DAE 然后使用
  • 移动包含子模块的 git 工作副本

    Git 最近的一项变化改变了 git使用子模块时处理目录 而不是拥有一个 git每个子模块 现在所有内容都位于 根级别 git目录 与包括子模块的工作副本相对应的目录 然后 在每个子模块中 创建一个文件 该文件指向该子模块的新位置 git目
  • 如何在kivy项目中隐藏python代码文件和其他相关文件

    我最近在 Google Play 上发布了一个用 Python Kivy 编写的 Android 应用程序 通常 build py 脚本会将整个项目文件包装到一个文件夹中 即应用程序包文件夹 但是 如果我在安装 apk 后检查手机上这个包的
  • 为什么我们需要 crossCheckMatching 功能?

    我正在阅读很多使用特征提取 sift ecc 进行对象检测的文章 在计算两个图像上的描述符后 为了获得良好的匹配 他们使用了 crossCheckMatching 发现于样本 cpp descritpor extractor matcher
  • 如何在角度6中实现内容显示更多和显示更少

    我们有 6 个内容分区 我们还使用字符限制每个 div 我们使用 Bootstrap 4 Angular 6 版本 6 div 一些切换 div 内容打开 一些关闭 https i stack imgur com dS04r jpg这个案例
  • 如何在 AppKit 上的自定义 SwiftUI 表单中右对齐项目标签?

    我有以下可可形式 struct Canvas PreviewProvider static var previews some View VStack HStack alignment firstTextBaseline Text Endp
  • 如何访问React路由器中的历史堆栈?

    我正在尝试访问反应路由器的历史堆栈 这是我想做的 我使用react js 和react router 创建一个板 如果用户单击板上的列表之一 则会转到详细信息页面 假设用户点击列表中 id 为 3 的文章 react router 会转到
  • 如何让 CameraX 预览在拍照时冻结?

    我的自定义 CameraX 流程如下 打开相机预览 实时 点击按钮拍照 单击该按钮时有一个过程 将路径转换为位图 旋转图像 自动裁剪图像 保存到设备中 运行所有进程并成功后 将图像发送到其他Fragment并将其显示为glide 问题是何时