web-dev-qa-db-ja.com

カメラプレビューの効果的なぼかし

私がこれまでに試したこと:


すべてのフレームをビットマップに変換し、 library でぼかして、カメラプレビューの前にあるImageViewに入れます。明らかに遅すぎました-1 fpsのようなものです。


次に、すべてのフレームをぼかすRenderScriptを使い始めました。処理の結果は、カバーカメラのプレビューであるTextureViewに配置する必要があります。

そのアプローチのコードの本質的な平和:

BlurFilter

ScriptIntrinsicBlur.create(rs, Element.RGBA_8888(rs)).apply {
    setRadius(BLUR_RADIUS)
}
private val yuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(rs))
private var surface: SurfaceTexture? = null

private fun setupSurface() {
    if (surface != null) {
        aBlurOut?.surface = Surface(surface)
    }
}

fun reset(width: Int, height: Int) {
    aBlurOut?.destroy()

    this.width = width
    this.height = height

    val tbConvIn = Type.Builder(rs, Element.U8(rs))
            .setX(width)
            .setY(height)
            .setYuvFormat(Android.graphics.ImageFormat.NV21)
    aConvIn = Allocation.createTyped(rs, tbConvIn.create(), Allocation.USAGE_SCRIPT)

    val tbConvOut = Type.Builder(rs, Element.RGBA_8888(rs))
            .setX(width)
            .setY(height)
    aConvOut = Allocation.createTyped(rs, tbConvOut.create(), Allocation.USAGE_SCRIPT)

    val tbBlurOut = Type.Builder(rs, Element.RGBA_8888(rs))
            .setX(width)
            .setY(height)
    aBlurOut = Allocation.createTyped(rs, tbBlurOut.create(),
            Allocation.USAGE_SCRIPT or Allocation.USAGE_IO_OUTPUT)

    setupSurface()
}

fun execute(yuv: ByteArray) {
    if (surface != null) {
        //YUV -> RGB
        aConvIn!!.copyFrom(yuv)
        yuvToRgb.setInput(aConvIn)
        yuvToRgb.forEach(aConvOut)
        //RGB -> BLURED RGB
        blurRc.setInput(aConvOut)
        blurRc.forEach(aBlurOut)
        aBlurOut!!.ioSend()
    }
}

MainActivity

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    initQrScanner()
}

override fun onStart() {
    super.onStart()
    fotoapparat.start()
}

override fun onStop() {
    fotoapparat.stop()
    super.onStop()
}

private fun initQrScanner() {
    val filter = BlurFilter(RenderScript.create(this))
    tvWholeOverlay.surfaceTextureListener = filter

    fotoapparat = Fotoapparat
            .with(this)
            .into(cvQrScanner)
            .frameProcessor({
                if (it.size.width != filter.width || it.size.height != filter.height) {
                    filter.reset(it.size.width, it.size.height)
                }
                filter.execute(it.image)
            })
            .build()
}

activity_main.xml

<Android.support.constraint.ConstraintLayout 
xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context="com.blur.andrey.blurtest.MainActivity">

    <io.fotoapparat.view.CameraView
        Android:id="@+id/cvQrScanner"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent" />

    <TextureView
        Android:id="@+id/tvWholeOverlay"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</Android.support.constraint.ConstraintLayout>

そして残念ながら、それでも遅くなります-3-4 FPS。ぼかしオーバーレイも回転しますが、それは別の問題です。


私はGithubでのテストプロジェクトを作成しました。ここでは、問題をすばやく再現し、最適化の方法を確認できます。あなたのアイデアを楽しみにしています。


[〜#〜] upd [〜#〜]ぼかす前に入力日を縮小することで、パフォーマンスを向上させることができました。これらの変更をテストリポジトリにプッシュしました。今、私はローエンドのデバイスでも本当に良い(15-20 FPS)パフォーマンスを持っていますが、低解像度(たとえばHD)であり、十分ではありませんFHDおよびUHD((8-12 FPS)

10
Divers

CameraViewTextureViewに置き換えて、カメラのプレビューとして使用するのが最善の方法だと思います。ここでそれを行う方法の例を簡単に見つけることができます https://developer.Android.com/reference/Android/view/TextureView.html 、そしてここ https://github.com /dalinaum/TextureViewDemo/blob/master/src/kr/gdg/Android/textureview/CameraActivity.Java

次のステップは、TextureViewでぼかしシェーダーを使用することです。ここで例を見つけることができます: https://github.com/nekocode/blur-using-textureview/blob/master/app/src/main/Java/cn/nekocode/blurringview/sample/BlurFilter.Java

このシェーダーを使用するか、見栄えの良いシェーダーを見つけることができます。

すぐに使用できるソリューションが必要な場合は、次のライブラリをご覧ください: https://github.com/krazykira/VidEffects

これにより、シェーダーをビデオビューに適用できるため、ぼかしシェーダーを使用して目的の効果を実現できます。

このライブラリの例: https://stackoverflow.com/a/38125734/3286059

[〜#〜]編集[〜#〜]

そこで、Nekocodeから素晴らしいライブラリをフォークし、機能するぼかしフィルターを追加しました。私の最新のコミットをご覧ください。 https://github.com/Dimezis/CameraFilter

私が言ったように、TextureView + GLシェーダー。ブラーシェーダーを有効にするには、右上隅のメニューをクリックして、対応するオプションを選択します。

より速く/より良く/よりシンプルなブラーシェーダーが必要な場合は、 https://www.shadertoy.com で検索できます。

一部のデバイスでは、カメラのプレビューが反転する場合がありますが、それは解決すべきもう1つの問題です。

9
Dimezis