簡體   English   中英

如何使用渲染腳本將Camera2預覽幀獲取為位圖或OpenCV Mat

[英]How to get Camera2 preview frame as Bitmap or OpenCV Mat with renderscript

我想使用OpenCV進行實時圖像處理,並且想使用Android Camera2 API。 我的問題是將預覽幀轉換為OpenCV Mat(或者首先轉換為位圖也會有所幫助)。

我知道您可以將ImageReader附加到相機並將每個可用的圖像轉換為位圖。 問題在於將ImageReader附加到相機會大大降低幀速率(不是任何圖像轉換,而只是使用ImageReader而沒有任何其他代碼)。 所以我的想法是將Allocation的表面附加到相機,將該Allocation傳遞給ScriptIntrinsicYuvToRGB-Renderscript,然后將輸出Allocation復制到Bitmap中,就像在android-hdf-viewfinder示例中一樣 那就是我到目前為止所嘗試的:

private fun setupRenderscript(){
        rs = RenderScript.create(context)

        val tb1 = Type.Builder(rs, Element.YUV(rs)).setX(size.width).setY(size.height)
        rsInput = Allocation.createTyped(rs, tb1.create(), Allocation.USAGE_IO_INPUT or Allocation.USAGE_SCRIPT)

        bmOut = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888)
        val tb2 = Type.Builder(rs, Element.RGBA_8888(rs)).setX(size.width).setY(size.height)
        rsOutput = Allocation.createTyped(rs, tb2.create(), Allocation.USAGE_SCRIPT)

        yuvToRgbIntrinistic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs))
        yuvToRgbIntrinistic.setInput(rsInput)
    }

private fun createCameraPreviewSession() {
        setupRenderscript()

        val texture = cameraTextureView.surfaceTexture //Normal camera preview surface
        texture.setDefaultBufferSize(size.width, size.height)
        val surface = Surface(texture)

        captureRequestBuilder = cameraDevice?.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
        captureRequestBuilder?.addTarget(surface)
        captureRequestBuilder?.addTarget(rsInput.surface) //Attach Allocation Surface to CaptureRequest
        cameraDevice?.createCaptureSession(Arrays.asList(surface, rsInput.surface), cameraCaptureSession, backgroundHandler)

private val surfaceTextureListener = object : SurfaceTextureListener {
        override fun onSurfaceTextureAvailable(texture: SurfaceTexture?, width: Int, height: Int) {
            openCamera(width, height)
        }

        override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture?, width: Int, heigth: Int) {
            configureTransform(width, heigth)
        }

        override fun onSurfaceTextureUpdated(texture: SurfaceTexture?){
            if (::rsOutput.isInitialized){
                log("Image")
                rsInput.ioReceive()
                yuvToRgbIntrinistic.forEach(rsOutput)
                rsOutput.copyTo(bmOut)
            }
        }

        override fun onSurfaceTextureDestroyed(texture: SurfaceTexture?) = true
    }

相機預覽工作正常,現在引發致命錯誤,但我沒有將預覽作為位圖。 我收到以下日志消息:
對於rsInput.ioReceive()

E/NdkImageReader: acquireImageLocked: Output buffer format: 0x22, ImageReader configured format: 0x1
E/RenderScript: lockNextBuffer: acquire image from reader 0x7427c7d8a0 failed! ret: -10000, img 0x0
E/RenderScript_jni: non fatal RS error, Error receiving IO input buffer.

對於yuvToRgbIntrinistic.forEach(rsOutput)我可能多次獲得相同的消息,可能是每個像素:

E/RenderScript: YuvToRGB executed without data, skipping

因此,似乎無法將數據復制/讀取到輸入分配中,但是我不知道自己在做什么錯。 它的工作方式應類似於上面鏈接的hdr示例。

問題在於,將ImageReader附加到相機會大大降低幀率(不是任何圖像轉換,而只是使用ImageReader而沒有任何其他代碼)

那不應該發生的。 您可能沒有正確配置相機會話和圖像讀取器的輸出目標。 您還需要確保盡快關閉發送到圖像閱讀器的圖像,以便下一幅圖像可以進入。如果您真的很在意性能,則應該使用YUV_420_888作為像素格式,具體取決於輸出目標的大小,3-5幀作為圖像讀取器的緩沖區。 這是一些示例代碼,可幫助您從本博客文章開始改編:

val bufferSize = 3
val imageReader = ImageReader.newInstance(
    // Pick width and height from supported camera output sizes
    width, height, ImageFormat.YUV_420_888, bufferSize)

// Retrieve surface from image reader
val imReaderSurface = imageReader.surface
val targets: MutableList<Surface> = arrayOf(imReaderSurface).toMutableList()

// Create a capture session using the predefined targets
cameraDevice.createCaptureSession(targets, object: CameraCaptureSession.StateCallback() {
    override fun onConfigured(session: CameraCaptureSession) {
        // Submit capture requests here
    }
    // Omitting for brevity...
    override fun onConfigureFailed(session: CameraCaptureSession) = Unit
}, null)

關於RenderScript錯誤,很難說明您提供的詳細信息是怎么回事。 如果您尚未這樣做,我建議您使用RenderScript支持庫 ,並在仿真器中測試代碼以排除潛在的驅動程序實現問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM