diff --git a/app/build.gradle b/app/build.gradle index 6b8633d..ce9214f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,8 +56,9 @@ //基础依赖库 implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.4' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + def androidx_version = '1.6.1' + implementation "androidx.appcompat:appcompat:${androidx_version}" + implementation "com.google.android.material:material:${androidx_version}" implementation 'androidx.cardview:cardview:1.0.0' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' diff --git a/app/build.gradle b/app/build.gradle index 6b8633d..ce9214f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,8 +56,9 @@ //基础依赖库 implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.4' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + def androidx_version = '1.6.1' + implementation "androidx.appcompat:appcompat:${androidx_version}" + implementation "com.google.android.material:material:${androidx_version}" implementation 'androidx.cardview:cardview:1.0.0' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' diff --git a/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt b/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt index dcb946c..a6b13f6 100644 --- a/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt +++ b/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt @@ -1,6 +1,5 @@ package com.casic.br.app.view -import android.annotation.SuppressLint import android.graphics.ImageFormat import android.os.Build import android.os.Bundle @@ -10,11 +9,11 @@ import android.util.Log import android.view.Surface import androidx.camera.core.AspectRatio -import androidx.camera.core.CameraInfo import androidx.camera.core.CameraSelector import androidx.camera.core.CameraState import androidx.camera.core.ImageAnalysis import androidx.camera.core.ImageCapture +import androidx.camera.core.ImageProxy import androidx.camera.core.Preview import androidx.camera.lifecycle.ProcessCameraProvider import androidx.core.content.ContextCompat @@ -25,8 +24,6 @@ import com.casic.br.app.widgets.SelectSceneDialog import com.google.common.util.concurrent.ListenableFuture import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.toBitmap import com.pengxh.kt.lite.utils.WeakReferenceHandler import java.util.concurrent.ExecutionException @@ -39,9 +36,12 @@ class StartCheckActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + private const val RATIO_4_3_VALUE = 4.0 / 3.0 + private const val RATIO_16_9_VALUE = 16.0 / 9.0 + } + private val kTag = "StartCheckActivity" - private val ratio_4_3 = 4.0 / 3.0 - private val ratio_16_9 = 16.0 / 9.0 private val executor = ThreadPoolExecutor( 16, 16, 0L, TimeUnit.MILLISECONDS, @@ -62,8 +62,7 @@ // 检查 CameraProvider 可用性 cameraProviderFuture.addListener({ try { - val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() - bindPreview(cameraProvider) + bindPreview(cameraProviderFuture.get()) } catch (e: ExecutionException) { e.printStackTrace() } catch (e: InterruptedException) { @@ -104,6 +103,7 @@ imageAnalysis = ImageAnalysis.Builder() .setTargetAspectRatio(screenAspectRatio) .setTargetRotation(Surface.ROTATION_0) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() // Must unbind the use-cases before rebinding them @@ -119,41 +119,28 @@ // Attach the viewfinder's surface provider to preview use case cameraPreViewBuilder.setSurfaceProvider(binding.cameraPreView.surfaceProvider) - observeCameraState(camera.cameraInfo) + camera.cameraInfo.cameraState.observe(this) { + //开始预览之后才人脸检测 + if (it.type == CameraState.Type.OPEN) { + imageAnalysis.setAnalyzer(cameraExecutor, faceImageAnalyzer) + } + } } catch (e: Exception) { Log.e(kTag, "Use case binding failed", e) } } - @SuppressLint("UnsafeOptInUsageError") - private fun observeCameraState(cameraInfo: CameraInfo) { - val screenWidth = getScreenWidth() - val screenHeight = getScreenHeight() + @androidx.camera.core.ExperimentalGetImage + private val faceImageAnalyzer = object : ImageAnalysis.Analyzer { + override fun analyze(imageProxy: ImageProxy) { + if (imageProxy.format == ImageFormat.YUV_420_888) { + executor.execute { + val image = imageProxy.image + val bitmap = image?.toBitmap(ImageFormat.YUV_420_888) ?: return@execute + //TODO 开始调用算法检测物品 - cameraInfo.cameraState.observe(this) { cameraState -> - if (cameraState.type == CameraState.Type.OPEN) { - imageAnalysis.setAnalyzer(cameraExecutor) { imageProxy -> - /** - * CameraX 可通过 setOutputImageFormat(int) 支持 YUV_420_888 和 RGBA_8888。默认格式为 YUV_420_888 - * - * NV12是iOS中有的模式,它的存储顺序是先存Y分量,再YV进行交替存储。 - * NV21是Android中有的模式,它的存储顺序是先存Y分量,再VU交替存储。 - * NV12和NV21格式都属于YUV420SP类型 - */ - if (imageProxy.format == ImageFormat.YUV_420_888) { - executor.execute { - val image = imageProxy.image - val bitmap = image?.toBitmap(ImageFormat.YUV_420_888) ?: return@execute - - val widthRatio = screenWidth / bitmap.width.toFloat() - val heightRatio = screenHeight / bitmap.height.toFloat() - Log.d(kTag, "observeCameraState => [${widthRatio},${heightRatio}]") - //TODO 开始调用算法检测物品 - - //检测完之后close就会继续生成下一帧图片,否则就会被阻塞不会继续生成下一帧 - imageProxy.close() - } - } + //检测完之后close就会继续生成下一帧图片,否则就会被阻塞不会继续生成下一帧 + imageProxy.close() } } } @@ -223,7 +210,7 @@ private fun aspectRatio(width: Int, height: Int): Int { val ratio = width.coerceAtLeast(height).toDouble() / width.coerceAtMost(height) - return if (abs(ratio - ratio_4_3) <= abs(ratio - ratio_16_9) + return if (abs(ratio - RATIO_4_3_VALUE) <= abs(ratio - RATIO_16_9_VALUE) ) { AspectRatio.RATIO_4_3 } else AspectRatio.RATIO_16_9 diff --git a/app/build.gradle b/app/build.gradle index 6b8633d..ce9214f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,8 +56,9 @@ //基础依赖库 implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.4' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + def androidx_version = '1.6.1' + implementation "androidx.appcompat:appcompat:${androidx_version}" + implementation "com.google.android.material:material:${androidx_version}" implementation 'androidx.cardview:cardview:1.0.0' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' diff --git a/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt b/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt index dcb946c..a6b13f6 100644 --- a/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt +++ b/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt @@ -1,6 +1,5 @@ package com.casic.br.app.view -import android.annotation.SuppressLint import android.graphics.ImageFormat import android.os.Build import android.os.Bundle @@ -10,11 +9,11 @@ import android.util.Log import android.view.Surface import androidx.camera.core.AspectRatio -import androidx.camera.core.CameraInfo import androidx.camera.core.CameraSelector import androidx.camera.core.CameraState import androidx.camera.core.ImageAnalysis import androidx.camera.core.ImageCapture +import androidx.camera.core.ImageProxy import androidx.camera.core.Preview import androidx.camera.lifecycle.ProcessCameraProvider import androidx.core.content.ContextCompat @@ -25,8 +24,6 @@ import com.casic.br.app.widgets.SelectSceneDialog import com.google.common.util.concurrent.ListenableFuture import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.toBitmap import com.pengxh.kt.lite.utils.WeakReferenceHandler import java.util.concurrent.ExecutionException @@ -39,9 +36,12 @@ class StartCheckActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + private const val RATIO_4_3_VALUE = 4.0 / 3.0 + private const val RATIO_16_9_VALUE = 16.0 / 9.0 + } + private val kTag = "StartCheckActivity" - private val ratio_4_3 = 4.0 / 3.0 - private val ratio_16_9 = 16.0 / 9.0 private val executor = ThreadPoolExecutor( 16, 16, 0L, TimeUnit.MILLISECONDS, @@ -62,8 +62,7 @@ // 检查 CameraProvider 可用性 cameraProviderFuture.addListener({ try { - val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() - bindPreview(cameraProvider) + bindPreview(cameraProviderFuture.get()) } catch (e: ExecutionException) { e.printStackTrace() } catch (e: InterruptedException) { @@ -104,6 +103,7 @@ imageAnalysis = ImageAnalysis.Builder() .setTargetAspectRatio(screenAspectRatio) .setTargetRotation(Surface.ROTATION_0) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() // Must unbind the use-cases before rebinding them @@ -119,41 +119,28 @@ // Attach the viewfinder's surface provider to preview use case cameraPreViewBuilder.setSurfaceProvider(binding.cameraPreView.surfaceProvider) - observeCameraState(camera.cameraInfo) + camera.cameraInfo.cameraState.observe(this) { + //开始预览之后才人脸检测 + if (it.type == CameraState.Type.OPEN) { + imageAnalysis.setAnalyzer(cameraExecutor, faceImageAnalyzer) + } + } } catch (e: Exception) { Log.e(kTag, "Use case binding failed", e) } } - @SuppressLint("UnsafeOptInUsageError") - private fun observeCameraState(cameraInfo: CameraInfo) { - val screenWidth = getScreenWidth() - val screenHeight = getScreenHeight() + @androidx.camera.core.ExperimentalGetImage + private val faceImageAnalyzer = object : ImageAnalysis.Analyzer { + override fun analyze(imageProxy: ImageProxy) { + if (imageProxy.format == ImageFormat.YUV_420_888) { + executor.execute { + val image = imageProxy.image + val bitmap = image?.toBitmap(ImageFormat.YUV_420_888) ?: return@execute + //TODO 开始调用算法检测物品 - cameraInfo.cameraState.observe(this) { cameraState -> - if (cameraState.type == CameraState.Type.OPEN) { - imageAnalysis.setAnalyzer(cameraExecutor) { imageProxy -> - /** - * CameraX 可通过 setOutputImageFormat(int) 支持 YUV_420_888 和 RGBA_8888。默认格式为 YUV_420_888 - * - * NV12是iOS中有的模式,它的存储顺序是先存Y分量,再YV进行交替存储。 - * NV21是Android中有的模式,它的存储顺序是先存Y分量,再VU交替存储。 - * NV12和NV21格式都属于YUV420SP类型 - */ - if (imageProxy.format == ImageFormat.YUV_420_888) { - executor.execute { - val image = imageProxy.image - val bitmap = image?.toBitmap(ImageFormat.YUV_420_888) ?: return@execute - - val widthRatio = screenWidth / bitmap.width.toFloat() - val heightRatio = screenHeight / bitmap.height.toFloat() - Log.d(kTag, "observeCameraState => [${widthRatio},${heightRatio}]") - //TODO 开始调用算法检测物品 - - //检测完之后close就会继续生成下一帧图片,否则就会被阻塞不会继续生成下一帧 - imageProxy.close() - } - } + //检测完之后close就会继续生成下一帧图片,否则就会被阻塞不会继续生成下一帧 + imageProxy.close() } } } @@ -223,7 +210,7 @@ private fun aspectRatio(width: Int, height: Int): Int { val ratio = width.coerceAtLeast(height).toDouble() / width.coerceAtMost(height) - return if (abs(ratio - ratio_4_3) <= abs(ratio - ratio_16_9) + return if (abs(ratio - RATIO_4_3_VALUE) <= abs(ratio - RATIO_16_9_VALUE) ) { AspectRatio.RATIO_4_3 } else AspectRatio.RATIO_16_9 diff --git a/app/src/main/res/layout/activity_start_check.xml b/app/src/main/res/layout/activity_start_check.xml index 331effa..4c0e897 100644 --- a/app/src/main/res/layout/activity_start_check.xml +++ b/app/src/main/res/layout/activity_start_check.xml @@ -22,7 +22,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" - android:text="正在识别中..." + android:text="场景识别中..." android:textColor="@color/white" android:textSize="@dimen/sp_18" android:textStyle="bold" /> diff --git a/app/build.gradle b/app/build.gradle index 6b8633d..ce9214f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,8 +56,9 @@ //基础依赖库 implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.4' implementation 'androidx.core:core-ktx:1.9.0' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' + def androidx_version = '1.6.1' + implementation "androidx.appcompat:appcompat:${androidx_version}" + implementation "com.google.android.material:material:${androidx_version}" implementation 'androidx.cardview:cardview:1.0.0' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' diff --git a/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt b/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt index dcb946c..a6b13f6 100644 --- a/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt +++ b/app/src/main/java/com/casic/br/app/view/StartCheckActivity.kt @@ -1,6 +1,5 @@ package com.casic.br.app.view -import android.annotation.SuppressLint import android.graphics.ImageFormat import android.os.Build import android.os.Bundle @@ -10,11 +9,11 @@ import android.util.Log import android.view.Surface import androidx.camera.core.AspectRatio -import androidx.camera.core.CameraInfo import androidx.camera.core.CameraSelector import androidx.camera.core.CameraState import androidx.camera.core.ImageAnalysis import androidx.camera.core.ImageCapture +import androidx.camera.core.ImageProxy import androidx.camera.core.Preview import androidx.camera.lifecycle.ProcessCameraProvider import androidx.core.content.ContextCompat @@ -25,8 +24,6 @@ import com.casic.br.app.widgets.SelectSceneDialog import com.google.common.util.concurrent.ListenableFuture import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.toBitmap import com.pengxh.kt.lite.utils.WeakReferenceHandler import java.util.concurrent.ExecutionException @@ -39,9 +36,12 @@ class StartCheckActivity : KotlinBaseActivity(), Handler.Callback { + companion object { + private const val RATIO_4_3_VALUE = 4.0 / 3.0 + private const val RATIO_16_9_VALUE = 16.0 / 9.0 + } + private val kTag = "StartCheckActivity" - private val ratio_4_3 = 4.0 / 3.0 - private val ratio_16_9 = 16.0 / 9.0 private val executor = ThreadPoolExecutor( 16, 16, 0L, TimeUnit.MILLISECONDS, @@ -62,8 +62,7 @@ // 检查 CameraProvider 可用性 cameraProviderFuture.addListener({ try { - val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() - bindPreview(cameraProvider) + bindPreview(cameraProviderFuture.get()) } catch (e: ExecutionException) { e.printStackTrace() } catch (e: InterruptedException) { @@ -104,6 +103,7 @@ imageAnalysis = ImageAnalysis.Builder() .setTargetAspectRatio(screenAspectRatio) .setTargetRotation(Surface.ROTATION_0) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() // Must unbind the use-cases before rebinding them @@ -119,41 +119,28 @@ // Attach the viewfinder's surface provider to preview use case cameraPreViewBuilder.setSurfaceProvider(binding.cameraPreView.surfaceProvider) - observeCameraState(camera.cameraInfo) + camera.cameraInfo.cameraState.observe(this) { + //开始预览之后才人脸检测 + if (it.type == CameraState.Type.OPEN) { + imageAnalysis.setAnalyzer(cameraExecutor, faceImageAnalyzer) + } + } } catch (e: Exception) { Log.e(kTag, "Use case binding failed", e) } } - @SuppressLint("UnsafeOptInUsageError") - private fun observeCameraState(cameraInfo: CameraInfo) { - val screenWidth = getScreenWidth() - val screenHeight = getScreenHeight() + @androidx.camera.core.ExperimentalGetImage + private val faceImageAnalyzer = object : ImageAnalysis.Analyzer { + override fun analyze(imageProxy: ImageProxy) { + if (imageProxy.format == ImageFormat.YUV_420_888) { + executor.execute { + val image = imageProxy.image + val bitmap = image?.toBitmap(ImageFormat.YUV_420_888) ?: return@execute + //TODO 开始调用算法检测物品 - cameraInfo.cameraState.observe(this) { cameraState -> - if (cameraState.type == CameraState.Type.OPEN) { - imageAnalysis.setAnalyzer(cameraExecutor) { imageProxy -> - /** - * CameraX 可通过 setOutputImageFormat(int) 支持 YUV_420_888 和 RGBA_8888。默认格式为 YUV_420_888 - * - * NV12是iOS中有的模式,它的存储顺序是先存Y分量,再YV进行交替存储。 - * NV21是Android中有的模式,它的存储顺序是先存Y分量,再VU交替存储。 - * NV12和NV21格式都属于YUV420SP类型 - */ - if (imageProxy.format == ImageFormat.YUV_420_888) { - executor.execute { - val image = imageProxy.image - val bitmap = image?.toBitmap(ImageFormat.YUV_420_888) ?: return@execute - - val widthRatio = screenWidth / bitmap.width.toFloat() - val heightRatio = screenHeight / bitmap.height.toFloat() - Log.d(kTag, "observeCameraState => [${widthRatio},${heightRatio}]") - //TODO 开始调用算法检测物品 - - //检测完之后close就会继续生成下一帧图片,否则就会被阻塞不会继续生成下一帧 - imageProxy.close() - } - } + //检测完之后close就会继续生成下一帧图片,否则就会被阻塞不会继续生成下一帧 + imageProxy.close() } } } @@ -223,7 +210,7 @@ private fun aspectRatio(width: Int, height: Int): Int { val ratio = width.coerceAtLeast(height).toDouble() / width.coerceAtMost(height) - return if (abs(ratio - ratio_4_3) <= abs(ratio - ratio_16_9) + return if (abs(ratio - RATIO_4_3_VALUE) <= abs(ratio - RATIO_16_9_VALUE) ) { AspectRatio.RATIO_4_3 } else AspectRatio.RATIO_16_9 diff --git a/app/src/main/res/layout/activity_start_check.xml b/app/src/main/res/layout/activity_start_check.xml index 331effa..4c0e897 100644 --- a/app/src/main/res/layout/activity_start_check.xml +++ b/app/src/main/res/layout/activity_start_check.xml @@ -22,7 +22,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" - android:text="正在识别中..." + android:text="场景识别中..." android:textColor="@color/white" android:textSize="@dimen/sp_18" android:textStyle="bold" /> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 48f34ce..e0a4aed 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,9 +1,7 @@ - - -