react-native-vision-camera-spoof-detector 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/android/.cxx/Debug/2a1it684/arm64-v8a/.cmake/api/v1/reply/{codemodel-v2-390962e2784a6a84fa3e.json → codemodel-v2-83ca4b3bde3a78057c1f.json} +2 -2
  2. package/android/.cxx/Debug/2a1it684/arm64-v8a/.cmake/api/v1/reply/{index-2025-11-25T14-48-56-0722.json → index-2025-11-27T05-30-44-0002.json} +2 -2
  3. package/android/.cxx/Debug/2a1it684/arm64-v8a/.cmake/api/v1/reply/{target-yuv-Debug-1e27b8a2bdcddd47b87d.json → target-yuv-Debug-a4349d98b162d7b162c2.json} +2 -2
  4. package/android/.cxx/Debug/2a1it684/arm64-v8a/.cmake/api/v1/reply/{target-yuv_shared-Debug-ac9194487d1fc1268a87.json → target-yuv_shared-Debug-f13b6c904c5f79494e23.json} +2 -2
  5. package/android/.cxx/Debug/2a1it684/arm64-v8a/.ninja_deps +0 -0
  6. package/android/.cxx/Debug/2a1it684/arm64-v8a/.ninja_log +125 -125
  7. package/android/.cxx/Debug/2a1it684/arm64-v8a/CMakeFiles/CMakeOutput.log +22 -22
  8. package/android/.cxx/Debug/2a1it684/arm64-v8a/configure_fingerprint.bin +15 -15
  9. package/android/.cxx/Debug/2a1it684/armeabi-v7a/.ninja_deps +0 -0
  10. package/android/.cxx/Debug/2a1it684/armeabi-v7a/.ninja_log +119 -117
  11. package/android/.cxx/Debug/2a1it684/armeabi-v7a/CMakeFiles/CMakeOutput.log +20 -20
  12. package/android/.cxx/Debug/2a1it684/armeabi-v7a/configure_fingerprint.bin +15 -15
  13. package/android/.cxx/Debug/2a1it684/x86/.ninja_deps +0 -0
  14. package/android/.cxx/Debug/2a1it684/x86/.ninja_log +111 -109
  15. package/android/.cxx/Debug/2a1it684/x86/CMakeFiles/CMakeOutput.log +20 -20
  16. package/android/.cxx/Debug/2a1it684/x86/configure_fingerprint.bin +15 -15
  17. package/android/.cxx/Debug/2a1it684/x86_64/.ninja_deps +0 -0
  18. package/android/.cxx/Debug/2a1it684/x86_64/.ninja_log +109 -109
  19. package/android/.cxx/Debug/2a1it684/x86_64/CMakeFiles/CMakeOutput.log +20 -20
  20. package/android/.cxx/Debug/2a1it684/x86_64/configure_fingerprint.bin +15 -15
  21. package/android/build/.transforms/4ebf3dd0dca4f83fe1776360e21ded81/transformed/classes/classes_dex/classes.dex +0 -0
  22. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/AcceleratorConfig.dex +0 -0
  23. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/AntiSpoofingResult.dex +0 -0
  24. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/FaceAntiSpoofingAdvanced$Companion.dex +0 -0
  25. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/FaceAntiSpoofingAdvanced$EnvironmentAssessment.dex +0 -0
  26. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/FaceAntiSpoofingAdvanced$SpoofDetectionResult.dex +0 -0
  27. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/FaceAntiSpoofingAdvanced.dex +0 -0
  28. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/ImageFormatEncoder$ImageFormat.dex +0 -0
  29. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/ImageFormatEncoder.dex +0 -0
  30. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/YuvToFloatArrayConverter$Companion.dex +0 -0
  31. package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/YuvToFloatArrayConverter.dex +0 -0
  32. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  33. package/android/build/intermediates/cxx/Debug/2a1it684/logs/arm64-v8a/build_stdout_targets.txt +59 -59
  34. package/android/build/intermediates/cxx/Debug/2a1it684/logs/arm64-v8a/generate_cxx_metadata_947_timing.txt +9 -0
  35. package/android/build/intermediates/cxx/Debug/2a1it684/logs/armeabi-v7a/build_stdout_targets.txt +52 -52
  36. package/android/build/intermediates/cxx/Debug/2a1it684/logs/armeabi-v7a/{generate_cxx_metadata_455_timing.txt → generate_cxx_metadata_944_timing.txt} +1 -1
  37. package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86/build_stdout_targets.txt +36 -36
  38. package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86/{generate_cxx_metadata_455_timing.txt → generate_cxx_metadata_944_timing.txt} +1 -1
  39. package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86_64/build_stdout_targets.txt +41 -41
  40. package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86_64/generate_cxx_metadata_944_timing.txt +9 -0
  41. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  42. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/AcceleratorConfig.class +0 -0
  43. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/AntiSpoofingResult.class +0 -0
  44. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/FaceAntiSpoofingAdvanced$Companion.class +0 -0
  45. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/FaceAntiSpoofingAdvanced$EnvironmentAssessment.class +0 -0
  46. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/FaceAntiSpoofingAdvanced$SpoofDetectionResult.class +0 -0
  47. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/FaceAntiSpoofingAdvanced.class +0 -0
  48. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/ImageFormatEncoder$ImageFormat.class +0 -0
  49. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/ImageFormatEncoder.class +0 -0
  50. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/YuvToFloatArrayConverter$Companion.class +0 -0
  51. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/YuvToFloatArrayConverter.class +0 -0
  52. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  53. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  54. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  55. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  56. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  57. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  58. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  59. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  60. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  61. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  62. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  63. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  64. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  65. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  66. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  67. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
  68. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
  69. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
  70. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
  71. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
  72. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
  73. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  74. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  75. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  76. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  77. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  78. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  79. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  80. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  81. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  82. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  83. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  84. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  85. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  86. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  87. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  88. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  89. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  90. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  91. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  92. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  93. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  94. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  95. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  96. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/AcceleratorConfig.class +0 -0
  97. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/AntiSpoofingResult.class +0 -0
  98. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced$Companion.class +0 -0
  99. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced$EnvironmentAssessment.class +0 -0
  100. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced$SpoofDetectionResult.class +0 -0
  101. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced.class +0 -0
  102. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/ImageFormatEncoder$ImageFormat.class +0 -0
  103. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/ImageFormatEncoder.class +0 -0
  104. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/YuvToFloatArrayConverter$Companion.class +0 -0
  105. package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/YuvToFloatArrayConverter.class +0 -0
  106. package/android/src/main/java/com/faceantispoof/AcceleratorConfig.kt +57 -9
  107. package/android/src/main/java/com/faceantispoof/FaceAntiSpoofingAdvanced.kt +187 -41
  108. package/android/src/main/java/com/faceantispoof/ImageFormatEncoder.kt +92 -6
  109. package/android/src/main/java/com/faceantispoof/YuvToFloatArrayConverter.kt +203 -2
  110. package/package.json +1 -1
  111. package/android/build/intermediates/cxx/Debug/2a1it684/logs/arm64-v8a/generate_cxx_metadata_456_timing.txt +0 -9
  112. package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86_64/generate_cxx_metadata_455_timing.txt +0 -9
  113. /package/android/.cxx/Debug/2a1it684/armeabi-v7a/.cmake/api/v1/reply/{index-2025-11-25T14-14-30-0191.json → index-2025-11-27T04-19-25-0344.json} +0 -0
  114. /package/android/.cxx/Debug/2a1it684/x86/.cmake/api/v1/reply/{index-2025-11-25T14-14-37-0548.json → index-2025-11-27T04-19-33-0139.json} +0 -0
  115. /package/android/.cxx/Debug/2a1it684/x86_64/.cmake/api/v1/reply/{index-2025-11-25T14-49-17-0490.json → index-2025-11-27T05-31-26-0486.json} +0 -0
@@ -1 +1 @@
1
- #Tue Nov 25 20:14:46 IST 2025
1
+ #Thu Nov 27 10:59:27 IST 2025
@@ -3,12 +3,14 @@ package com.faceantispoof
3
3
  /**
4
4
  * Configuration class for TensorFlow Lite accelerators
5
5
  * Allows developers to control GPU/NNAPI delegate behavior
6
+ * and optimize for different device tiers (low-end, mid-range, high-end)
6
7
  */
7
8
  object AcceleratorConfig {
8
9
 
9
10
  /**
10
11
  * Enable GPU acceleration (recommended for modern devices)
11
12
  * Accelerates model 3-10x compared to CPU
13
+ * GPU is automatically skipped on low-end devices even if enabled
12
14
  */
13
15
  var enableGpu: Boolean = true
14
16
 
@@ -16,34 +18,80 @@ object AcceleratorConfig {
16
18
  * Enable NNAPI acceleration (recommended for Pixel/Samsung devices)
17
19
  * Accelerates model 3-10x compared to CPU
18
20
  * Fallback if GPU is not available
21
+ * Works better on mid-range and high-end devices
19
22
  */
20
23
  var enableNnapi: Boolean = true
21
24
 
22
25
  /**
23
26
  * Enable CPU fallback if GPU/NNAPI are not available
24
- * Default: true
27
+ * Default: true (always fallback to CPU)
25
28
  */
26
29
  var enableCpuFallback: Boolean = true
27
30
 
28
31
  /**
29
32
  * Number of threads for CPU inference
30
- * Default: 4 threads
33
+ * Default: 4 threads (optimal for most devices)
34
+ * Low-end devices will use 1-2 threads regardless
31
35
  */
32
36
  var cpuThreadCount: Int = 4
33
37
 
34
38
  /**
35
- * Print debug logs for accelerator selection
39
+ * Force CPU-only mode for all devices
40
+ * Useful for debugging or if GPU/NNAPI causes issues
41
+ * Default: false
42
+ */
43
+ var forceCpuOnly: Boolean = false
44
+
45
+ /**
46
+ * Disable GPU delegate specifically
47
+ * Keeps NNAPI enabled if available
48
+ * Default: false
49
+ */
50
+ var disableGpuDelegate: Boolean = false
51
+
52
+ /**
53
+ * Disable NNAPI delegate specifically
54
+ * GPU will still be attempted if enabled
55
+ * Default: false
56
+ */
57
+ var disableNnapiDelegate: Boolean = false
58
+
59
+ /**
60
+ * Print debug logs for accelerator selection and performance
61
+ * Default: true
36
62
  */
37
63
  var debugLogging: Boolean = true
38
64
 
65
+ /**
66
+ * Enable aggressive optimization for low-end devices
67
+ * Reduces memory usage and processes fewer frames
68
+ * Default: true
69
+ */
70
+ var optimizeForLowEndDevices: Boolean = true
71
+
72
+ /**
73
+ * Maximum memory (in MB) to allocate for the interpreter
74
+ * Low-end devices will use less aggressive settings
75
+ * Default: 0 (use system defaults)
76
+ */
77
+ var maxMemoryAllocation: Int = 0
78
+
39
79
  override fun toString(): String {
40
80
  return """
41
- AcceleratorConfig:
42
- - GPU Enabled: $enableGpu
43
- - NNAPI Enabled: $enableNnapi
44
- - CPU Fallback: $enableCpuFallback
45
- - CPU Threads: $cpuThreadCount
46
- - Debug Logging: $debugLogging
81
+ ╔════════════════════════════════════════════════╗
82
+ ║ TFLite Accelerator Configuration ║
83
+ ╠════════════════════════════════════════════════╣
84
+ GPU Acceleration: $enableGpu
85
+ NNAPI Acceleration: $enableNnapi
86
+ CPU Fallback: $enableCpuFallback
87
+ ║ CPU Threads: $cpuThreadCount
88
+ ║ Force CPU Only: $forceCpuOnly
89
+ ║ Disable GPU Delegate: $disableGpuDelegate
90
+ ║ Disable NNAPI Delegate: $disableNnapiDelegate
91
+ ║ Debug Logging: $debugLogging
92
+ ║ Optimize Low-End: $optimizeForLowEndDevices
93
+ ║ Max Memory (MB): $maxMemoryAllocation
94
+ ╚════════════════════════════════════════════════╝
47
95
  """.trimIndent()
48
96
  }
49
97
  }
@@ -34,10 +34,10 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
34
34
  const val ACCELERATOR_GPU = "GPU"
35
35
  const val ACCELERATOR_NNAPI = "NNAPI"
36
36
 
37
- // Image format configuration for face recognition systems
38
- // Supported: JPEG (compressed), PNG (lossless), BMP (uncompressed)
37
+ // ENHANCED IMAGE FORMAT CONFIGURATION FOR FACE RECOGNITION
38
+ // Optimized for maximum quality for face detection APIs
39
39
  const val DEFAULT_IMAGE_FORMAT = "JPEG" // Options: "JPEG", "PNG", "BMP"
40
- const val DEFAULT_JPEG_QUALITY = 85 // 0-100, higher = better quality but larger
40
+ const val DEFAULT_JPEG_QUALITY = 92 // Increased from 85 to 92 for better quality
41
41
  const val DEFAULT_OUTPUT_RESOLUTION = 640 // 640×640 for face recognition
42
42
 
43
43
  // Advanced spoof detection constants
@@ -49,6 +49,11 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
49
49
  private const val TEXTURE_COMPLEXITY_THRESHOLD = 800
50
50
  private const val COLOR_SATURATION_THRESHOLD = 0.4f
51
51
  private const val DEPTH_VARIATION_THRESHOLD = 0.1f
52
+
53
+ // STABILITY ENHANCEMENT CONSTANTS
54
+ private const val BLUR_DETECTION_THRESHOLD = 100 // Laplacian score threshold
55
+ private const val MIN_STABLE_FRAMES = 3 // Require stable frames before generating base64
56
+ private const val MOTION_THRESHOLD = 0.1f // Limit motion/instability
52
57
  }
53
58
 
54
59
  private var interpreter: Interpreter? = null
@@ -79,6 +84,12 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
79
84
  private var frameCount = 0
80
85
  private var adaptiveThreshold = BASE_THRESHOLD
81
86
  private var environmentAssessment = EnvironmentAssessment()
87
+
88
+ // STABILITY AND QUALITY TRACKING
89
+ private var consecutiveQualityFrames = 0 // Track consecutive high-quality frames
90
+ private var lastStableFrameTime = System.currentTimeMillis()
91
+ private var lastProcessedBlurScore = 0
92
+ private var frameStabilityScore = 0f
82
93
 
83
94
  data class EnvironmentAssessment(
84
95
  var avgBrightness: Float = 0f,
@@ -96,22 +107,15 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
96
107
  try {
97
108
  val modelBuffer = loadModelFile(assetManager, MODEL_FILE)
98
109
  val options = Interpreter.Options()
99
- options.setNumThreads(4)
100
110
 
101
- if (tryAddGpuDelegate(options)) {
102
- currentAccelerator = ACCELERATOR_GPU
103
- Log.i(TAG, "GPU delegate enabled successfully")
104
- }
105
- else {
106
- try {
107
- options.setUseNNAPI(true)
108
- currentAccelerator = ACCELERATOR_NNAPI
109
- Log.i(TAG, "NNAPI enabled successfully")
110
- } catch (e: Exception) {
111
- currentAccelerator = ACCELERATOR_CPU
112
- Log.i(TAG, "Running on CPU (GPU/NNAPI not available): ${e.message}")
113
- }
114
- }
111
+ // FORCE CPU-ONLY MODE FOR LOW-END DEVICE COMPATIBILITY
112
+ // This bypasses all GPU/NNAPI issues and uses stable CPU inference
113
+ val optimalThreads = getOptimalThreadCount()
114
+ options.setNumThreads(optimalThreads)
115
+
116
+ currentAccelerator = ACCELERATOR_CPU
117
+ Log.i(TAG, "✓ FORCED CPU-ONLY MODE - Bypassing GPU/NNAPI")
118
+ Log.i(TAG, "Using $optimalThreads threads for CPU inference")
115
119
 
116
120
  interpreter = Interpreter(modelBuffer, options)
117
121
 
@@ -126,28 +130,46 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
126
130
  outputs[outputIndex0] = clssPred
127
131
  outputs[outputIndex1] = leafNodeMask
128
132
  isInitialized = true
129
- Log.i(TAG, "Interpreter initialized with accelerator: $currentAccelerator")
133
+ Log.i(TAG, " Face Anti-Spoof initialized | CPU-ONLY MODE | Threads: $optimalThreads")
130
134
  } catch (e: Exception) {
131
- Log.e(TAG, "Failed to load TFLite model", e)
135
+ Log.e(TAG, "Failed to load TFLite model: ${e.message}", e)
132
136
  isInitialized = false
137
+ currentAccelerator = ACCELERATOR_CPU
133
138
  }
134
139
  }
135
140
 
136
141
  private fun tryAddGpuDelegate(options: Interpreter.Options): Boolean {
137
142
  return try {
143
+ // Additional check: verify device has minimum Android version for GPU delegate
144
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
145
+ Log.w(TAG, "GPU delegate requires Android 5.0+, device running: ${android.os.Build.VERSION.SDK_INT}")
146
+ return false
147
+ }
148
+
138
149
  val compatibilityList = CompatibilityList()
139
150
  if (compatibilityList.isDelegateSupportedOnThisDevice) {
140
- gpuDelegate = GpuDelegate(compatibilityList.bestOptionsForThisDevice)
141
- options.addDelegate(gpuDelegate)
142
- Log.d(TAG, "GPU delegate added successfully")
143
- true
151
+ try {
152
+ gpuDelegate = GpuDelegate(compatibilityList.bestOptionsForThisDevice)
153
+ options.addDelegate(gpuDelegate)
154
+ Log.d(TAG, "GPU delegate added successfully")
155
+ true
156
+ } catch (e: Exception) {
157
+ Log.w(TAG, "Failed to initialize GPU delegate after compatibility check: ${e.message}")
158
+ gpuDelegate?.close()
159
+ gpuDelegate = null
160
+ false
161
+ }
144
162
  } else {
145
163
  Log.d(TAG, "GPU delegate not supported on this device")
146
164
  false
147
165
  }
148
166
  } catch (e: Exception) {
149
167
  Log.w(TAG, "Failed to add GPU delegate: ${e.message}")
150
- gpuDelegate?.close()
168
+ try {
169
+ gpuDelegate?.close()
170
+ } catch (e2: Exception) {
171
+ Log.w(TAG, "Error closing GPU delegate: ${e2.message}")
172
+ }
151
173
  gpuDelegate = null
152
174
  false
153
175
  }
@@ -274,21 +296,47 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
274
296
  var recognitionImageBase64: String? = null
275
297
  val DEBUG_FORCE_BASE64 = false // Set to true to force Base64 generation for testing
276
298
 
277
- if (isLive || DEBUG_FORCE_BASE64) {
278
- Log.d(TAG, "🔍 isLive=$isLive (DEBUG_FORCE_BASE64=$DEBUG_FORCE_BASE64) - generating ${outputImageResolution}×${outputImageResolution} $outputImageFormat Base64...")
299
+ // STABILITY CHECK: Only generate base64 for high-quality, stable frames
300
+ val isQualityFrame = laplacianScore > BLUR_DETECTION_THRESHOLD &&
301
+ temporalConsistency < MOTION_THRESHOLD &&
302
+ textureScore > TEXTURE_COMPLEXITY_THRESHOLD / 2
303
+
304
+ if (isQualityFrame) {
305
+ consecutiveQualityFrames++
306
+ frameStabilityScore = (laplacianScore.toFloat() / 1000f).coerceIn(0f, 1f)
307
+ } else {
308
+ consecutiveQualityFrames = 0
309
+ frameStabilityScore = 0f
310
+ }
311
+
312
+ // Only generate base64 after collecting stable frames
313
+ val shouldGenerateBase64 = (isLive && (consecutiveQualityFrames >= MIN_STABLE_FRAMES || DEBUG_FORCE_BASE64)) ||
314
+ DEBUG_FORCE_BASE64
315
+
316
+ if (shouldGenerateBase64) {
317
+ Log.d(TAG, "🔍 Quality Frame Detected - Stability Score: $frameStabilityScore (${consecutiveQualityFrames}/$MIN_STABLE_FRAMES frames)")
318
+ Log.d(TAG, " Blur Score: $laplacianScore (threshold: $BLUR_DETECTION_THRESHOLD)")
319
+ Log.d(TAG, " Motion: $temporalConsistency (threshold: $MOTION_THRESHOLD)")
320
+ Log.d(TAG, " Texture: $textureScore (min: ${TEXTURE_COMPLEXITY_THRESHOLD / 2})")
321
+
279
322
  try {
280
323
  recognitionImageBase64 = generateRecognitionImageBase64(nv21, width, height)
281
324
  if (recognitionImageBase64 != null) {
282
- Log.d(TAG, " Generated 640x640 JPEG Base64 for recognition API (size: ${recognitionImageBase64.length} bytes)")
325
+ Log.d(TAG, " Generated 640x640 JPEG Base64 for recognition API (size: ${recognitionImageBase64.length} bytes)")
283
326
  } else {
284
- Log.w(TAG, " generate640x640JpegBase64 returned null")
327
+ Log.w(TAG, "⚠️ generateRecognitionImageBase64 returned null")
285
328
  }
286
329
  } catch (e: Exception) {
287
- Log.w(TAG, " Failed to generate 640x640 JPEG Base64: ${e.message}", e)
330
+ Log.w(TAG, " Failed to generate Base64: ${e.message}", e)
288
331
  // Continue without the image - it's not critical
289
332
  }
290
333
  } else {
291
- Log.d(TAG, " isLive is FALSE - skipping Base64 generation")
334
+ if (!isLive) {
335
+ Log.d(TAG, "🚫 Not generating Base64 - Spoof detected (${spoofDetection.type})")
336
+ } else {
337
+ Log.d(TAG, "🚫 Waiting for stable frames... (${consecutiveQualityFrames}/$MIN_STABLE_FRAMES)")
338
+ Log.d(TAG, " Quality Score: $frameStabilityScore | Blur: $laplacianScore | Motion: $temporalConsistency")
339
+ }
292
340
  }
293
341
 
294
342
  AntiSpoofingResult(
@@ -386,6 +434,13 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
386
434
 
387
435
  /**
388
436
  * Generate image as Base64 string for face recognition API.
437
+ *
438
+ * QUALITY ENHANCEMENTS:
439
+ * - Uses bilinear interpolation for smooth resizing (no blur artifacts)
440
+ * - Applies unsharp masking for edge enhancement
441
+ * - Uses quality 92 JPEG encoding (up from 85) for better face detection
442
+ * - Validates frame stability before generation
443
+ *
389
444
  * Supports JPEG, PNG, and BMP formats with configurable resolution.
390
445
  * Compatible with OpenCV cv2.imdecode() for face recognition systems.
391
446
  *
@@ -396,9 +451,10 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
396
451
  */
397
452
  private fun generateRecognitionImageBase64(nv21: ByteArray, width: Int, height: Int): String? {
398
453
  return try {
399
- Log.d(TAG, "Starting ${outputImageResolution}×${outputImageResolution} $outputImageFormat generation. Input: ${width}x${height}, NV21 size: ${nv21.size}")
454
+ Log.d(TAG, "Starting HIGH-QUALITY ${outputImageResolution}×${outputImageResolution} $outputImageFormat generation...")
455
+ Log.d(TAG, "Input: ${width}x${height}, JPEG Quality: $outputImageQuality (optimized for face detection)")
400
456
 
401
- // Convert NV21 to RGB byte array directly (configurable resolution)
457
+ // Convert NV21 to RGB byte array using HIGH-QUALITY BILINEAR interpolation
402
458
  val rgbBytes = ByteArray(outputImageResolution * outputImageResolution * 3)
403
459
  Log.d(TAG, "Allocated RGB buffer: ${rgbBytes.size} bytes")
404
460
 
@@ -409,10 +465,13 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
409
465
  rgbBytes
410
466
  )
411
467
  val convertTime = System.currentTimeMillis() - startConvert
412
- Log.d(TAG, "YUV to RGB conversion completed in ${convertTime}ms. RGB data: ${convertedRgb.size} bytes")
468
+ Log.d(TAG, "YUVRGB conversion (bilinear): ${convertTime}ms | ${convertedRgb.size} bytes")
413
469
 
414
- // Encode RGB to target format (JPEG, PNG, or BMP) and Base64
415
- // NOTE: ImageFormatEncoder.rgbToBase64() automatically converts RGB→BGR for OpenCV compatibility
470
+ // Encode RGB to target format with sharpening
471
+ // NOTE: ImageFormatEncoder.rgbToBase64() automatically:
472
+ // - Applies unsharp masking for edge enhancement
473
+ // - Converts RGB→BGR for OpenCV compatibility
474
+ // - Uses optimized JPEG quality
416
475
  val startEncode = System.currentTimeMillis()
417
476
  val format = when (outputImageFormat) {
418
477
  "PNG" -> ImageFormatEncoder.ImageFormat.PNG
@@ -425,17 +484,22 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
425
484
  outputImageResolution,
426
485
  outputImageResolution,
427
486
  format,
428
- outputImageQuality
487
+ outputImageQuality // Using quality 92 for better face detection
429
488
  )
430
489
  val encodeTime = System.currentTimeMillis() - startEncode
431
490
 
432
491
  if (base64Result != null) {
433
- Log.d(TAG, "$outputImageFormat encoding completed in ${encodeTime}ms. Base64 size: ${base64Result.length} bytes")
434
- Log.d(TAG, "✅ Generated ${outputImageResolution}×${outputImageResolution} $outputImageFormat Base64 for recognition API in BGR format (total: ${convertTime + encodeTime}ms)")
492
+ Log.d(TAG, "$outputImageFormat encoding (with sharpening): ${encodeTime}ms")
493
+ Log.d(TAG, "✅ HIGH-QUALITY Base64 Generated:")
494
+ Log.d(TAG, " Resolution: ${outputImageResolution}×${outputImageResolution}")
495
+ Log.d(TAG, " Format: $outputImageFormat (BGR for OpenCV)")
496
+ Log.d(TAG, " Quality: $outputImageQuality (enhanced for face recognition)")
497
+ Log.d(TAG, " Size: ${base64Result.length} chars (est. ${base64Result.length * 0.75 / 1024}KB)")
498
+ Log.d(TAG, " Total Time: ${convertTime + encodeTime}ms")
435
499
  val estSize = estimateImageSize()
436
- Log.d(TAG, "Format: $outputImageFormat (BGR), Quality: $outputImageQuality, Estimated: ${estSize / 1024}KB")
500
+ Log.d(TAG, " Estimated: ${estSize / 1024}KB")
437
501
  } else {
438
- Log.w(TAG, "⚠️ ImageFormatEncoder returned null for BGR conversion")
502
+ Log.w(TAG, "⚠️ ImageFormatEncoder returned null")
439
503
  }
440
504
 
441
505
  base64Result
@@ -772,6 +836,88 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
772
836
  Log.e(TAG, "Error closing interpreter", e)
773
837
  }
774
838
  }
839
+
840
+ /**
841
+ * Detects if the device is high-end based on RAM, processor, and Android version.
842
+ * High-end devices can use GPU/NNAPI delegates.
843
+ * Low-end devices default to optimized CPU inference.
844
+ */
845
+ private fun isHighEndDevice(): Boolean {
846
+ try {
847
+ // Check Android version
848
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
849
+ Log.d(TAG, "Device running Android ${android.os.Build.VERSION.SDK_INT} (< 5.0) - low-end")
850
+ return false
851
+ }
852
+
853
+ // Check available RAM
854
+ val runtime = Runtime.getRuntime()
855
+ val maxMemory = runtime.maxMemory() / (1024 * 1024) // Convert to MB
856
+ if (maxMemory < 256) { // Less than 256MB allocated
857
+ Log.d(TAG, "Low available RAM: ${maxMemory}MB - treating as low-end device")
858
+ return false
859
+ }
860
+
861
+ // Check processor cores (devices with 2 cores or less are typically low-end)
862
+ val processorCount = Runtime.getRuntime().availableProcessors()
863
+ if (processorCount <= 2) {
864
+ Log.d(TAG, "Limited CPU cores: $processorCount - low-end device")
865
+ return false
866
+ }
867
+
868
+ // Check device name for known low-end models
869
+ val model = android.os.Build.MODEL.lowercase()
870
+ val lowEndMarkers = listOf(
871
+ "moto g", "samsung a", "samsung j", "redmi 6", "redmi 7",
872
+ "honor 8a", "galaxy a01", "galaxy j2"
873
+ )
874
+
875
+ for (marker in lowEndMarkers) {
876
+ if (model.contains(marker)) {
877
+ Log.d(TAG, "Known low-end device model: ${android.os.Build.MODEL}")
878
+ return false
879
+ }
880
+ }
881
+
882
+ Log.d(TAG, "Device appears to be high-end (Android ${android.os.Build.VERSION.SDK_INT}, $processorCount cores, ${maxMemory}MB RAM)")
883
+ return true
884
+ } catch (e: Exception) {
885
+ Log.w(TAG, "Error detecting device tier: ${e.message}, defaulting to CPU-only")
886
+ return false
887
+ }
888
+ }
889
+
890
+ /**
891
+ * Calculates optimal thread count based on available processors and device resources.
892
+ * Low-end devices use 1-2 threads to avoid memory issues.
893
+ */
894
+ private fun getOptimalThreadCount(): Int {
895
+ return try {
896
+ val availableProcessors = Runtime.getRuntime().availableProcessors()
897
+
898
+ // For low-end devices, limit thread count
899
+ if (!isHighEndDevice()) {
900
+ Log.d(TAG, "Low-end device: limiting threads to 1-2")
901
+ return maxOf(1, minOf(2, availableProcessors - 1))
902
+ }
903
+
904
+ // For high-end devices, use configured count or optimal calculation
905
+ val configured = AcceleratorConfig.cpuThreadCount
906
+ val optimal = maxOf(1, availableProcessors - 1)
907
+
908
+ val threadCount = if (configured > 0) {
909
+ minOf(configured, availableProcessors)
910
+ } else {
911
+ optimal
912
+ }
913
+
914
+ Log.d(TAG, "Optimal thread count: $threadCount (available processors: $availableProcessors)")
915
+ threadCount
916
+ } catch (e: Exception) {
917
+ Log.w(TAG, "Error calculating optimal threads: ${e.message}, using default")
918
+ AcceleratorConfig.cpuThreadCount
919
+ }
920
+ }
775
921
  }
776
922
 
777
923
  data class AntiSpoofingResult(