react-native-vision-camera-spoof-detector 1.0.22 → 1.0.23

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 (193) hide show
  1. package/README.md +442 -442
  2. package/android/build.gradle +12 -4
  3. package/android/src/main/cpp/CMakeLists.txt +101 -94
  4. package/android/src/main/cpp/libyuv/.clang-format +6 -6
  5. package/android/src/main/cpp/libyuv/.gn +40 -40
  6. package/android/src/main/cpp/libyuv/.vpython3 +410 -410
  7. package/android/src/main/cpp/libyuv/AUTHORS +7 -7
  8. package/android/src/main/cpp/libyuv/Android.bp +202 -202
  9. package/android/src/main/cpp/libyuv/Android.mk +106 -106
  10. package/android/src/main/cpp/libyuv/BUILD.gn +490 -490
  11. package/android/src/main/cpp/libyuv/CM_linux_packages.cmake +70 -70
  12. package/android/src/main/cpp/libyuv/CMakeLists.txt +259 -252
  13. package/android/src/main/cpp/libyuv/DEPS +935 -935
  14. package/android/src/main/cpp/libyuv/DIR_METADATA +3 -3
  15. package/android/src/main/cpp/libyuv/LICENSE +29 -29
  16. package/android/src/main/cpp/libyuv/OWNERS +11 -11
  17. package/android/src/main/cpp/libyuv/PATENTS +23 -23
  18. package/android/src/main/cpp/libyuv/PRESUBMIT.py +65 -65
  19. package/android/src/main/cpp/libyuv/README.chromium +11 -11
  20. package/android/src/main/cpp/libyuv/README.md +19 -19
  21. package/android/src/main/cpp/libyuv/build_overrides/build.gni +60 -60
  22. package/android/src/main/cpp/libyuv/build_overrides/gtest.gni +19 -19
  23. package/android/src/main/cpp/libyuv/build_overrides/partition_alloc.gni +17 -17
  24. package/android/src/main/cpp/libyuv/codereview.settings +5 -5
  25. package/android/src/main/cpp/libyuv/docs/deprecated_builds.md +409 -409
  26. package/android/src/main/cpp/libyuv/docs/environment_variables.md +64 -64
  27. package/android/src/main/cpp/libyuv/docs/feature_detection.md +108 -108
  28. package/android/src/main/cpp/libyuv/docs/filtering.md +196 -196
  29. package/android/src/main/cpp/libyuv/docs/formats.md +208 -208
  30. package/android/src/main/cpp/libyuv/docs/getting_started.md +296 -296
  31. package/android/src/main/cpp/libyuv/docs/rotation.md +107 -107
  32. package/android/src/main/cpp/libyuv/download_vs_toolchain.py +29 -29
  33. package/android/src/main/cpp/libyuv/include/libyuv/basic_types.h +68 -68
  34. package/android/src/main/cpp/libyuv/include/libyuv/compare.h +111 -111
  35. package/android/src/main/cpp/libyuv/include/libyuv/compare_row.h +112 -112
  36. package/android/src/main/cpp/libyuv/include/libyuv/convert.h +1117 -1117
  37. package/android/src/main/cpp/libyuv/include/libyuv/convert_argb.h +2335 -2335
  38. package/android/src/main/cpp/libyuv/include/libyuv/convert_from.h +203 -203
  39. package/android/src/main/cpp/libyuv/include/libyuv/convert_from_argb.h +394 -394
  40. package/android/src/main/cpp/libyuv/include/libyuv/cpu_id.h +147 -147
  41. package/android/src/main/cpp/libyuv/include/libyuv/cpu_support.h +99 -99
  42. package/android/src/main/cpp/libyuv/include/libyuv/loongson_intrinsics.h +1949 -1949
  43. package/android/src/main/cpp/libyuv/include/libyuv/mjpeg_decoder.h +195 -195
  44. package/android/src/main/cpp/libyuv/include/libyuv/planar_functions.h +1131 -1131
  45. package/android/src/main/cpp/libyuv/include/libyuv/rotate.h +296 -296
  46. package/android/src/main/cpp/libyuv/include/libyuv/rotate_argb.h +37 -37
  47. package/android/src/main/cpp/libyuv/include/libyuv/rotate_row.h +265 -265
  48. package/android/src/main/cpp/libyuv/include/libyuv/row.h +6738 -6738
  49. package/android/src/main/cpp/libyuv/include/libyuv/row_sve.h +2154 -2154
  50. package/android/src/main/cpp/libyuv/include/libyuv/scale.h +336 -336
  51. package/android/src/main/cpp/libyuv/include/libyuv/scale_argb.h +76 -76
  52. package/android/src/main/cpp/libyuv/include/libyuv/scale_rgb.h +42 -42
  53. package/android/src/main/cpp/libyuv/include/libyuv/scale_row.h +1726 -1726
  54. package/android/src/main/cpp/libyuv/include/libyuv/scale_uv.h +51 -51
  55. package/android/src/main/cpp/libyuv/include/libyuv/version.h +16 -16
  56. package/android/src/main/cpp/libyuv/include/libyuv/video_common.h +222 -222
  57. package/android/src/main/cpp/libyuv/include/libyuv.h +33 -33
  58. package/android/src/main/cpp/libyuv/infra/config/OWNERS +3 -3
  59. package/android/src/main/cpp/libyuv/infra/config/PRESUBMIT.py +17 -17
  60. package/android/src/main/cpp/libyuv/infra/config/README.md +2 -2
  61. package/android/src/main/cpp/libyuv/infra/config/codereview.settings +6 -6
  62. package/android/src/main/cpp/libyuv/infra/config/commit-queue.cfg +144 -144
  63. package/android/src/main/cpp/libyuv/infra/config/cr-buildbucket.cfg +1185 -1185
  64. package/android/src/main/cpp/libyuv/infra/config/luci-logdog.cfg +9 -9
  65. package/android/src/main/cpp/libyuv/infra/config/luci-milo.cfg +246 -246
  66. package/android/src/main/cpp/libyuv/infra/config/luci-scheduler.cfg +385 -385
  67. package/android/src/main/cpp/libyuv/infra/config/main.star +402 -402
  68. package/android/src/main/cpp/libyuv/infra/config/project.cfg +16 -16
  69. package/android/src/main/cpp/libyuv/infra/config/realms.cfg +111 -111
  70. package/android/src/main/cpp/libyuv/libyuv.gni +34 -34
  71. package/android/src/main/cpp/libyuv/libyuv.gyp +149 -149
  72. package/android/src/main/cpp/libyuv/libyuv.gypi +87 -87
  73. package/android/src/main/cpp/libyuv/linux.mk +96 -96
  74. package/android/src/main/cpp/libyuv/public.mk +13 -13
  75. package/android/src/main/cpp/libyuv/pylintrc +49 -49
  76. package/android/src/main/cpp/libyuv/riscv_script/prepare_toolchain_qemu.sh +74 -74
  77. package/android/src/main/cpp/libyuv/riscv_script/riscv-clang.cmake +56 -56
  78. package/android/src/main/cpp/libyuv/riscv_script/run_qemu.sh +15 -15
  79. package/android/src/main/cpp/libyuv/source/compare.cc +435 -435
  80. package/android/src/main/cpp/libyuv/source/compare_common.cc +74 -74
  81. package/android/src/main/cpp/libyuv/source/compare_gcc.cc +362 -362
  82. package/android/src/main/cpp/libyuv/source/compare_neon.cc +96 -96
  83. package/android/src/main/cpp/libyuv/source/compare_neon64.cc +223 -223
  84. package/android/src/main/cpp/libyuv/source/compare_win.cc +241 -241
  85. package/android/src/main/cpp/libyuv/source/convert.cc +4746 -4746
  86. package/android/src/main/cpp/libyuv/source/convert_argb.cc +9179 -9179
  87. package/android/src/main/cpp/libyuv/source/convert_from.cc +866 -866
  88. package/android/src/main/cpp/libyuv/source/convert_from_argb.cc +3671 -3671
  89. package/android/src/main/cpp/libyuv/source/convert_jpeg.cc +602 -602
  90. package/android/src/main/cpp/libyuv/source/convert_to_argb.cc +391 -391
  91. package/android/src/main/cpp/libyuv/source/convert_to_i420.cc +288 -288
  92. package/android/src/main/cpp/libyuv/source/cpu_id.cc +496 -496
  93. package/android/src/main/cpp/libyuv/source/mjpeg_decoder.cc +580 -580
  94. package/android/src/main/cpp/libyuv/source/mjpeg_validate.cc +71 -71
  95. package/android/src/main/cpp/libyuv/source/planar_functions.cc +5663 -5663
  96. package/android/src/main/cpp/libyuv/source/rotate.cc +1241 -1241
  97. package/android/src/main/cpp/libyuv/source/rotate_any.cc +76 -76
  98. package/android/src/main/cpp/libyuv/source/rotate_argb.cc +259 -259
  99. package/android/src/main/cpp/libyuv/source/rotate_common.cc +208 -208
  100. package/android/src/main/cpp/libyuv/source/rotate_gcc.cc +505 -505
  101. package/android/src/main/cpp/libyuv/source/rotate_lsx.cc +233 -233
  102. package/android/src/main/cpp/libyuv/source/rotate_neon.cc +219 -219
  103. package/android/src/main/cpp/libyuv/source/rotate_neon64.cc +273 -273
  104. package/android/src/main/cpp/libyuv/source/rotate_sme.cc +174 -174
  105. package/android/src/main/cpp/libyuv/source/rotate_win.cc +253 -253
  106. package/android/src/main/cpp/libyuv/source/row_any.cc +2519 -2519
  107. package/android/src/main/cpp/libyuv/source/row_common.cc +4461 -4461
  108. package/android/src/main/cpp/libyuv/source/row_gcc.cc +9570 -9570
  109. package/android/src/main/cpp/libyuv/source/row_lasx.cc +2343 -2343
  110. package/android/src/main/cpp/libyuv/source/row_lsx.cc +3030 -3030
  111. package/android/src/main/cpp/libyuv/source/row_neon.cc +4026 -4026
  112. package/android/src/main/cpp/libyuv/source/row_neon64.cc +5617 -5617
  113. package/android/src/main/cpp/libyuv/source/row_rvv.cc +2599 -2599
  114. package/android/src/main/cpp/libyuv/source/row_sme.cc +1183 -1183
  115. package/android/src/main/cpp/libyuv/source/row_sve.cc +1088 -1088
  116. package/android/src/main/cpp/libyuv/source/row_win.cc +6453 -6453
  117. package/android/src/main/cpp/libyuv/source/scale.cc +2710 -2710
  118. package/android/src/main/cpp/libyuv/source/scale_any.cc +991 -991
  119. package/android/src/main/cpp/libyuv/source/scale_argb.cc +1158 -1158
  120. package/android/src/main/cpp/libyuv/source/scale_common.cc +1977 -1977
  121. package/android/src/main/cpp/libyuv/source/scale_gcc.cc +2947 -2947
  122. package/android/src/main/cpp/libyuv/source/scale_lsx.cc +739 -739
  123. package/android/src/main/cpp/libyuv/source/scale_neon.cc +1449 -1449
  124. package/android/src/main/cpp/libyuv/source/scale_neon64.cc +1552 -1552
  125. package/android/src/main/cpp/libyuv/source/scale_rgb.cc +82 -82
  126. package/android/src/main/cpp/libyuv/source/scale_rvv.cc +1971 -1971
  127. package/android/src/main/cpp/libyuv/source/scale_sme.cc +555 -555
  128. package/android/src/main/cpp/libyuv/source/scale_uv.cc +1159 -1159
  129. package/android/src/main/cpp/libyuv/source/scale_win.cc +1392 -1392
  130. package/android/src/main/cpp/libyuv/source/test.sh +35 -35
  131. package/android/src/main/cpp/libyuv/source/video_common.cc +62 -62
  132. package/android/src/main/cpp/libyuv/tools_libyuv/OWNERS +4 -4
  133. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/roll_deps.py +931 -931
  134. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/roll_deps_test.py +164 -164
  135. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS +21 -21
  136. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.new +13 -13
  137. package/android/src/main/cpp/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.old +13 -13
  138. package/android/src/main/cpp/libyuv/tools_libyuv/get_landmines.py +38 -38
  139. package/android/src/main/cpp/libyuv/tools_libyuv/msan/OWNERS +3 -3
  140. package/android/src/main/cpp/libyuv/tools_libyuv/msan/blacklist.txt +9 -9
  141. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/OWNERS +3 -3
  142. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/blacklist.txt +15 -15
  143. package/android/src/main/cpp/libyuv/tools_libyuv/ubsan/vptr_blacklist.txt +25 -25
  144. package/android/src/main/cpp/libyuv/unit_test/basictypes_test.cc +43 -43
  145. package/android/src/main/cpp/libyuv/unit_test/color_test.cc +848 -848
  146. package/android/src/main/cpp/libyuv/unit_test/compare_test.cc +739 -739
  147. package/android/src/main/cpp/libyuv/unit_test/convert_argb_test.cc +2867 -2867
  148. package/android/src/main/cpp/libyuv/unit_test/convert_test.cc +2133 -2133
  149. package/android/src/main/cpp/libyuv/unit_test/cpu_test.cc +427 -427
  150. package/android/src/main/cpp/libyuv/unit_test/cpu_thread_test.cc +63 -63
  151. package/android/src/main/cpp/libyuv/unit_test/math_test.cc +160 -160
  152. package/android/src/main/cpp/libyuv/unit_test/planar_test.cc +4731 -4731
  153. package/android/src/main/cpp/libyuv/unit_test/rotate_argb_test.cc +334 -334
  154. package/android/src/main/cpp/libyuv/unit_test/rotate_test.cc +962 -962
  155. package/android/src/main/cpp/libyuv/unit_test/scale_argb_test.cc +590 -590
  156. package/android/src/main/cpp/libyuv/unit_test/scale_plane_test.cc +465 -465
  157. package/android/src/main/cpp/libyuv/unit_test/scale_rgb_test.cc +280 -280
  158. package/android/src/main/cpp/libyuv/unit_test/scale_test.cc +1135 -1135
  159. package/android/src/main/cpp/libyuv/unit_test/scale_uv_test.cc +249 -249
  160. package/android/src/main/cpp/libyuv/unit_test/testdata/arm_v7.txt +12 -12
  161. package/android/src/main/cpp/libyuv/unit_test/testdata/mips.txt +7 -7
  162. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson2k.txt +5 -5
  163. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson3.txt +10 -10
  164. package/android/src/main/cpp/libyuv/unit_test/testdata/mips_loongson_mmi.txt +7 -7
  165. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64.txt +3 -3
  166. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64_rvv.txt +3 -3
  167. package/android/src/main/cpp/libyuv/unit_test/testdata/riscv64_rvv_zvfh.txt +3 -3
  168. package/android/src/main/cpp/libyuv/unit_test/testdata/tegra3.txt +23 -23
  169. package/android/src/main/cpp/libyuv/unit_test/unit_test.cc +581 -581
  170. package/android/src/main/cpp/libyuv/unit_test/unit_test.h +232 -232
  171. package/android/src/main/cpp/libyuv/unit_test/video_common_test.cc +112 -112
  172. package/android/src/main/cpp/libyuv/util/Makefile +9 -9
  173. package/android/src/main/cpp/libyuv/util/color.cc +120 -120
  174. package/android/src/main/cpp/libyuv/util/compare.cc +67 -67
  175. package/android/src/main/cpp/libyuv/util/cpuid.c +211 -211
  176. package/android/src/main/cpp/libyuv/util/i444tonv12_eg.cc +27 -27
  177. package/android/src/main/cpp/libyuv/util/psnr.cc +291 -291
  178. package/android/src/main/cpp/libyuv/util/psnr.h +47 -47
  179. package/android/src/main/cpp/libyuv/util/psnr_main.cc +620 -620
  180. package/android/src/main/cpp/libyuv/util/ssim.cc +364 -364
  181. package/android/src/main/cpp/libyuv/util/ssim.h +38 -38
  182. package/android/src/main/cpp/libyuv/util/yuvconstants.c +114 -114
  183. package/android/src/main/cpp/libyuv/util/yuvconvert.cc +367 -367
  184. package/android/src/main/cpp/libyuv/winarm.mk +47 -47
  185. package/package.json +86 -86
  186. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  187. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  188. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  189. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  190. package/android/.gradle/8.9/gc.properties +0 -0
  191. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  192. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  193. package/android/.gradle/vcs-1/gc.properties +0 -0
package/README.md CHANGED
@@ -1,442 +1,442 @@
1
- # react-native-vision-camera-spoof-detector
2
-
3
- [![npm version](https://badge.fury.io/js/react-native-vision-camera-spoof-detector.svg)](https://badge.fury.io/js/react-native-vision-camera-spoof-detector)
4
- [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue)](https://github.com/dpraful/react-native-vision-camera-spoof-detector)
5
-
6
- High-performance face anti-spoofing and liveness detection module for React Native Vision Camera. Features TensorFlow Lite with GPU acceleration, optimized YUV processing, and real-time blink detection for robust liveness verification.
7
-
8
- ## 🎯 Features
9
-
10
- - **🚀 Real-time Performance**: GPU-accelerated TensorFlow Lite processing for smooth 60fps detection
11
- - **🎯 High Accuracy**: Advanced ML models for distinguishing live faces from spoofing attempts
12
- - **👁️ Blink Detection**: Native blink detection for enhanced liveness verification
13
- - **📱 Optimized YUV Processing**: Efficient image data handling for React Native
14
- - **🔧 Easy Integration**: Seamlessly integrates with `react-native-vision-camera`
15
- - **⚡ Face Stability Tracking**: Automatic stable face detection with customizable thresholds
16
- - **🛡️ Face Centering**: Intelligent face positioning validation in frame
17
- - **📊 Anti-spoofing Confidence**: Detailed confidence scores with multiple detection models
18
- - **🔄 Batched Updates**: Optimized state management with minimal re-renders
19
-
20
- ## 📋 Requirements
21
-
22
- - React Native >= 0.60.0
23
- - react-native-vision-camera >= 4.6.4
24
- - react-native-reanimated >= 3.0.0
25
- - react-native-worklets-core >= 1.0.0
26
- - react-native-vision-camera-face-detector (optional, for enhanced features)
27
-
28
- ## 📦 Installation
29
-
30
- ### Step 1: Install the package
31
-
32
- ```bash
33
- npm install react-native-vision-camera-spoof-detector
34
- # or
35
- yarn add react-native-vision-camera-spoof-detector
36
- ```
37
-
38
- ### Step 2: Install peer dependencies
39
-
40
- ```bash
41
- npm install react-native-vision-camera react-native-reanimated react-native-worklets-core
42
- # or
43
- yarn add react-native-vision-camera react-native-reanimated react-native-worklets-core
44
- ```
45
-
46
- ### Step 3: Configure Android (if not auto-linked)
47
-
48
- Add to `android/app/build.gradle`:
49
-
50
- ```gradle
51
- dependencies {
52
- implementation project(':react-native-vision-camera-spoof-detector')
53
- }
54
- ```
55
-
56
- ### Step 4: Link native module (for React Native < 0.60)
57
-
58
- ```bash
59
- react-native link react-native-vision-camera-spoof-detector
60
- ```
61
-
62
- ## 🚀 Quick Start
63
-
64
- ### Simple Usage
65
-
66
- ```javascript
67
- import React, { useEffect, useState } from 'react';
68
- import { StyleSheet, Text, View } from 'react-native';
69
- import { Camera, useCameraDevices, useFrameProcessor } from 'react-native-vision-camera';
70
- import { faceAntiSpoofFrameProcessor, initializeFaceAntiSpoof } from 'react-native-vision-camera-spoof-detector';
71
- import { runOnJS } from 'react-native-reanimated';
72
-
73
- export default function App() {
74
- const devices = useCameraDevices();
75
- const device = devices.front;
76
- const [spoofResult, setSpoofResult] = useState(null);
77
-
78
- useEffect(() => {
79
- initializeFaceAntiSpoof().then((success) => {
80
- console.log('FaceAntiSpoof initialized:', success);
81
- });
82
- }, []);
83
-
84
- const frameProcessor = useFrameProcessor((frame) => {
85
- 'worklet';
86
- const result = faceAntiSpoofFrameProcessor(frame);
87
- if (result) {
88
- runOnJS(setSpoofResult)(result);
89
- }
90
- }, []);
91
-
92
- if (device == null) return <Text>Loading...</Text>;
93
-
94
- return (
95
- <View style={styles.container}>
96
- <Camera
97
- style={StyleSheet.absoluteFill}
98
- device={device}
99
- isActive={true}
100
- frameProcessor={frameProcessor}
101
- frameProcessorFps={5}
102
- />
103
- {spoofResult && (
104
- <View style={styles.resultContainer}>
105
- <Text style={styles.resultText}>
106
- Is Live: {spoofResult.isLive ? 'Yes' : 'No'}
107
- </Text>
108
- <Text style={styles.resultText}>
109
- Score: {spoofResult.neuralNetworkScore?.toFixed(2)}
110
- </Text>
111
- <Text style={styles.resultText}>
112
- Label: {spoofResult.label}
113
- </Text>
114
- </View>
115
- )}
116
- </View>
117
- );
118
- }
119
-
120
- const styles = StyleSheet.create({
121
- container: { flex: 1 },
122
- resultContainer: {
123
- position: 'absolute',
124
- bottom: 50,
125
- left: 0,
126
- right: 0,
127
- alignItems: 'center',
128
- backgroundColor: 'rgba(0,0,0,0.5)',
129
- padding: 10,
130
- },
131
- resultText: {
132
- color: 'white',
133
- fontSize: 20,
134
- fontWeight: 'bold',
135
- },
136
- });
137
- ```
138
-
139
- ### Advanced Usage with Full Feature Set
140
-
141
- ```javascript
142
- import { useCallback, useMemo, useEffect, useRef } from 'react';
143
- import { Worklets } from 'react-native-worklets-core';
144
- import { useFrameProcessor } from 'react-native-vision-camera';
145
- import { useFaceDetector } from 'react-native-vision-camera-face-detector';
146
- import {
147
- faceAntiSpoofFrameProcessor,
148
- initializeFaceAntiSpoof,
149
- isFaceAntiSpoofAvailable,
150
- } from 'react-native-vision-camera-spoof-detector';
151
-
152
- const useFaceDetectionFrameProcessor = ({
153
- onStableFaceDetected = () => { },
154
- onFacesUpdate = () => { },
155
- onLivenessUpdate = () => { },
156
- onAntiSpoofUpdate = () => { },
157
- showCodeScanner = false,
158
- isLoading = false,
159
- isActive = true,
160
- livenessLevel = 0,
161
- antispooflevel = 0.35,
162
- }) => {
163
- const { detectFaces } = useFaceDetector({
164
- performanceMode: 'fast',
165
- landmarkMode: 'none',
166
- contourMode: 'none',
167
- classificationMode: livenessLevel === 1 ? 'all' : 'none',
168
- minFaceSize: 0.2,
169
- });
170
-
171
- const isMounted = useRef(true);
172
- const antiSpoofInitialized = useRef(false);
173
-
174
- const initializeAntiSpoof = useCallback(async () => {
175
- if (antiSpoofInitialized.current) return true;
176
- try {
177
- const available = isFaceAntiSpoofAvailable?.();
178
- if (!available) return false;
179
- await initializeFaceAntiSpoof();
180
- antiSpoofInitialized.current = true;
181
- return true;
182
- } catch (err) {
183
- console.error('Anti-spoof initialization error:', err);
184
- return false;
185
- }
186
- }, []);
187
-
188
- useEffect(() => {
189
- initializeAntiSpoof();
190
- }, [initializeAntiSpoof]);
191
-
192
- // Shared state for face tracking
193
- const sharedState = useMemo(
194
- () =>
195
- Worklets.createSharedValue({
196
- flags: {
197
- captured: false,
198
- showCodeScanner: showCodeScanner,
199
- isActive: isActive,
200
- hasSingleFace: false,
201
- isFaceCentered: false,
202
- },
203
- antiSpoof: {
204
- isLive: false,
205
- confidence: 0,
206
- consecutiveLiveFrames: 0,
207
- },
208
- }),
209
- []
210
- );
211
-
212
- const frameProcessor = useFrameProcessor(
213
- (frame) => {
214
- 'worklet';
215
-
216
- try {
217
- const detected = detectFaces?.(frame);
218
-
219
- if (!detected || detected.length === 0) {
220
- onFacesUpdate?.({ count: 0, progress: 0 });
221
- return;
222
- }
223
-
224
- if (detected.length === 1 && !sharedState.value.flags.captured) {
225
- const antiSpoofResult = faceAntiSpoofFrameProcessor?.(frame);
226
-
227
- if (antiSpoofResult?.isLive) {
228
- sharedState.value.antiSpoof.isLive = true;
229
- sharedState.value.antiSpoof.confidence = antiSpoofResult.combinedScore;
230
- onAntiSpoofUpdate?.({
231
- isLive: true,
232
- confidence: antiSpoofResult.combinedScore,
233
- });
234
- }
235
-
236
- onFacesUpdate?.({ count: 1, progress: 50 });
237
- } else {
238
- onFacesUpdate?.({ count: detected.length, progress: 0 });
239
- }
240
- } catch (err) {
241
- console.error('Frame processing error:', err);
242
- } finally {
243
- frame.release?.();
244
- }
245
- },
246
- [detectFaces, isLoading]
247
- );
248
-
249
- return {
250
- frameProcessor,
251
- sharedState,
252
- initializeAntiSpoof,
253
- };
254
- };
255
-
256
- export default useFaceDetectionFrameProcessor;
257
- ```
258
-
259
- ## 📚 API Reference
260
-
261
- ### `initializeFaceAntiSpoof()`
262
-
263
- Initializes the face anti-spoofing module. Must be called before using the frame processor.
264
-
265
- ```javascript
266
- const success = await initializeFaceAntiSpoof();
267
- ```
268
-
269
- **Returns**: `Promise<boolean>` - True if successful
270
-
271
- ---
272
-
273
- ### `isFaceAntiSpoofAvailable()`
274
-
275
- Checks if the module is available on the device.
276
-
277
- ```javascript
278
- const available = isFaceAntiSpoofAvailable();
279
- ```
280
-
281
- **Returns**: `boolean`
282
-
283
- ---
284
-
285
- ### `faceAntiSpoofFrameProcessor(frame)`
286
-
287
- Process frame and get anti-spoofing result.
288
-
289
- ```javascript
290
- const result = faceAntiSpoofFrameProcessor(frame);
291
- ```
292
-
293
- **Parameters**: `frame` (Vision Camera Frame)
294
-
295
- **Returns**: `FaceAntiSpoofingResult | null`
296
-
297
- ### `FaceAntiSpoofingResult`
298
-
299
- ```typescript
300
- interface FaceAntiSpoofingResult {
301
- isLive: boolean; // Real face (true) or spoof (false)
302
- label: string; // "Live Face" or "Spoof Face"
303
- neuralNetworkScore: number; // 0.0-1.0 confidence
304
- laplacianScore: number; // Image quality score
305
- combinedScore: number; // Weighted average
306
- error?: string; // Error message if any
307
- }
308
- ```
309
-
310
- ## 🔧 Configuration
311
-
312
- ```javascript
313
- // Anti-spoofing sensitivity (0.0-1.0, lower = more lenient)
314
- const antispooflevel = 0.35;
315
-
316
- // Liveness verification mode
317
- // 0: Anti-spoofing only
318
- // 1: Anti-spoofing + blink detection
319
- const livenessLevel = 1;
320
-
321
- // Customizable thresholds
322
- const FACE_STABILITY_THRESHOLD = 3; // Frames for stable face
323
- const FACE_MOVEMENT_THRESHOLD = 15; // Max pixel movement
324
- const BLINK_THRESHOLD = 0.3; // Eye closure probability
325
- const REQUIRED_BLINKS = 3; // Blinks for liveness
326
- const REQUIRED_CONSECUTIVE_LIVE_FRAMES = 3; // Consecutive live frames
327
- const REAL_LAPLACIAN_THRESHOLD = 3500; // Image quality threshold
328
- const FACE_CENTER_THRESHOLD_X = 0.2; // X-axis tolerance
329
- const FACE_CENTER_THRESHOLD_Y = 0.15; // Y-axis tolerance
330
- ```
331
-
332
- ## 🎮 Complete Examples
333
-
334
- Check the [examples](./examples) folder for:
335
- - Basic anti-spoofing detection
336
- - Face detection with liveness
337
- - Complete capture flow
338
- - UI components and feedback
339
-
340
- ## 🔍 Attack Detection Capabilities
341
-
342
- The module detects and prevents:
343
- - ✅ Print attacks (photos)
344
- - ✅ Display attacks (screens/tablets)
345
- - ✅ Mask attacks (with blink detection)
346
- - ✅ Replay attacks (videos)
347
-
348
- Performance depends on:
349
- - Image quality
350
- - Lighting conditions
351
- - Face angle and positioning
352
- - Device camera specs
353
-
354
- ## ⚙️ Performance Tips
355
-
356
- 1. Use `performanceMode: 'fast'` in Face Detector
357
- 2. Module automatically batches state updates
358
- 3. Adjust `FRAME_PROCESSOR_MIN_INTERVAL_MS` as needed
359
- 4. GPU acceleration is used automatically when available
360
- 5. Proper frame release prevents memory leaks
361
-
362
- ## 📱 Platform Support
363
-
364
- | Platform | Status | GPU | Notes |
365
- |----------|--------|-----|-------|
366
- | Android | ✅ Supported | Yes | Fully optimized |
367
- | iOS | ⏳ In Progress | Yes | Coming soon |
368
- | Web | ❌ No | N/A | Not applicable |
369
-
370
- ## 🐛 Troubleshooting
371
-
372
- **Module won't initialize**
373
- ```javascript
374
- const available = isFaceAntiSpoofAvailable();
375
- if (!available) {
376
- console.log('Not available on this device');
377
- }
378
- ```
379
-
380
- **Low accuracy**
381
- - Check lighting conditions
382
- - Ensure face is centered
383
- - Adjust `antispooflevel` parameter
384
- - Verify TensorFlow Lite models are bundled
385
-
386
- **Performance issues**
387
- - Reduce frame processing frequency
388
- - Use lower camera resolution
389
- - Enable fast performance mode
390
- - Check device temperature
391
-
392
- **Face detection fails**
393
- - Ensure clear face visibility
394
- - Check camera permissions
395
- - Verify sufficient lighting
396
- - Check minimum face size threshold
397
-
398
- ## 📖 Documentation
399
-
400
- - [Complete API Documentation](./.docs/API.md)
401
- - [Migration Guide](./.docs/MIGRATION.md)
402
- - [Best Practices](./.docs/BEST_PRACTICES.md)
403
- - [Comprehensive Example](./examples/CompleteExampleApp.tsx)
404
-
405
- ## 🤝 Contributing
406
-
407
- Contributions welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
408
-
409
- ## 📄 License
410
-
411
- JESCON TECHNOLOGIES PVT LTD License - see [LICENSE](./LICENSE) file for details.
412
-
413
- ## 👨‍💼 Author
414
-
415
- **PRAFULDAS M M**
416
- - Company: JESCON TECHNOLOGIES PVT LTD
417
- - Location: Thrissur, Kerala, India
418
- - Email: jescontechnologies@gmail.com
419
-
420
- ## 🔗 Quick Links
421
-
422
- - [NPM Package](https://www.npmjs.com/package/react-native-vision-camera-spoof-detector)
423
- - [GitHub Repository](https://github.com/dpraful/react-native-vision-camera-spoof-detector)
424
- - [React Native Vision Camera](https://react-native-vision-camera.com)
425
- - [TensorFlow Lite](https://www.tensorflow.org/lite)
426
-
427
- ## 📞 Support & Community
428
-
429
- - 🐛 [Report Issues](https://github.com/dpraful/react-native-vision-camera-spoof-detector/issues)
430
- - 💬 [GitHub Discussions](https://github.com/dpraful/react-native-vision-camera-spoof-detector/discussions)
431
- - 📧 Email: jescontechnologies@gmail.com
432
-
433
- ## 🙏 Acknowledgments
434
-
435
- Built with:
436
- - [TensorFlow Lite](https://www.tensorflow.org/lite)
437
- - [React Native Vision Camera](https://react-native-vision-camera.com)
438
- - [React Native Worklets](https://docs.swmansion.com/react-native-worklets/)
439
-
440
- ---
441
-
442
- Made with ❤️ by JESCON TECHNOLOGIES PVT LTD
1
+ # react-native-vision-camera-spoof-detector
2
+
3
+ [![npm version](https://badge.fury.io/js/react-native-vision-camera-spoof-detector.svg)](https://badge.fury.io/js/react-native-vision-camera-spoof-detector)
4
+ [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue)](https://github.com/dpraful/react-native-vision-camera-spoof-detector)
5
+
6
+ High-performance face anti-spoofing and liveness detection module for React Native Vision Camera. Features TensorFlow Lite with GPU acceleration, optimized YUV processing, and real-time blink detection for robust liveness verification.
7
+
8
+ ## 🎯 Features
9
+
10
+ - **🚀 Real-time Performance**: GPU-accelerated TensorFlow Lite processing for smooth 60fps detection
11
+ - **🎯 High Accuracy**: Advanced ML models for distinguishing live faces from spoofing attempts
12
+ - **👁️ Blink Detection**: Native blink detection for enhanced liveness verification
13
+ - **📱 Optimized YUV Processing**: Efficient image data handling for React Native
14
+ - **🔧 Easy Integration**: Seamlessly integrates with `react-native-vision-camera`
15
+ - **⚡ Face Stability Tracking**: Automatic stable face detection with customizable thresholds
16
+ - **🛡️ Face Centering**: Intelligent face positioning validation in frame
17
+ - **📊 Anti-spoofing Confidence**: Detailed confidence scores with multiple detection models
18
+ - **🔄 Batched Updates**: Optimized state management with minimal re-renders
19
+
20
+ ## 📋 Requirements
21
+
22
+ - React Native >= 0.60.0
23
+ - react-native-vision-camera >= 4.6.4
24
+ - react-native-reanimated >= 3.0.0
25
+ - react-native-worklets-core >= 1.0.0
26
+ - react-native-vision-camera-face-detector (optional, for enhanced features)
27
+
28
+ ## 📦 Installation
29
+
30
+ ### Step 1: Install the package
31
+
32
+ ```bash
33
+ npm install react-native-vision-camera-spoof-detector
34
+ # or
35
+ yarn add react-native-vision-camera-spoof-detector
36
+ ```
37
+
38
+ ### Step 2: Install peer dependencies
39
+
40
+ ```bash
41
+ npm install react-native-vision-camera react-native-reanimated react-native-worklets-core
42
+ # or
43
+ yarn add react-native-vision-camera react-native-reanimated react-native-worklets-core
44
+ ```
45
+
46
+ ### Step 3: Configure Android (if not auto-linked)
47
+
48
+ Add to `android/app/build.gradle`:
49
+
50
+ ```gradle
51
+ dependencies {
52
+ implementation project(':react-native-vision-camera-spoof-detector')
53
+ }
54
+ ```
55
+
56
+ ### Step 4: Link native module (for React Native < 0.60)
57
+
58
+ ```bash
59
+ react-native link react-native-vision-camera-spoof-detector
60
+ ```
61
+
62
+ ## 🚀 Quick Start
63
+
64
+ ### Simple Usage
65
+
66
+ ```javascript
67
+ import React, { useEffect, useState } from 'react';
68
+ import { StyleSheet, Text, View } from 'react-native';
69
+ import { Camera, useCameraDevices, useFrameProcessor } from 'react-native-vision-camera';
70
+ import { faceAntiSpoofFrameProcessor, initializeFaceAntiSpoof } from 'react-native-vision-camera-spoof-detector';
71
+ import { runOnJS } from 'react-native-reanimated';
72
+
73
+ export default function App() {
74
+ const devices = useCameraDevices();
75
+ const device = devices.front;
76
+ const [spoofResult, setSpoofResult] = useState(null);
77
+
78
+ useEffect(() => {
79
+ initializeFaceAntiSpoof().then((success) => {
80
+ console.log('FaceAntiSpoof initialized:', success);
81
+ });
82
+ }, []);
83
+
84
+ const frameProcessor = useFrameProcessor((frame) => {
85
+ 'worklet';
86
+ const result = faceAntiSpoofFrameProcessor(frame);
87
+ if (result) {
88
+ runOnJS(setSpoofResult)(result);
89
+ }
90
+ }, []);
91
+
92
+ if (device == null) return <Text>Loading...</Text>;
93
+
94
+ return (
95
+ <View style={styles.container}>
96
+ <Camera
97
+ style={StyleSheet.absoluteFill}
98
+ device={device}
99
+ isActive={true}
100
+ frameProcessor={frameProcessor}
101
+ frameProcessorFps={5}
102
+ />
103
+ {spoofResult && (
104
+ <View style={styles.resultContainer}>
105
+ <Text style={styles.resultText}>
106
+ Is Live: {spoofResult.isLive ? 'Yes' : 'No'}
107
+ </Text>
108
+ <Text style={styles.resultText}>
109
+ Score: {spoofResult.neuralNetworkScore?.toFixed(2)}
110
+ </Text>
111
+ <Text style={styles.resultText}>
112
+ Label: {spoofResult.label}
113
+ </Text>
114
+ </View>
115
+ )}
116
+ </View>
117
+ );
118
+ }
119
+
120
+ const styles = StyleSheet.create({
121
+ container: { flex: 1 },
122
+ resultContainer: {
123
+ position: 'absolute',
124
+ bottom: 50,
125
+ left: 0,
126
+ right: 0,
127
+ alignItems: 'center',
128
+ backgroundColor: 'rgba(0,0,0,0.5)',
129
+ padding: 10,
130
+ },
131
+ resultText: {
132
+ color: 'white',
133
+ fontSize: 20,
134
+ fontWeight: 'bold',
135
+ },
136
+ });
137
+ ```
138
+
139
+ ### Advanced Usage with Full Feature Set
140
+
141
+ ```javascript
142
+ import { useCallback, useMemo, useEffect, useRef } from 'react';
143
+ import { Worklets } from 'react-native-worklets-core';
144
+ import { useFrameProcessor } from 'react-native-vision-camera';
145
+ import { useFaceDetector } from 'react-native-vision-camera-face-detector';
146
+ import {
147
+ faceAntiSpoofFrameProcessor,
148
+ initializeFaceAntiSpoof,
149
+ isFaceAntiSpoofAvailable,
150
+ } from 'react-native-vision-camera-spoof-detector';
151
+
152
+ const useFaceDetectionFrameProcessor = ({
153
+ onStableFaceDetected = () => { },
154
+ onFacesUpdate = () => { },
155
+ onLivenessUpdate = () => { },
156
+ onAntiSpoofUpdate = () => { },
157
+ showCodeScanner = false,
158
+ isLoading = false,
159
+ isActive = true,
160
+ livenessLevel = 0,
161
+ antispooflevel = 0.35,
162
+ }) => {
163
+ const { detectFaces } = useFaceDetector({
164
+ performanceMode: 'fast',
165
+ landmarkMode: 'none',
166
+ contourMode: 'none',
167
+ classificationMode: livenessLevel === 1 ? 'all' : 'none',
168
+ minFaceSize: 0.2,
169
+ });
170
+
171
+ const isMounted = useRef(true);
172
+ const antiSpoofInitialized = useRef(false);
173
+
174
+ const initializeAntiSpoof = useCallback(async () => {
175
+ if (antiSpoofInitialized.current) return true;
176
+ try {
177
+ const available = isFaceAntiSpoofAvailable?.();
178
+ if (!available) return false;
179
+ await initializeFaceAntiSpoof();
180
+ antiSpoofInitialized.current = true;
181
+ return true;
182
+ } catch (err) {
183
+ console.error('Anti-spoof initialization error:', err);
184
+ return false;
185
+ }
186
+ }, []);
187
+
188
+ useEffect(() => {
189
+ initializeAntiSpoof();
190
+ }, [initializeAntiSpoof]);
191
+
192
+ // Shared state for face tracking
193
+ const sharedState = useMemo(
194
+ () =>
195
+ Worklets.createSharedValue({
196
+ flags: {
197
+ captured: false,
198
+ showCodeScanner: showCodeScanner,
199
+ isActive: isActive,
200
+ hasSingleFace: false,
201
+ isFaceCentered: false,
202
+ },
203
+ antiSpoof: {
204
+ isLive: false,
205
+ confidence: 0,
206
+ consecutiveLiveFrames: 0,
207
+ },
208
+ }),
209
+ []
210
+ );
211
+
212
+ const frameProcessor = useFrameProcessor(
213
+ (frame) => {
214
+ 'worklet';
215
+
216
+ try {
217
+ const detected = detectFaces?.(frame);
218
+
219
+ if (!detected || detected.length === 0) {
220
+ onFacesUpdate?.({ count: 0, progress: 0 });
221
+ return;
222
+ }
223
+
224
+ if (detected.length === 1 && !sharedState.value.flags.captured) {
225
+ const antiSpoofResult = faceAntiSpoofFrameProcessor?.(frame);
226
+
227
+ if (antiSpoofResult?.isLive) {
228
+ sharedState.value.antiSpoof.isLive = true;
229
+ sharedState.value.antiSpoof.confidence = antiSpoofResult.combinedScore;
230
+ onAntiSpoofUpdate?.({
231
+ isLive: true,
232
+ confidence: antiSpoofResult.combinedScore,
233
+ });
234
+ }
235
+
236
+ onFacesUpdate?.({ count: 1, progress: 50 });
237
+ } else {
238
+ onFacesUpdate?.({ count: detected.length, progress: 0 });
239
+ }
240
+ } catch (err) {
241
+ console.error('Frame processing error:', err);
242
+ } finally {
243
+ frame.release?.();
244
+ }
245
+ },
246
+ [detectFaces, isLoading]
247
+ );
248
+
249
+ return {
250
+ frameProcessor,
251
+ sharedState,
252
+ initializeAntiSpoof,
253
+ };
254
+ };
255
+
256
+ export default useFaceDetectionFrameProcessor;
257
+ ```
258
+
259
+ ## 📚 API Reference
260
+
261
+ ### `initializeFaceAntiSpoof()`
262
+
263
+ Initializes the face anti-spoofing module. Must be called before using the frame processor.
264
+
265
+ ```javascript
266
+ const success = await initializeFaceAntiSpoof();
267
+ ```
268
+
269
+ **Returns**: `Promise<boolean>` - True if successful
270
+
271
+ ---
272
+
273
+ ### `isFaceAntiSpoofAvailable()`
274
+
275
+ Checks if the module is available on the device.
276
+
277
+ ```javascript
278
+ const available = isFaceAntiSpoofAvailable();
279
+ ```
280
+
281
+ **Returns**: `boolean`
282
+
283
+ ---
284
+
285
+ ### `faceAntiSpoofFrameProcessor(frame)`
286
+
287
+ Process frame and get anti-spoofing result.
288
+
289
+ ```javascript
290
+ const result = faceAntiSpoofFrameProcessor(frame);
291
+ ```
292
+
293
+ **Parameters**: `frame` (Vision Camera Frame)
294
+
295
+ **Returns**: `FaceAntiSpoofingResult | null`
296
+
297
+ ### `FaceAntiSpoofingResult`
298
+
299
+ ```typescript
300
+ interface FaceAntiSpoofingResult {
301
+ isLive: boolean; // Real face (true) or spoof (false)
302
+ label: string; // "Live Face" or "Spoof Face"
303
+ neuralNetworkScore: number; // 0.0-1.0 confidence
304
+ laplacianScore: number; // Image quality score
305
+ combinedScore: number; // Weighted average
306
+ error?: string; // Error message if any
307
+ }
308
+ ```
309
+
310
+ ## 🔧 Configuration
311
+
312
+ ```javascript
313
+ // Anti-spoofing sensitivity (0.0-1.0, lower = more lenient)
314
+ const antispooflevel = 0.35;
315
+
316
+ // Liveness verification mode
317
+ // 0: Anti-spoofing only
318
+ // 1: Anti-spoofing + blink detection
319
+ const livenessLevel = 1;
320
+
321
+ // Customizable thresholds
322
+ const FACE_STABILITY_THRESHOLD = 3; // Frames for stable face
323
+ const FACE_MOVEMENT_THRESHOLD = 15; // Max pixel movement
324
+ const BLINK_THRESHOLD = 0.3; // Eye closure probability
325
+ const REQUIRED_BLINKS = 3; // Blinks for liveness
326
+ const REQUIRED_CONSECUTIVE_LIVE_FRAMES = 3; // Consecutive live frames
327
+ const REAL_LAPLACIAN_THRESHOLD = 3500; // Image quality threshold
328
+ const FACE_CENTER_THRESHOLD_X = 0.2; // X-axis tolerance
329
+ const FACE_CENTER_THRESHOLD_Y = 0.15; // Y-axis tolerance
330
+ ```
331
+
332
+ ## 🎮 Complete Examples
333
+
334
+ Check the [examples](./examples) folder for:
335
+ - Basic anti-spoofing detection
336
+ - Face detection with liveness
337
+ - Complete capture flow
338
+ - UI components and feedback
339
+
340
+ ## 🔍 Attack Detection Capabilities
341
+
342
+ The module detects and prevents:
343
+ - ✅ Print attacks (photos)
344
+ - ✅ Display attacks (screens/tablets)
345
+ - ✅ Mask attacks (with blink detection)
346
+ - ✅ Replay attacks (videos)
347
+
348
+ Performance depends on:
349
+ - Image quality
350
+ - Lighting conditions
351
+ - Face angle and positioning
352
+ - Device camera specs
353
+
354
+ ## ⚙️ Performance Tips
355
+
356
+ 1. Use `performanceMode: 'fast'` in Face Detector
357
+ 2. Module automatically batches state updates
358
+ 3. Adjust `FRAME_PROCESSOR_MIN_INTERVAL_MS` as needed
359
+ 4. GPU acceleration is used automatically when available
360
+ 5. Proper frame release prevents memory leaks
361
+
362
+ ## 📱 Platform Support
363
+
364
+ | Platform | Status | GPU | Notes |
365
+ |----------|--------|-----|-------|
366
+ | Android | ✅ Supported | Yes | Fully optimized |
367
+ | iOS | ⏳ In Progress | Yes | Coming soon |
368
+ | Web | ❌ No | N/A | Not applicable |
369
+
370
+ ## 🐛 Troubleshooting
371
+
372
+ **Module won't initialize**
373
+ ```javascript
374
+ const available = isFaceAntiSpoofAvailable();
375
+ if (!available) {
376
+ console.log('Not available on this device');
377
+ }
378
+ ```
379
+
380
+ **Low accuracy**
381
+ - Check lighting conditions
382
+ - Ensure face is centered
383
+ - Adjust `antispooflevel` parameter
384
+ - Verify TensorFlow Lite models are bundled
385
+
386
+ **Performance issues**
387
+ - Reduce frame processing frequency
388
+ - Use lower camera resolution
389
+ - Enable fast performance mode
390
+ - Check device temperature
391
+
392
+ **Face detection fails**
393
+ - Ensure clear face visibility
394
+ - Check camera permissions
395
+ - Verify sufficient lighting
396
+ - Check minimum face size threshold
397
+
398
+ ## 📖 Documentation
399
+
400
+ - [Complete API Documentation](./.docs/API.md)
401
+ - [Migration Guide](./.docs/MIGRATION.md)
402
+ - [Best Practices](./.docs/BEST_PRACTICES.md)
403
+ - [Comprehensive Example](./examples/CompleteExampleApp.tsx)
404
+
405
+ ## 🤝 Contributing
406
+
407
+ Contributions welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
408
+
409
+ ## 📄 License
410
+
411
+ JESCON TECHNOLOGIES PVT LTD License - see [LICENSE](./LICENSE) file for details.
412
+
413
+ ## 👨‍💼 Author
414
+
415
+ **PRAFULDAS M M**
416
+ - Company: JESCON TECHNOLOGIES PVT LTD
417
+ - Location: Thrissur, Kerala, India
418
+ - Email: jescontechnologies@gmail.com
419
+
420
+ ## 🔗 Quick Links
421
+
422
+ - [NPM Package](https://www.npmjs.com/package/react-native-vision-camera-spoof-detector)
423
+ - [GitHub Repository](https://github.com/dpraful/react-native-vision-camera-spoof-detector)
424
+ - [React Native Vision Camera](https://react-native-vision-camera.com)
425
+ - [TensorFlow Lite](https://www.tensorflow.org/lite)
426
+
427
+ ## 📞 Support & Community
428
+
429
+ - 🐛 [Report Issues](https://github.com/dpraful/react-native-vision-camera-spoof-detector/issues)
430
+ - 💬 [GitHub Discussions](https://github.com/dpraful/react-native-vision-camera-spoof-detector/discussions)
431
+ - 📧 Email: jescontechnologies@gmail.com
432
+
433
+ ## 🙏 Acknowledgments
434
+
435
+ Built with:
436
+ - [TensorFlow Lite](https://www.tensorflow.org/lite)
437
+ - [React Native Vision Camera](https://react-native-vision-camera.com)
438
+ - [React Native Worklets](https://docs.swmansion.com/react-native-worklets/)
439
+
440
+ ---
441
+
442
+ Made with ❤️ by JESCON TECHNOLOGIES PVT LTD