이 기사에서는 프론트 엔드가 최근 Douyin에서 매우 인기가 있는 그림 객관식 특수 효과를 구현하는 방법을 주로 소개합니다. 친구들의 도움이 필요하다면 함께 보시길 바랍니다.
보안상의 이유로 Nuggets에서는 iframe 태그에 허용="microphone *;camera *"를 설정하지 않아 카메라가 열리지 않게 되었습니다! 자세히 보시려면 오른쪽 상단의 "상세보기"를 클릭해주세요! 아니면 아래 링크를 클릭하시면
//复制链接预览 https://code.juejin.cn/pen/7160886403805970445
를 보실 수 있습니다. 최근 Douyin 특수효과에 아주 인기가 좋은 그림 객관식 문제
가 있습니다. 오늘은 앞글을 구현하는 방법에 대해 말씀드리겠습니다. 아래에서는 머리를 왼쪽으로 움직일지 오른쪽으로 움직일지 결정
하는 방법에 대해 주로 설명하겠습니다. 图片选择题
特别火,今天就来讲一下前端如何实现,下面我主要讲一下如何判断左右摆头
。
抽象整体的实现思路如下
MediaPipe Face Mesh是一个解决方案,即使在移动设备上也能实时估计468个3D面部地标。它使用机器学习(ML)来推断3D面部表面,只需要一个摄像头输入,而无需专用的深度传感器。该解决方案利用轻量级模型架构以及整个管道中的GPU加速,为实时体验提供了至关重要的实时性能。
import '@mediapipe/face_mesh'; import '@tensorflow/tfjs-core'; import '@tensorflow/tfjs-backend-webgl'; import * as faceLandmarksDetection from '@tensorflow-models/face-landmarks-detection';
引入tensorflow训练好的人脸特征点检测模型
,预测 486
个 3D 人脸特征点,推断出人脸的近似面部几何图形。
maxFaces
默认为1。模型将检测到的最大人脸数量。返回的面孔数量可以小于最大值(例如,当输入中没有人脸时)。强烈建议将此值设置为预期的最大人脸数量,否则模型将继续搜索缺失的面孔,这可能会减慢性能。refineLandmarks
默认为false。如果设置为真,则细化眼睛和嘴唇周围的地标坐标,并在虹膜周围输出其他地标。(这里我可以设置false
,因为我们没有用到眼部坐标)solutionPath
通往am二进制文件和模型文件所在位置的路径。(强烈建议将模型放到国内的对象存储里面,首次加载可以节省大量时间,大小大概10M
async createDetector(){ const model = faceLandmarksDetection.SupportedModels.MediaPipeFaceMesh; const detectorConfig = { maxFaces:1, //检测到的最大面部数量 refineLandmarks:false, //可以完善眼睛和嘴唇周围的地标坐标,并在虹膜周围输出其他地标 runtime: 'mediapipe', solutionPath: 'https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh', //WASM二进制文件和模型文件所在的路径 }; this.detector = await faceLandmarksDetection.createDetector(model, detectorConfig); }
텐서플로 학습된얼굴 특징점 감지 모델 코드 도입 >, <code>486
3D 얼굴 특징점을 예측하고 얼굴의 대략적인 얼굴 기하구조를 추론합니다.
maxFaces
의 기본값은 1입니다. 모델이 감지할 최대 얼굴 수입니다. 반환되는 얼굴 수는 최대값보다 작을 수 있습니다(예: 입력에 얼굴이 없는 경우). 이 값을 예상되는 최대 얼굴 수로 설정하는 것이 좋습니다. 그렇지 않으면 모델이 누락된 얼굴을 계속 검색하므로 성능이 저하될 수 있습니다.HTMLVideoElement
、HTMLImageElement
、HTMLCanvasElement
和Tensor3D
。
flipHorizontal
refineLandmarks
기본값은 false입니다. true로 설정하면 눈과 입술 주변의 랜드마크 좌표를 구체화하고 홍채 주변의 추가 랜드마크를 출력합니다. (눈 좌표를 사용하지 않기 때문에 여기서 false
를 설정할 수 있습니다.) solutionPath
am 바이너리 및 모델 파일의 위치에 대한 경로입니다. (모델을 국내 개체 저장소에 넣어 두는 것을 적극 권장합니다. 처음 로드하면 시간을 많이 절약할 수 있습니다. 크기는 10M
정도입니다.)async renderPrediction() { var video = this.$refs['video']; var canvas = this.$refs['canvas']; var context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); const Faces = await this.detector.estimateFaces(video, { flipHorizontal:false, //镜像 }); if (Faces.length > 0) { this.log(`检测到人脸`); } else { this.log(`没有检测到人脸`); } }얼굴 인식반품됨 얼굴 목록은 각 얼굴의 이미지 감지 표면에 포함됩니다. 모델이 얼굴을 감지할 수 없는 경우 목록은 비어 있습니다. 각 얼굴에는 감지된 얼굴의 경계 상자와 키포인트 배열이 포함됩니다. MediaPipeFaceMesh는 468개의 키포인트를 반환합니다. 각 키포인트에는 x, y와 이름이 포함됩니다.
이제 감지기를 사용하여 얼굴을 감지할 수 있습니다. estimateFaces 메소드는 HTMLVideoElement
, HTMLImageElement
, HTMLCanvasElement
및 Tensor3D
를 포함한 다양한 형식의 이미지와 비디오를 허용합니다. >. 额头中心位置
第二个点 下巴中心位置
const place1 = (face.keypoints || []).find((e,i)=>i===10); //额头位置 const place2 = (face.keypoints || []).find((e,i)=>i===152); //下巴位置 /* x1,y1 | | | x2,y2 -------|------- x4,y4 x3,y3 */ const [x1,y1,x2,y2,x3,y3,x4,y4] = [ place1.x,place1.y, 0,place2.y, place2.x,place2.y, this.canvas.width, place2.y ];
通过canvas.width 额头中心位置
和下巴中心位置
计算出 x1,y1,x2,y2,x3,y3,x4,y4
flipHorizontal
선택사항. 기본값은 거짓입니다. 카메라에서 이미지 데이터를 가져오는 경우 결과를 수평으로 뒤집어야 합니다. getAngle({ x: x1, y: y1 }, { x: x2, y: y2 }){ const dot = x1 * x2 + y1 * y2 const det = x1 * y2 - y1 * x2 const angle = Math.atan2(det, dot) / Math.PI * 180 return Math.round(angle + 360) % 360 } const angle = this.getAngle({ x: x1 - x3, y: y1 - y3, }, { x: x2 - x3, y: y2 - y3, }); console.log('角度',angle)🎜🎜🎜상자는 이미지 픽셀 공간에서 얼굴의 경계 상자를 나타내고, xMin과 xMax는 x 경계를 나타내고, yMin, yMax는 y 경계를 나타내며, 너비와 높이는 경계 상자의 크기를 나타냅니다. . 키포인트의 경우 x와 y는 이미지 픽셀 공간의 실제 키포인트 위치를 나타냅니다. z는 머리 중심이 원점이 되는 깊이를 나타냅니다. 값이 작을수록 키 포인트가 카메라에 가까워집니다. Z의 크기는 x와 거의 동일한 크기를 사용합니다. 이 이름은 "입술", "왼쪽 눈" 등과 같은 일부 핵심 사항에 대한 레이블을 제공합니다. 모든 키포인트에 라벨이 있는 것은 아닙니다. 🎜🎜판단 방법🎜🎜사람 얼굴에서 두 점 찾기🎜🎜첫 번째 점
이마 중심 위치
두 번째 점 턱 중심 위치
🎜rrreee🎜통과 canvas.width 이마 중앙 위치
및 턱 중앙 위치
는 x1,y1,x2,y2,x3,y3,x4,y4
🎜🎜 🎜🎜를 계산합니다.getAngle({ x: x1, y: y1 }, { x: x2, y: y2 }){ const dot = x1 * x2 + y1 * y2 const det = x1 * y2 - y1 * x2 const angle = Math.atan2(det, dot) / Math.PI * 180 return Math.round(angle + 360) % 360 } const angle = this.getAngle({ x: x1 - x3, y: y1 - y3, }, { x: x2 - x3, y: y2 - y3, }); console.log('角度',angle)
通过获取角度,通过角度的大小来判断左右摆头。
推荐:《web前端开发视频教程》
위 내용은 Douyin의 인기 사진 객관식 특수 효과를 프런트 엔드를 사용하여 빠르게 구현할 수 있습니다!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!