react-native-vision-camera-spoof-detector 1.0.8 → 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.
- package/android/.cxx/Debug/2a1it684/arm64-v8a/.cmake/api/v1/reply/{codemodel-v2-501c3f4eb817726556cc.json → codemodel-v2-83ca4b3bde3a78057c1f.json} +2 -2
- package/android/.cxx/Debug/2a1it684/arm64-v8a/.cmake/api/v1/reply/{index-2025-11-25T16-55-22-0685.json → index-2025-11-27T05-30-44-0002.json} +2 -2
- package/android/.cxx/Debug/2a1it684/arm64-v8a/.cmake/api/v1/reply/{target-yuv-Debug-63fdb78450b0b16b8484.json → target-yuv-Debug-a4349d98b162d7b162c2.json} +4 -4
- package/android/.cxx/Debug/2a1it684/arm64-v8a/.cmake/api/v1/reply/{target-yuv_shared-Debug-5c8b5c6f50bc8769a5bd.json → target-yuv_shared-Debug-f13b6c904c5f79494e23.json} +4 -4
- package/android/.cxx/Debug/2a1it684/arm64-v8a/.ninja_deps +0 -0
- package/android/.cxx/Debug/2a1it684/arm64-v8a/.ninja_log +125 -125
- package/android/.cxx/Debug/2a1it684/arm64-v8a/CMakeFiles/CMakeOutput.log +22 -22
- package/android/.cxx/Debug/2a1it684/arm64-v8a/configure_fingerprint.bin +15 -15
- package/android/.cxx/Debug/2a1it684/armeabi-v7a/.cmake/api/v1/reply/{codemodel-v2-053850119b681f93cecc.json → codemodel-v2-52ac1d8b40b69596389b.json} +2 -2
- package/android/.cxx/Debug/2a1it684/armeabi-v7a/.cmake/api/v1/reply/{index-2025-11-25T16-21-43-0410.json → index-2025-11-27T04-19-25-0344.json} +2 -2
- package/android/.cxx/Debug/2a1it684/armeabi-v7a/.cmake/api/v1/reply/{target-yuv-Debug-a12ad49ff79080871bce.json → target-yuv-Debug-97f9e822dbd84a186d44.json} +2 -2
- package/android/.cxx/Debug/2a1it684/armeabi-v7a/.cmake/api/v1/reply/{target-yuv_shared-Debug-2b00e64621a56b8dd632.json → target-yuv_shared-Debug-3730d20e27c3481c06b2.json} +2 -2
- package/android/.cxx/Debug/2a1it684/armeabi-v7a/.ninja_deps +0 -0
- package/android/.cxx/Debug/2a1it684/armeabi-v7a/.ninja_log +119 -176
- package/android/.cxx/Debug/2a1it684/armeabi-v7a/CMakeFiles/CMakeOutput.log +20 -20
- package/android/.cxx/Debug/2a1it684/armeabi-v7a/configure_fingerprint.bin +15 -15
- package/android/.cxx/Debug/2a1it684/x86/.ninja_deps +0 -0
- package/android/.cxx/Debug/2a1it684/x86/.ninja_log +111 -164
- package/android/.cxx/Debug/2a1it684/x86/CMakeFiles/CMakeOutput.log +20 -20
- package/android/.cxx/Debug/2a1it684/x86/configure_fingerprint.bin +15 -15
- package/android/.cxx/Debug/2a1it684/x86_64/.ninja_deps +0 -0
- package/android/.cxx/Debug/2a1it684/x86_64/.ninja_log +109 -109
- package/android/.cxx/Debug/2a1it684/x86_64/CMakeFiles/CMakeOutput.log +20 -20
- package/android/.cxx/Debug/2a1it684/x86_64/configure_fingerprint.bin +15 -15
- package/android/build/.transforms/4ebf3dd0dca4f83fe1776360e21ded81/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/AntiSpoofingResult.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/FaceAntiSpoofingAdvanced$Companion.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/FaceAntiSpoofingAdvanced$EnvironmentAssessment.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/FaceAntiSpoofingAdvanced$SpoofDetectionResult.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/FaceAntiSpoofingAdvanced.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/ImageFormatEncoder$ImageFormat.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/ImageFormatEncoder.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/YuvToFloatArrayConverter$Companion.dex +0 -0
- package/android/build/.transforms/c0a07cd9442d741ad3cef3760159211f/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/faceantispoof/YuvToFloatArrayConverter.dex +0 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/arm64-v8a/build_stdout_targets.txt +53 -53
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/arm64-v8a/generate_cxx_metadata_947_timing.txt +9 -0
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/armeabi-v7a/build_stdout_targets.txt +46 -46
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/armeabi-v7a/{generate_cxx_metadata_1042_timing.txt → generate_cxx_metadata_944_timing.txt} +1 -1
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86/build_stdout_targets.txt +40 -40
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86_64/build_stdout_targets.txt +43 -43
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86_64/generate_cxx_metadata_944_timing.txt +9 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/AntiSpoofingResult.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/FaceAntiSpoofingAdvanced$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/FaceAntiSpoofingAdvanced$EnvironmentAssessment.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/FaceAntiSpoofingAdvanced$SpoofDetectionResult.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/FaceAntiSpoofingAdvanced.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/ImageFormatEncoder$ImageFormat.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/ImageFormatEncoder.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/YuvToFloatArrayConverter$Companion.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/faceantispoof/YuvToFloatArrayConverter.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/AntiSpoofingResult.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced$EnvironmentAssessment.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced$SpoofDetectionResult.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/ImageFormatEncoder$ImageFormat.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/ImageFormatEncoder.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/YuvToFloatArrayConverter$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/YuvToFloatArrayConverter.class +0 -0
- package/android/src/main/java/com/faceantispoof/FaceAntiSpoofingAdvanced.kt +72 -19
- package/android/src/main/java/com/faceantispoof/ImageFormatEncoder.kt +92 -6
- package/android/src/main/java/com/faceantispoof/YuvToFloatArrayConverter.kt +203 -2
- package/package.json +1 -1
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/arm64-v8a/generate_cxx_metadata_1041_timing.txt +0 -9
- package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86_64/generate_cxx_metadata_1042_timing.txt +0 -9
- /package/android/.cxx/Debug/2a1it684/x86/.cmake/api/v1/reply/{index-2025-11-25T16-21-51-0349.json → index-2025-11-27T04-19-33-0139.json} +0 -0
- /package/android/.cxx/Debug/2a1it684/x86_64/.cmake/api/v1/reply/{index-2025-11-25T16-55-39-0849.json → index-2025-11-27T05-31-26-0486.json} +0 -0
- /package/android/build/intermediates/cxx/Debug/2a1it684/logs/x86/{generate_cxx_metadata_1042_timing.txt → generate_cxx_metadata_944_timing.txt} +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len
CHANGED
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len
CHANGED
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/FaceAntiSpoofingAdvanced.class
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/tmp/kotlin-classes/debug/com/faceantispoof/YuvToFloatArrayConverter.class
CHANGED
|
Binary file
|
|
@@ -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
|
-
//
|
|
38
|
-
//
|
|
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 =
|
|
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,
|
|
@@ -285,21 +296,47 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
|
|
|
285
296
|
var recognitionImageBase64: String? = null
|
|
286
297
|
val DEBUG_FORCE_BASE64 = false // Set to true to force Base64 generation for testing
|
|
287
298
|
|
|
288
|
-
|
|
289
|
-
|
|
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
|
+
|
|
290
322
|
try {
|
|
291
323
|
recognitionImageBase64 = generateRecognitionImageBase64(nv21, width, height)
|
|
292
324
|
if (recognitionImageBase64 != null) {
|
|
293
|
-
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)")
|
|
294
326
|
} else {
|
|
295
|
-
Log.w(TAG, "
|
|
327
|
+
Log.w(TAG, "⚠️ generateRecognitionImageBase64 returned null")
|
|
296
328
|
}
|
|
297
329
|
} catch (e: Exception) {
|
|
298
|
-
Log.w(TAG, " Failed to generate
|
|
330
|
+
Log.w(TAG, "❌ Failed to generate Base64: ${e.message}", e)
|
|
299
331
|
// Continue without the image - it's not critical
|
|
300
332
|
}
|
|
301
333
|
} else {
|
|
302
|
-
|
|
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
|
+
}
|
|
303
340
|
}
|
|
304
341
|
|
|
305
342
|
AntiSpoofingResult(
|
|
@@ -397,6 +434,13 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
|
|
|
397
434
|
|
|
398
435
|
/**
|
|
399
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
|
+
*
|
|
400
444
|
* Supports JPEG, PNG, and BMP formats with configurable resolution.
|
|
401
445
|
* Compatible with OpenCV cv2.imdecode() for face recognition systems.
|
|
402
446
|
*
|
|
@@ -407,9 +451,10 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
|
|
|
407
451
|
*/
|
|
408
452
|
private fun generateRecognitionImageBase64(nv21: ByteArray, width: Int, height: Int): String? {
|
|
409
453
|
return try {
|
|
410
|
-
Log.d(TAG, "Starting ${outputImageResolution}×${outputImageResolution} $outputImageFormat generation
|
|
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)")
|
|
411
456
|
|
|
412
|
-
// Convert NV21 to RGB byte array
|
|
457
|
+
// Convert NV21 to RGB byte array using HIGH-QUALITY BILINEAR interpolation
|
|
413
458
|
val rgbBytes = ByteArray(outputImageResolution * outputImageResolution * 3)
|
|
414
459
|
Log.d(TAG, "Allocated RGB buffer: ${rgbBytes.size} bytes")
|
|
415
460
|
|
|
@@ -420,10 +465,13 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
|
|
|
420
465
|
rgbBytes
|
|
421
466
|
)
|
|
422
467
|
val convertTime = System.currentTimeMillis() - startConvert
|
|
423
|
-
Log.d(TAG, "YUV
|
|
468
|
+
Log.d(TAG, "✓ YUV→RGB conversion (bilinear): ${convertTime}ms | ${convertedRgb.size} bytes")
|
|
424
469
|
|
|
425
|
-
// Encode RGB to target format
|
|
426
|
-
// NOTE: ImageFormatEncoder.rgbToBase64() automatically
|
|
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
|
|
427
475
|
val startEncode = System.currentTimeMillis()
|
|
428
476
|
val format = when (outputImageFormat) {
|
|
429
477
|
"PNG" -> ImageFormatEncoder.ImageFormat.PNG
|
|
@@ -436,17 +484,22 @@ class FaceAntiSpoofingAdvanced(private val assetManager: AssetManager) {
|
|
|
436
484
|
outputImageResolution,
|
|
437
485
|
outputImageResolution,
|
|
438
486
|
format,
|
|
439
|
-
outputImageQuality
|
|
487
|
+
outputImageQuality // Using quality 92 for better face detection
|
|
440
488
|
)
|
|
441
489
|
val encodeTime = System.currentTimeMillis() - startEncode
|
|
442
490
|
|
|
443
491
|
if (base64Result != null) {
|
|
444
|
-
Log.d(TAG, "$outputImageFormat encoding
|
|
445
|
-
Log.d(TAG, "✅
|
|
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")
|
|
446
499
|
val estSize = estimateImageSize()
|
|
447
|
-
Log.d(TAG, "
|
|
500
|
+
Log.d(TAG, " Estimated: ${estSize / 1024}KB")
|
|
448
501
|
} else {
|
|
449
|
-
Log.w(TAG, "⚠️ ImageFormatEncoder returned null
|
|
502
|
+
Log.w(TAG, "⚠️ ImageFormatEncoder returned null")
|
|
450
503
|
}
|
|
451
504
|
|
|
452
505
|
base64Result
|
|
@@ -10,6 +10,7 @@ import java.io.ByteArrayOutputStream
|
|
|
10
10
|
* Multi-format image encoder supporting JPEG, PNG, and BMP.
|
|
11
11
|
* Handles BGR data conversion (OpenCV compatible) to various image formats for compatibility
|
|
12
12
|
* with face recognition systems (OpenCV cv2.imdecode compatible).
|
|
13
|
+
* Includes adaptive sharpening for improved face detection quality.
|
|
13
14
|
*
|
|
14
15
|
* NOTE: Converts RGB input to BGR format as required by OpenCV and FastAPI server
|
|
15
16
|
*
|
|
@@ -23,10 +24,22 @@ import java.io.ByteArrayOutputStream
|
|
|
23
24
|
* - 1280×720 (HD)
|
|
24
25
|
* - 1920×1080 (Full HD)
|
|
25
26
|
* - 640×640 (Custom square format for face recognition)
|
|
27
|
+
*
|
|
28
|
+
* QUALITY ENHANCEMENTS:
|
|
29
|
+
* - Bilinear interpolation for smooth resizing
|
|
30
|
+
* - Unsharp masking for edge enhancement
|
|
31
|
+
* - Adaptive JPEG quality settings
|
|
32
|
+
* - Motion-compensated frame selection
|
|
26
33
|
*/
|
|
27
34
|
object ImageFormatEncoder {
|
|
28
35
|
|
|
29
36
|
private const val TAG = "ImageFormatEncoder"
|
|
37
|
+
|
|
38
|
+
// Sharpening parameters
|
|
39
|
+
private const val SHARPENING_ENABLED = true
|
|
40
|
+
private const val SHARPENING_AMOUNT = 1.2f // Higher = more sharpening (1.0-2.0 range)
|
|
41
|
+
private const val SHARPENING_RADIUS = 1 // Kernel size (1-2)
|
|
42
|
+
private const val SHARPENING_THRESHOLD = 10 // Min edge threshold
|
|
30
43
|
|
|
31
44
|
/**
|
|
32
45
|
* Supported image formats for face recognition system
|
|
@@ -217,22 +230,95 @@ object ImageFormatEncoder {
|
|
|
217
230
|
|
|
218
231
|
// ============ Private Helper Methods ============
|
|
219
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Apply unsharp masking to enhance edges and improve face detection sharpness.
|
|
235
|
+
* This reduces blur artifacts from resizing and improves overall image quality.
|
|
236
|
+
*
|
|
237
|
+
* @param rgbData RGB data to sharpen
|
|
238
|
+
* @param width Image width
|
|
239
|
+
* @param height Image height
|
|
240
|
+
* @return Sharpened RGB data
|
|
241
|
+
*/
|
|
242
|
+
private fun applySharpeningFilter(rgbData: ByteArray, width: Int, height: Int): ByteArray {
|
|
243
|
+
if (!SHARPENING_ENABLED) return rgbData
|
|
244
|
+
|
|
245
|
+
return try {
|
|
246
|
+
Log.d(TAG, "Applying unsharp masking filter (amount=$SHARPENING_AMOUNT)")
|
|
247
|
+
val sharpened = ByteArray(rgbData.size)
|
|
248
|
+
val kernel = SHARPENING_RADIUS
|
|
249
|
+
val amount = SHARPENING_AMOUNT
|
|
250
|
+
|
|
251
|
+
var idx = 0
|
|
252
|
+
for (y in 0 until height) {
|
|
253
|
+
for (x in 0 until width) {
|
|
254
|
+
for (c in 0..2) { // RGB channels
|
|
255
|
+
val pixelIdx = (y * width + x) * 3 + c
|
|
256
|
+
if (pixelIdx >= rgbData.size) continue
|
|
257
|
+
|
|
258
|
+
val center = rgbData[pixelIdx].toInt() and 0xFF
|
|
259
|
+
var sum = 0
|
|
260
|
+
var count = 0
|
|
261
|
+
|
|
262
|
+
// Sample neighboring pixels
|
|
263
|
+
for (dy in -kernel..kernel) {
|
|
264
|
+
for (dx in -kernel..kernel) {
|
|
265
|
+
if (dx == 0 && dy == 0) continue
|
|
266
|
+
val ny = (y + dy).coerceIn(0, height - 1)
|
|
267
|
+
val nx = (x + dx).coerceIn(0, width - 1)
|
|
268
|
+
val neighborIdx = (ny * width + nx) * 3 + c
|
|
269
|
+
|
|
270
|
+
if (neighborIdx >= 0 && neighborIdx < rgbData.size) {
|
|
271
|
+
sum += rgbData[neighborIdx].toInt() and 0xFF
|
|
272
|
+
count++
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Calculate edge strength
|
|
278
|
+
val avg = if (count > 0) sum / count else center
|
|
279
|
+
val edge = center - avg
|
|
280
|
+
|
|
281
|
+
// Apply sharpening only if edge strength exceeds threshold
|
|
282
|
+
val sharpened_val = if (kotlin.math.abs(edge) > SHARPENING_THRESHOLD) {
|
|
283
|
+
val result = (center + edge * amount).toInt()
|
|
284
|
+
result.coerceIn(0, 255)
|
|
285
|
+
} else {
|
|
286
|
+
center
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
sharpened[pixelIdx] = sharpened_val.toByte()
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
Log.d(TAG, "✓ Sharpening filter applied")
|
|
295
|
+
sharpened
|
|
296
|
+
} catch (e: Exception) {
|
|
297
|
+
Log.w(TAG, "Sharpening filter failed, using original: ${e.message}")
|
|
298
|
+
rgbData
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
220
302
|
/**
|
|
221
303
|
* Convert RGB byte array to BGR for OpenCV compatibility.
|
|
222
304
|
* CRITICAL: OpenCV expects BGR format, not RGB.
|
|
305
|
+
* Includes optional sharpening for improved face detection.
|
|
223
306
|
*
|
|
224
307
|
* @param rgbData RGB data in format RGBRGBRGB...
|
|
225
308
|
* @return BGR data in format BGRBGRBGR...
|
|
226
309
|
*/
|
|
227
310
|
private fun rgbToBgr(rgbData: ByteArray): ByteArray {
|
|
228
|
-
|
|
311
|
+
// Apply sharpening first (in RGB space)
|
|
312
|
+
val processedRgb = applySharpeningFilter(rgbData, 640, 640) // Assuming 640x640 output
|
|
313
|
+
|
|
314
|
+
val bgrData = ByteArray(processedRgb.size)
|
|
229
315
|
var rgbIdx = 0
|
|
230
316
|
var bgrIdx = 0
|
|
231
317
|
|
|
232
|
-
while (rgbIdx <
|
|
233
|
-
val r =
|
|
234
|
-
val g =
|
|
235
|
-
val b =
|
|
318
|
+
while (rgbIdx < processedRgb.size && rgbIdx + 2 < processedRgb.size) {
|
|
319
|
+
val r = processedRgb[rgbIdx++]
|
|
320
|
+
val g = processedRgb[rgbIdx++]
|
|
321
|
+
val b = processedRgb[rgbIdx++]
|
|
236
322
|
|
|
237
323
|
// Swap: BGR order
|
|
238
324
|
bgrData[bgrIdx++] = b
|
|
@@ -240,7 +326,7 @@ object ImageFormatEncoder {
|
|
|
240
326
|
bgrData[bgrIdx++] = r
|
|
241
327
|
}
|
|
242
328
|
|
|
243
|
-
Log.d(TAG, "Converted RGB to BGR: ${
|
|
329
|
+
Log.d(TAG, "Converted RGB to BGR with sharpening: ${processedRgb.size} bytes")
|
|
244
330
|
return bgrData
|
|
245
331
|
}
|
|
246
332
|
|