Ver código fonte

人脸识别功能demo

刘洋 1 ano atrás
pai
commit
313276e278
6 arquivos alterados com 219 adições e 11 exclusões
  1. 0 0
      index.ts
  2. 155 5
      src/pages/home/home.vue
  3. 0 3
      src/pages/index/index.vue
  4. 2 0
      src/pages/login/login.vue
  5. 57 1
      src/utils/utils.js
  6. 5 2
      tsconfig.json

+ 0 - 0
index.ts


+ 155 - 5
src/pages/home/home.vue

@@ -1,16 +1,166 @@
 <template>
 <template>
-  <view> 我的页面 </view>
+  <view class="home">
+    <camera class="camera" device-position="front" flash="off"></camera>
+    <image v-if="tempImg" mode="widthFix" :src="tempImg" />
+  </view>
 </template>
 </template>
 
 
 <script>
 <script>
+  import { imgToBase64 } from '@/utils/utils'
   export default {
   export default {
     name: 'HomePage',
     name: 'HomePage',
     data() {
     data() {
-      return {}
+      return {
+        cameraAuth: false,
+        tempImg: '',
+        VKSession: null,
+        videoCtx: null,
+        listener: null
+      }
     },
     },
-    created() {},
-    methods: {}
+
+    mounted() {
+      this.getAuth()
+      this.initData()
+    },
+    onUnload() {
+      this.VKSession?.destroy()
+      this.listener?.stop({
+        complete: (res) => {
+          console.log('listener.stop', res)
+        }
+      })
+    },
+    methods: {
+      async openSetting() {
+        const _this = this
+        let promise = new Promise((resolve, reject) => {
+          uni.showModal({
+            title: '授权',
+            content: '请先授权获取摄像头权限',
+            success(res) {
+              if (res.confirm) {
+                uni.openSetting({
+                  success(res) {
+                    if (res.authSetting['scope.camera']) {
+                      // 用户打开了授权开关
+                      resolve(true)
+                    } else {
+                      // 用户没有打开授权开关, 继续打开设置页面
+                      _this.openSetting().then((res) => {
+                        resolve(true)
+                      })
+                    }
+                  },
+                  fail(res) {
+                    console.log(res)
+                  }
+                })
+              } else if (res.cancel) {
+                setTimeout(() => {
+                  _this.openSetting().then((res) => {
+                    resolve(true)
+                  })
+                }, 3000)
+              }
+            }
+          })
+        })
+        return promise
+      },
+      async getAuth() {
+        const _this = this
+        uni.getSetting({
+          success(res) {
+            console.log('sss', res.authSetting)
+            if (res.authSetting['scope.camera']) {
+              // 用户已经授权
+              _this.cameraAuth = true
+            } else {
+              uni.authorize({
+                scope: 'scope.camera',
+                success() {
+                  // 用户同意授权
+                  _this.cameraAuth = true
+                },
+                fail() {
+                  // 用户不同意授权
+                  _this.openSetting().then((res) => {
+                    console.log('终于授权了')
+                    _this.cameraAuth = true
+                  })
+                }
+              })
+            }
+          }
+        })
+      },
+      async detectFace(frame) {
+        this.VKSession.detectFace({
+          frameBuffer: frame.data,
+          width: frame.width,
+          height: frame.height,
+          scoreThreshold: 0.8,
+          sourceType: 0,
+          modelMode: 1
+        })
+      },
+      initData() {
+        this.videoCtx = wx.createCameraContext()
+        console.log('videoCtx:', this.videoCtx)
+        let count = 0
+        this.listener = this.videoCtx.onCameraFrame((frame) => {
+          count++
+          if (count === 10) {
+            this.detectFace(frame)
+            count = 0
+          }
+        })
+        this.VKSession = wx.createVKSession({
+          version: 'v1',
+          track: {
+            plane: {
+              mode: 1
+            },
+            face: { mode: 2 }
+          }
+        })
+        this.VKSession.on('updateAnchors', (anchors) => {
+          console.log('anchors', anchors)
+          if (anchors.length && !this.tempImg) {
+            this.videoCtx.takePhoto({
+              quality: 'high',
+              success: (res) => {
+                this.tempImg = res.tempImagePath
+                imgToBase64(this.tempImg).then((base64) => {
+                  console.log('人脸拍照图片 base64', base64)
+                })
+              }
+            })
+          }
+        })
+        this.VKSession.start((error) => {
+          if (error) {
+            this.$u.toast('VKSession start error')
+            // 如果失败,将返回 errno
+          }
+        })
+        this.listener.start()
+      }
+    }
   }
   }
 </script>
 </script>
 
 
-<style></style>
+<style lang="scss" scoped>
+  .home {
+    width: 100%;
+    height: 100%;
+    text-align: center;
+    .camera {
+      width: 400upx;
+      height: 400upx;
+      border-radius: 50%;
+      margin: 40rpx auto;
+    }
+  }
+</style>

+ 0 - 3
src/pages/index/index.vue

@@ -12,9 +12,6 @@
       return {}
       return {}
     },
     },
     created() {},
     created() {},
-    mounted() {
-      this.$u.vuex('vuex_token', '123')
-    },
     onShow() {},
     onShow() {},
     methods: {
     methods: {
       /**
       /**

+ 2 - 0
src/pages/login/login.vue

@@ -50,11 +50,13 @@
        */
        */
       async getWxCode() {
       async getWxCode() {
         this.wxCode = await getWxLoginCode()
         this.wxCode = await getWxLoginCode()
+        console.log('this.wxCode:', this.wxCode)
       },
       },
       /**
       /**
        * 微信登录
        * 微信登录
        */
        */
       async toWxLogin(wxLoginInfo) {
       async toWxLogin(wxLoginInfo) {
+        console.log('wxLoginInfo:', wxLoginInfo)
         const params = {
         const params = {
           wxCode: this.wxCode,
           wxCode: this.wxCode,
           ...wxLoginInfo.detail
           ...wxLoginInfo.detail

+ 57 - 1
src/utils/utils.js

@@ -2,7 +2,7 @@ import Vue from 'vue'
 function tip(data) {
 function tip(data) {
   setTimeout(() => {
   setTimeout(() => {
     uni.showToast(data)
     uni.showToast(data)
-  }, 500)
+  }, 100)
 }
 }
 
 
 // 身份证格式校验
 // 身份证格式校验
@@ -492,3 +492,59 @@ export const getAppWxLatLon = function (successCallback, errCallback) {
   }
   }
   // #endif
   // #endif
 }
 }
+
+/**
+ * 图片转base64
+ * @returns {Promise<any>} 返回一个 promise 对象,resolve 结果或 reject 错误
+ */
+export function imgToBase64(filePath) {
+  return new Promise((resolve, reject) => {
+    if (filePath.indexOf('wxfile') === 0 || filePath.indexOf('http://tmp/') === 0) {
+      wx.getFileSystemManager().readFile({
+        filePath: filePath,
+        encoding: 'base64',
+        success: (res) => {
+          wx.getImageInfo({
+            src: filePath,
+            success: (infoRes) => {
+              resolve(`data:image/${infoRes.type};base64,${res.data}`)
+            },
+            fail: (err) => {
+              reject('Error getting image info')
+            }
+          })
+        },
+        fail: (err) => {
+          reject('Error reading file')
+        }
+      })
+    } else {
+      wx.downloadFile({
+        url: filePath,
+        success: (res) => {
+          wx.getFileSystemManager().readFile({
+            filePath: res.tempFilePath,
+            encoding: 'base64',
+            success: (res) => {
+              wx.getImageInfo({
+                src: filePath,
+                success: (infoRes) => {
+                  resolve(`data:image/${infoRes.type};base64,${res.data}`)
+                },
+                fail: (err) => {
+                  reject('Error getting image info')
+                }
+              })
+            },
+            fail: (err) => {
+              console.log('网络', err)
+            }
+          })
+        },
+        fail: (err) => {
+          console.log('下载网络失败', err)
+        }
+      })
+    }
+  })
+}

+ 5 - 2
jsconfig.json → tsconfig.json

@@ -1,5 +1,6 @@
 {
 {
   "compilerOptions": {
   "compilerOptions": {
+    "baseUrl": ".", 
     "target": "esnext",
     "target": "esnext",
     "module": "esnext",
     "module": "esnext",
     "moduleResolution": "node",
     "moduleResolution": "node",
@@ -34,12 +35,13 @@
     ],
     ],
     "paths": {
     "paths": {
       "@/*": [
       "@/*": [
-        "./src/*"
+        "src/*"
       ]
       ]
     }
     }
   },
   },
   "include": [
   "include": [
     "src/**/*.ts",
     "src/**/*.ts",
+    "src/**/*.js",
     "src/**/*.d.ts",
     "src/**/*.d.ts",
     "src/**/*.tsx",
     "src/**/*.tsx",
     "src/**/*.vue",
     "src/**/*.vue",
@@ -51,5 +53,6 @@
     "test",
     "test",
     "dist",
     "dist",
     ".history"
     ".history"
-  ]
+  ],
+  "files": ["index.ts"]
 }
 }