我到目前为止已经试过的有效模糊:相机预览
转换每一帧转换成位图,与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。模糊叠加也是旋转的,但这是另一个问题。
我创建test project on Github在那里你可以迅速重现问题并检查它如何可以优化。期待您的想法。
UPD 我是能够提高性能与模糊之前缩小输入日期。我推动这些更改来测试回购。即使在低端设备上,但具有低分辨率(例如HD),在FHD和UHD上的性能也不错((8-12 FPS)。
你试过分析应用程序? – Xiao
你的意思是Android Studio的分析器? – Divers
是否有一个特别的原因,你为什么要用''ImageFormat.NV_21'''来处理yuv'''byte'''而不直接从相机中获取预览帧?使用USAGE_IO_INPUT和ImageFormat.YUV_420_888可以将相机2预览帧直接用于yuv分配。你将不得不切换到本地rs,但它应该没问题,因为你有minApi 19.如果那是好的,那么我认为我有一个解决方案。 –