This commit is contained in:
2026-09-24 16:25:22 +08:00
commit 7428184f01
1198 changed files with 314515 additions and 0 deletions
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
</dict>
</plist>
@@ -0,0 +1,355 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>GoogleMVFaceDetectorResources.bundle/BCLjoy_200.emd</key>
<data>
96Uw5p4tLIiDbN11Du0p0c5xqE8=
</data>
<key>GoogleMVFaceDetectorResources.bundle/BCLlefteyeclosed_200.emd</key>
<data>
KBTvwnLXsoe2PIlGUwZzMUOp5k8=
</data>
<key>GoogleMVFaceDetectorResources.bundle/BCLrighteyeclosed_200.emd</key>
<data>
fW6O7h6Je5DNmNrbOeCGmAixyLI=
</data>
<key>GoogleMVFaceDetectorResources.bundle/Info.plist</key>
<data>
sS7uhwBl1ZXssfZceNWmGpZYct0=
</data>
<key>GoogleMVFaceDetectorResources.bundle/LMprec_600.emd</key>
<data>
trY9XrpS4DxHzs3eHljZHIJNHrI=
</data>
<key>GoogleMVFaceDetectorResources.bundle/MFT_fssd_accgray.pb</key>
<data>
tq7fRawRQ359i/c0FEVvpQ6Oee0=
</data>
<key>GoogleMVFaceDetectorResources.bundle/MFT_fssd_fastgray.pb</key>
<data>
DP+qJf0czliL6znGLVx90ASNzCY=
</data>
<key>GoogleMVFaceDetectorResources.bundle/blazeface.tfl</key>
<data>
oseYQ/EQxo7JsNpdNgo4YVLh7a4=
</data>
<key>GoogleMVFaceDetectorResources.bundle/contours.tfl</key>
<data>
PaAh9+zFw3Is4fLMn5iQsLG5M34=
</data>
<key>GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_gray_v1.tflite</key>
<data>
VCp0NyrYJWQnYbGaxVv0Vzy0IeA=
</data>
<key>GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_v1.tflite</key>
<data>
AHaxev+fV4YGoIDboAUFlxfISmY=
</data>
<key>GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_gray_v1.tflite</key>
<data>
Rd53RFFpKHZNvbiDaE2p4XxjbY0=
</data>
<key>GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_v1.tflite</key>
<data>
RxtbTN3LjpFChp3tmniX3KD+dsE=
</data>
<key>Headers/unimoduleXFacedetection-Swift.h</key>
<data>
BgxJ1I5k5MMBQ6xo5tZUy5d60tQ=
</data>
<key>Headers/unimoduleXFacedetection.h</key>
<data>
FH2SRnQAHIO8AbDZPa5/Bz/CcdA=
</data>
<key>Info.plist</key>
<data>
PAgX/P+2Nr5qTH+62odWUCKos8k=
</data>
<key>Modules/module.modulemap</key>
<data>
Zs/pbohrSFVhBYtMd56wG2K8w+s=
</data>
<key>Modules/unimoduleXFacedetection.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo</key>
<data>
aS63R8pVNYw0JVr4ejn70VPlNUc=
</data>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
<data>
VR3vMqk9fyleB4pmV+rgX1OX9F4=
</data>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
<data>
y73yJ903XXHaZ0v6wemdBjTKYF0=
</data>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
<data>
qliuAzBQoC+dStdbKgiR0WqcTV0=
</data>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
<data>
y73yJ903XXHaZ0v6wemdBjTKYF0=
</data>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
<data>
eXYli4ct9KFQLJTu7d0hBYsH/xw=
</data>
<key>config.json</key>
<data>
CzGjQQN8WuE+yTnq013U9m0usAM=
</data>
</dict>
<key>files2</key>
<dict>
<key>GoogleMVFaceDetectorResources.bundle/BCLjoy_200.emd</key>
<dict>
<key>hash2</key>
<data>
8A8lZEpijnOMFV9JPQcq8UPyU8v5nwi/SCnL5dT0NRw=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/BCLlefteyeclosed_200.emd</key>
<dict>
<key>hash2</key>
<data>
0xIT5PJf+LIXgeeG/YnO3lkX75s/vlC99V1IOvE27e0=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/BCLrighteyeclosed_200.emd</key>
<dict>
<key>hash2</key>
<data>
Y8oL2DjlGXdImtrbgKC+AWxaoLe2kPvDiaBkWqzP5P8=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/Info.plist</key>
<dict>
<key>hash2</key>
<data>
kLtzThegQhDjMdMnp21m/n5y4M/GWaJBT3DF395jFL0=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/LMprec_600.emd</key>
<dict>
<key>hash2</key>
<data>
DtXIUoL5QNFKVyOmwK8F+cKr1Okww8TwvloHI203QRE=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/MFT_fssd_accgray.pb</key>
<dict>
<key>hash2</key>
<data>
8K2wTXshtNmImTKmLw7/En7tsn0vhTQqkBRBU8oLgbE=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/MFT_fssd_fastgray.pb</key>
<dict>
<key>hash2</key>
<data>
CUNCXfGzUODFinvmaL4flC6sM4wZjhpPFoWco+Eif0U=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/blazeface.tfl</key>
<dict>
<key>hash2</key>
<data>
TyXMFC6WtfIbMjbSFmwuZikgaB8dI5QtJRDpjIr27Nw=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/contours.tfl</key>
<dict>
<key>hash2</key>
<data>
hBYLwMSnSVF+Yvk8ssaKuP9J3lcfcOttFgJUypoHicA=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_gray_v1.tflite</key>
<dict>
<key>hash2</key>
<data>
ekzwnGrkp1gUTUK/NbmiapWYfjxYQdDcORCVaYKZ2as=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/fssd_100_8bit_v1.tflite</key>
<dict>
<key>hash2</key>
<data>
OvuTDu3I0dQENEgCgdO16M7EwwTlLTT9/IqVCDQLtxk=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_gray_v1.tflite</key>
<dict>
<key>hash2</key>
<data>
IVEbvtJxoKkri5ORjg+I9u+70RWjbRVV8GHO4TH2qzw=
</data>
</dict>
<key>GoogleMVFaceDetectorResources.bundle/fssd_25_8bit_v1.tflite</key>
<dict>
<key>hash2</key>
<data>
2pAlL0mzu5QuX4gBgKFFYfZpKW5/s+3s3quqi2u3gio=
</data>
</dict>
<key>Headers/unimoduleXFacedetection-Swift.h</key>
<dict>
<key>hash2</key>
<data>
rTildwV5zLFcxijbFWhzuO4YvO9LA74X/7lz8WuQqJU=
</data>
</dict>
<key>Headers/unimoduleXFacedetection.h</key>
<dict>
<key>hash2</key>
<data>
XAsze1m7Z4PhyI2gj+RafZVS4xyqWjgvqraTawdVPMY=
</data>
</dict>
<key>Modules/module.modulemap</key>
<dict>
<key>hash2</key>
<data>
mktK2hAXHkebM3pE/qIOCLCiT0PsQ+hRCZ1j7Cbvxf4=
</data>
</dict>
<key>Modules/unimoduleXFacedetection.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo</key>
<dict>
<key>hash2</key>
<data>
J9NnQTKtAGGpoVeYKyZw5c4MV06RKpL8Al+SnPwYZdA=
</data>
</dict>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.abi.json</key>
<dict>
<key>hash2</key>
<data>
q82Bl78THFBZ+ZocAvtg3vOuP28SaJ8euEkpbaHmZRA=
</data>
</dict>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface</key>
<dict>
<key>hash2</key>
<data>
M+3tx0iPWvL/1tT7IYkaDX1waVEMZ0IyQGmfsPV4JNQ=
</data>
</dict>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
<dict>
<key>hash2</key>
<data>
WjiHhAVADf0QcXgeRlnwqWksqonEUfqUD8RRV4E3hd8=
</data>
</dict>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
<dict>
<key>hash2</key>
<data>
M+3tx0iPWvL/1tT7IYkaDX1waVEMZ0IyQGmfsPV4JNQ=
</data>
</dict>
<key>Modules/unimoduleXFacedetection.swiftmodule/x86_64-apple-ios-simulator.swiftmodule</key>
<dict>
<key>hash2</key>
<data>
Yulvj7VnfZMMHAC7X3icMFcyuJ7FzZNFowozFX8vwpQ=
</data>
</dict>
<key>config.json</key>
<dict>
<key>hash2</key>
<data>
u75O7GUa7m6ue3dUjfs+U7kF97YboIw8B2A8pKZTLAo=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
@@ -0,0 +1,10 @@
{
"deploymentTarget": "12",
"dependencies-pods": [
{
"name": "GoogleMLKit/FaceDetection",
"version": "5.0.0"
}
]
}
@@ -0,0 +1,225 @@
import { AVCaptureSession, AVCaptureDevice, AVMediaType, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureDeviceInput, AVCaptureInput, AVCaptureVideoDataOutput, AVCaptureConnection, AVCaptureVideoPreviewLayer, AVLayerVideoGravity, AVCaptureVideoOrientation } from 'AVFoundation';
import { PHPhotoLibrary, PHAuthorizationStatus } from 'Photos';
import { CMSampleBuffer, CMSampleBufferGetFormatDescription, CMFormatDescription, CMVideoFormatDescriptionGetDimensions } from 'CoreMedia';
import { DispatchQueue } from "Dispatch"
import { UIView, UIImage, UIApplication, UIImageView, UILabel, UIViewController, UIFontDescriptor, UIFont, NSTextAlignment, UITapGestureRecognizer, UIImagePickerController, UIImagePickerControllerDelegate, UINavigationControllerDelegate } from 'UIKit';
import { CGRect, CGFloat, CGPoint } from 'CoreFoundation';
import { Face, FaceContour, FaceDetector, FaceDetectorOptions,FaceContourType,FaceLandmarkType, FaceLandmark,FaceDetectorPerformanceMode,FaceDetectorClassificationMode,FaceDetectorLandmarkMode } from "MLKitFaceDetection"
import { VisionImage } from "MLKit"
import { NotificationCenter, NSNotification, Notification } from 'Foundation';
import { Selector } from 'ObjectiveC';
import { Alignment } from 'ARKit';
import { CABasicAnimation } from 'QuartzCore';
import { Int,Float } from 'Swift';
import { XFACE_CHECK_OPTS, XFACE_EVENT_SUCCESS, XFACE_TEST_EYE_TYPE, XFACE_FACE_Direction, XFACE_EVENT_CHECK_SUCCESS } from "../interface.uts"
import { XFACE_CHECK_OPTS_REAL, getDefaultConfig } from "../libs/config.uts"
const checkFaceResult = (orimg:UIImage, faces : Array<Face>, callBack : (result : XFACE_EVENT_SUCCESS[]) => void) => {
const cfaces = [] as XFACE_EVENT_SUCCESS[]
// @ts-ignore
for (item in faces) {
// @ts-ignore
const face = item as Face;
let rightEye = { openNum: 0, isOpen: false } as XFACE_TEST_EYE_TYPE;
let leftEye = { openNum: 0, isOpen: false } as XFACE_TEST_EYE_TYPE;
// 眼睛
let rightEyeMark = face.landmark(ofType = FaceLandmarkType.rightEye)
let leftEyeMark = face.landmark(ofType = FaceLandmarkType.leftEye)
// 鼻子
let noseMark = face.landmark(ofType = FaceLandmarkType.noseBase)
// 耳朵
let rightEarMark = face.landmark(ofType = FaceLandmarkType.rightEar)
let leftEarMark = face.landmark(ofType = FaceLandmarkType.leftEar)
let rightEyeNum = face.rightEyeOpenProbability
let leftEyeNum = face.leftEyeOpenProbability
let isSmile = face.smilingProbability
let faceId = face.trackingID
if (rightEyeNum != null) {
rightEye.openNum = new Number(rightEyeNum) + 0;
rightEye.isOpen = new Number(rightEyeNum) > 0.7
}
if (leftEyeNum != null) {
leftEye.openNum = new Number(leftEyeNum)+ 0;
leftEye.isOpen = new Number(leftEyeNum) > 0.7
}
// 检测当前左,右,下,上
let faceRightLeft : XFACE_FACE_Direction = "center"
let faceUpDown : XFACE_FACE_Direction = "center"
let eulerX = face.headEulerAngleX; // 获取头部左右旋转角度
let eulerY = face.headEulerAngleY; // 获取头部上下俯仰角度
let eulerZ = face.headEulerAngleZ; // 获取头部上下俯仰角度
// 嘴巴
let leftMouth = face.landmark(ofType = FaceLandmarkType.mouthLeft)
let rightMouth = face.landmark(ofType = FaceLandmarkType.mouthRight)
let bottomMouth = face.landmark(ofType = FaceLandmarkType.mouthBottom)
let isMouthOpened = false
let ANGLE_THRESHOLD = 30; // 容差值
let ANGLE_HEAD_THRESHOLD = 0; // 容差值
let ANGLE_EYE_THRESHOLD = 6; // 眨眼的容差.
let allHeadBody = false;
if (Math.abs(Number(eulerY)) > ANGLE_THRESHOLD) { // 确保头部没有明显上下俯仰
faceRightLeft = eulerY > 0 ? 'left' : 'right';
}
if (Math.abs(Number(eulerX)) >= ANGLE_HEAD_THRESHOLD) { // 确保头部没有明显上下俯仰
faceUpDown = eulerY > 0 ? 'down' : 'up';
}
if (leftMouth != null && rightMouth != null && bottomMouth != null) {
let mouthWidth = rightMouth!.position.x - leftMouth!.position.x
let mouthHeight = bottomMouth!.position.y - ((leftMouth!.position.y + rightMouth!.position.y) / 2)
if (mouthHeight / mouthWidth > 0.4 && faceRightLeft == 'center') {
isMouthOpened = true;
} else {
isMouthOpened = false;
}
}
if(
leftMouth != null &&
rightMouth != null &&
bottomMouth != null &&
noseMark !=null&&
rightEarMark !=null&&
leftEarMark !=null&&
rightEyeMark !=null&&
leftEyeMark !=null
){
allHeadBody = true;
}
cfaces.push({
imgWidth: orimg.size.width,
imgHeight: orimg.size.height,
isSmile: isSmile == null ? false : (isSmile >= 0.8),
rightEye,
leftEye,
faceRightLeft,
faceUpDown,
isMouthOpened,
allHeadBody,
faceId:faceId!=null?(faceId+0):null
})
}
callBack(cfaces)
}
export function checkFaceByImage(config : XFACE_CHECK_OPTS | null = null){
const cfg = getDefaultConfig(config)
let options_s = FaceDetectorOptions()
options_s.performanceMode = FaceDetectorPerformanceMode.accurate
options_s.landmarkMode = FaceDetectorLandmarkMode.all
options_s.classificationMode = FaceDetectorClassificationMode.all
// @ts-ignore
uni.chooseImage({
count: 1,
// @ts-ignore
success(evt : ChooseImageSuccess) {
if (evt.tempFilePaths.length == 0) return;
const imgs = evt.tempFilePaths[0] as string;
const decodedPath = UTSiOS.convert2AbsFullPath(imgs)
let img = new UIImage(contentsOfFile = decodedPath);
let image = new VisionImage(image = img!);
let faceDetector = FaceDetector.faceDetector(options = options_s)
faceDetector.process(image as VisionImage,completion = (faces:Array<Face>|null,error:any|null)=>{
if(error != null||faces==null||(faces?.length??0)==0){
cfg.success({
images:[],
videoPath:"",
isPass:false
})
return;
}
const _faces = faces!;
checkFaceResult(img!, _faces, (result : XFACE_EVENT_SUCCESS[]) => {
DispatchQueue.main.async(execute = () : void => {
cfg.enter(result,JSON.stringify(result)!)
cfg.success({
isPass: true,
images: [decodedPath] as string[],
videoPath: ""
})
})
})
// for(item in faces!){
// const face = item as Face
// let leftEye = face.landmark(ofType = FaceLandmarkType.leftEye)
// if(leftEye!=null){
// let leftEyePosition = leftEye!.position
// console.log(leftEyePosition.x,'----',img!.size.width)
// }
// }
})
},
fail() {
cfg.fail("解析错误")
}
})
}
/**
* 提供外部图片地址检测当前图片是否存在人脸
*/
export function checkFaceByImageFromFilePath(config : XFACE_CHECK_OPTS) {
const cfg = getDefaultConfig(config)
const imgs = cfg.url;
const decodedPath = UTSiOS.convert2AbsFullPath(imgs!)
let img = new UIImage(contentsOfFile = decodedPath);
let image = new VisionImage(image = img!);
let options_s = FaceDetectorOptions()
options_s.performanceMode = FaceDetectorPerformanceMode.accurate
options_s.landmarkMode = FaceDetectorLandmarkMode.all
options_s.classificationMode = FaceDetectorClassificationMode.all
let faceDetector = FaceDetector.faceDetector(options = options_s)
faceDetector.process(image as VisionImage,completion = (faces:Array<Face>|null,error:any|null)=>{
if(error != null||faces==null||(faces?.length??0)==0){
cfg.success({
images:[],
videoPath:"",
isPass:false
})
return;
}
const _faces = faces!;
checkFaceResult(img!, _faces, (result : XFACE_EVENT_SUCCESS[]) => {
DispatchQueue.main.async(execute = () : void => {
cfg.enter(result,JSON.stringify(result)!)
cfg.success({
isPass: true,
images: [decodedPath] as string[],
videoPath: ""
})
})
})
})
}
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>我们需要您的相机权限来拍照或录像。</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要使用你的相册进行选择视频及图片</string>
</dict>
</plist>