【tracking.js】前端人脸识别框架 tracking.js 活体检测/拍照在 vue2 的使用-程序员宅基地

技术标签: Vue  前端  vue.js  javascript  开发语言  ecmascript  

Tracking.js 是一个独立的JavaScript库,用于跟踪从相机实时收到的数据。跟踪的数据既可以是颜色,也可以是人,也就是说我们可以通过检测到某特定颜色,或者检测一个人体/脸的出现与移动,来触发JavaScript 事件。它是非常易于使用的API,具有数个方法和事件(足够使用了)。

做项目要用到活体检测和拍照的

实现效果

image

活体检测组件

包需到下载 tracking-min.js 和 face-min.js 压缩文件,自行百度。

image

点击查看活体检测组件代码
<template>
  <el-dialog
    :visible="modalVisible"
    width="681px"
    custom-class="compaines-dialog"
    title="Complete Registration"
    class="face-dialog"
    v-dialogDrag
    :close-on-click-modal="false"
    @close="close"
    :append-to-body="true"
  >
    <div class="face" v-loading="faceloading">
      <p class="big-title">Liveness detection</p>
      <!-- <p v-if="steps === 'open' || steps === 'screen'">
        Please place your face into the outlined area,we will take the photo
        automatically!
      </p> -->
      <p v-if="steps === 'open' || steps === 'screen'">
        {
    { faceTips[imgList.length] }}
      </p>
      <div
        v-if="steps === 'screen' && imgList.length > 0"
        style="text-align: center; font-size: 30px"
      >
        <svg-icon :iconClass="faceLocation[imgList.length]" />
      </div>
      <p v-if="steps === 'end'">
        <span v-if="faceOk" class="success">Successful!</span>
        <span v-else class="fail">Failed!</span>
      </p>
      <div class="video-container" v-show="steps !== 'end'">
        <video
          id="video"
          preload
          autoplay
          loop
          muted
          width="295"
          height="345"
          :style="reverse ? 'transform:rotateY(180deg);' : ''"
        ></video>
        <canvas id="canvas" width="295" height="345"></canvas>
        <canvas
          id="shortCut"
          width="295"
          height="345"
          style="opacity: 0"
        ></canvas>
        <canvas
          id="canvas1"
          width="295"
          height="345"
          style="opacity: 0"
        ></canvas>
        <i @click="reverseVideo" v-show="steps === 'screen'">
          <svg-icon iconClass="icon-camera" class="icon-camera" />
        </i>
      </div>
      <div v-show="steps === 'end'" style="text-align: center">
        <img v-if="faceOk" src="@/icons/img/face-success.png" alt="" />
        <img v-else src="@/icons/img/face-fail.png" alt="" />
      </div>
      <div class="btns">
        <div class="add-num w300" @click="start" v-if="steps === 'open'">
          TURN CAMERA ON
        </div>
        <div
          class="retake-btn w300"
          style="margin-right: 0"
          @click="close"
          v-if="steps === 'screen'"
        >
          TURN CAMERA OFF
        </div>
        <div
          class="retake-btn w300"
          @click="tryAgain"
          v-if="steps === 'end' && !faceOk"
        >
          TRY AGAIN
        </div>
        <div
          class="add-num w300"
          @click="finish"
          v-if="steps === 'end' && faceOk"
        >
          FINISH
        </div>
        <p class="tips" v-if="steps === 'screen'">
          (To complete the liveness detection your camera must remain on)
        </p>
      </div>
      <div class="imgs" v-show="false">
        <p>未保存图片</p>

        <p>已保存图片</p>
        <div id="img"></div>
      </div>
    </div>
  </el-dialog>
</template>
<script>
import './tracking-min.js'
import './face-min.js'
import { livenessCheck } from '@modules/kyc/api/system/system'
import debounce from 'lodash/debounce'

export default {
  name: 'testTracking',
  model: {
    prop: 'formData',
    event: 'input',
  },
  props: {
    modalVisible: {
      type: Boolean,
      default: false,
    },
    formData: {
      type: Object | String,
    },
    option: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      saveArray: {},
      imgView: false,
      timer: true,
      steps: 'open',
      imgList: [],
      faceTips: [
        'Please place your face into the outlined area,we will take the photo automatically!',
        'Look to the left',
        'Look to the right',
        'Tilt your head up',
        'Tilt your head down',
      ],
      faceLocation: [
        '',
        'arrow-left',
        'arrow-right',
        'arrow-up',
        'arrow-down',
        '',
      ],
      faceloading: false,
      faceOk: false,
      startPhoto: false,
      reverse: true,
    }
  },
  created() {
    this.start = debounce(this.start, 500)
  },
  methods: {
    // 打开摄像头
    start() {
      window.navigator.mediaDevices
        .getUserMedia({
          video: true,
        })
        .then((stream) => {
          this.openVideo()
        })
        .catch((err) => {
          this.$message.error('Cannot capture user camera')
        })
    },
    openVideo() {
      let that = this
      this.steps = 'screen'
      this.startPhoto = true
      let canvas = document.getElementById('canvas')
      let context = canvas.getContext('2d')
      let tracker = new tracking.ObjectTracker('face')
      tracker.setInitialScale(4)
      tracker.setStepSize(2)
      tracker.setEdgesDensity(0.1)
      this.trackerTask = tracking.track('#video', tracker, { camera: true })
      tracker.on('track', function (event) {
        context.clearRect(0, 0, canvas.width, canvas.height)
        event.data.forEach(function (rect) {
          if (that.reverse) {
            context.strokeRect(
              295 - rect.x - rect.width,
              rect.y,
              rect.width,
              rect.height
            )
          } else {
            context.strokeRect(rect.x, rect.y, rect.width, rect.height)
          }
          context.strokeStyle = '#fff'
          context.fillStyle = '#fff'
          that.saveArray.x = rect.x
          that.saveArray.y = rect.y
          that.saveArray.width = rect.width
          that.saveArray.height = rect.height
        })
      })
      this.timer = true
      this.setPhotoInterval()
    },
    setPhotoInterval() {
      const countFun = () => {
        setTimeout(() => {
          if (this.timer && this.startPhoto) {
            countFun()
            if (this.reverse) {
              if (
                this.saveArray.x < 150 &&
                this.saveArray.y < 150 &&
                this.saveArray.width > 150 &&
                this.saveArray.height > 150
              ) {
                this.getPhoto()
              }
            } else {
              if (
                295 - this.saveArray.x - this.saveArray.width < 150 &&
                this.saveArray.y < 150 &&
                this.saveArray.width > 150 &&
                this.saveArray.height > 150
              ) {
                this.getPhoto()
              }
            }
          }
        }, 1000)
      }
      countFun()
    },
    // 获取人像照片
    getPhoto() {
      try {
        let video = document.getElementById('video')
        let cut = document.getElementById('shortCut')
        let context2 = cut.getContext('2d')
        context2.drawImage(video, 0, 0, 295, 345)
        this.keepImg()
      } catch (error) {}
    },
    // 将canvas转化为图片
    convertCanvasToImage(canvas) {
      let image = new Image()
      image.src = canvas.toDataURL('image/png')
      return image
    },
    //将base64转换为文件,dataurl为base64字符串,filename为文件名(必须带后缀名,如.jpg,.png)
    dataURLtoFile(dataurl, filename) {
      let arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
    },
    // 保存图片
    keepImg() {
      //先保存完整的截图
      let cut = document.getElementById('shortCut')
      let context = cut.getContext('2d')
      //从完整截图里面,截取左侧294x345大小的图片,添加到canvas1里面
      let imgData = context.getImageData(0, 0, 294, 345)
      let canvas1 = document.getElementById('canvas1')
      let context1 = canvas1.getContext('2d')
      context1.putImageData(imgData, 0, 0)
      let img = document.getElementById('img')
      //把canvas1里面的294x345大小的图片保存
      let photoImg = document.createElement('img')
      photoImg.src = this.convertCanvasToImage(canvas1).src
      img.appendChild(photoImg)
      this.imgList.push(
        this.dataURLtoFile(
          this.convertCanvasToImage(canvas1).src,
          `person${this.imgList.length}.jpg`
        )
      )
      this.timer = false
      //捕捉成功后停顿3秒,再捕捉下一张,捕捉5张后上传文件
      if (this.imgList.length === 5) {
        this.sendImages()
      } else {
        setTimeout(() => {
          this.timer = true
          this.setPhotoInterval()
        }, 3000)
      }
    },
    sendImages() {
      let formData = new FormData()
      this.imgList.forEach((item) => {
        formData.append('files', item)
      })
      this.faceloading = true
      formData.append('actionId', this.formData.id)
      livenessCheck(formData, { isUpload: true })
        .then((res) => {
          if (res.success) {
            this.faceOk = true
          } else {
            this.faceOk = false
          }
          this.faceloading = false
          this.steps = 'end'
        })
        .catch((err) => {
          this.openVideo()
          this.faceloading = false
          this.imgList = []
        })
    },
    tryAgain() {
      this.imgList = []
      this.openVideo()
    },
    finish() {
      this.closeFace()
      this.$emit('Liveness check success')
      this.$emit('close', 'success')
    },
    clearCanvas() {
      let c = document.getElementById('canvas')
      let c1 = document.getElementById('canvas1')
      let cxt = c.getContext('2d')
      let cxt1 = c1.getContext('2d')
      cxt.clearRect(0, 0, 581, 436)
      cxt1.clearRect(0, 0, 581, 436)
    },
    closeFace() {
      try {
        this.startPhoto = false
        this.timer = false
        this.imgList = []
        this.clearCanvas()
        // 关闭摄像头
        let video = document.getElementById('video')
        video.srcObject.getTracks()[0].stop()
        // 停止侦测
        this.trackerTask.stop()
      } catch (error) {}
    },
    close() {
      this.closeFace()
      if(this.faceOk){
        this.$emit('close', 'success')
      }else{
        this.$emit('close')
      }
    },
    reverseVideo() {
      this.reverse = !this.reverse
    },
  },
  watch: {},
}
</script>
<style lang="scss">
@import './face.scss';
</style>

拍照组件代码

点击查看拍照组件代码
<template>
  <el-dialog
    :visible="modalVisible"
    width="681px"
    custom-class="compaines-dialog"
    title="Complete Registration"
    class="face-dialog"
    @close="close"
  >
    <div class="face" v-loading="faceloading">
      <p class="big-title" v-if="steps !== 'save'">Take a profile picture</p>
      <p class="big-title success" v-if="steps === 'save'">Complete!</p>
      <p v-if="steps === 'open'">
        Please turn on your camera and center your face within the below guides.
      </p>
      <p v-if="steps === 'take'">Position your face within the outlined area,click the button and the image will be saved as your profile picture!</p>
      <p v-if="steps === 'save'">
        Happy with your picture? If not, you can take another one.
      </p>
      <div class="video-container">
        <video
          id="video"
          preload
          autoplay
          loop
          muted
          width="295"
          height="345"
          :style="reverse ? 'transform:rotateY(180deg);' : ''"
        ></video>
        <canvas id="canvas" width="295" height="345"></canvas>
        <canvas id="shortCut" v-show="false"></canvas>
        <img :src="imgSrc" alt="" v-show="steps === 'save'" />
        <i @click="reverseVideo" v-show="steps==='take'">
          <svg-icon iconClass="icon-camera" class="icon-camera" />
        </i>
      </div>
      <div class="btns">
        
        <div class="add-num w300" @click="start" v-if="steps === 'open'">
          TURN CAMERA ON
        </div>
        <div class="add-num w300" @click="getPhoto" v-if="steps === 'take'">
          SAVE THE IMAGE
        </div>

        <div class="retake-btn" @click="openVideo" v-if="steps === 'save'">
          RETAKE
        </div>
        <div class="add-num" @click="keepImg" v-if="steps === 'save'">
          USE PICTURE
        </div>
        <p class="tips" v-if="steps === 'take'">
          (To take a profile picture your camera must remain on)
        </p>
        <div class="imgs" v-show="false">
          <canvas
            id="canvas1"
            width="295"
            height="345"
            v-show="steps === 'save'"
          ></canvas>

          <p>save images</p>
          <div id="img"></div>
        </div>
      </div>
    </div>
  </el-dialog>
</template>
<script>
import './tracking-min.js'
import './face-min.js'
import { individualPhoto } from '@modules/kyc/api/system/system'
import debounce from 'lodash/debounce'
export default {
  name: 'testTracking',
  model: {
    prop: 'formData',
    event: 'input',
  },
  props: {
    modalVisible: {
      type: Boolean,
      default: false,
    },
    formData: {
      type: Object,
    },
    option: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      saveArray: {},
      imgView: false,
      timer: null,
      steps: 'open',
      imageFile: {},
      faceloading: false,
      btnLoading: false,
      imgSrc: '',
      reverse: true,
    }
  },
  created() {
    this.start = debounce(this.start, 500)
  },
  methods: {
    // 打开摄像头
    start() {
      window.navigator.mediaDevices
        .getUserMedia({
          video: true,
        })
        .then((stream) => {
          this.openVideo()
        })
        .catch((err) => {
          this.$message.error('Cannot capture user camera')
        })
    },
    openVideo() {
      let that = this
      this.steps = 'take'
      let saveArray = {}
      let canvas = document.getElementById('canvas')
      let context = canvas.getContext('2d')
      let tracker = new tracking.ObjectTracker('face')
      tracker.setInitialScale(4)
      tracker.setStepSize(1.5)
      tracker.setEdgesDensity(0.1)
      this.imgSrc = ''
      this.trackerTask = tracking.track('#video', tracker, { camera: true })
      tracker.on('track', function (event) {
        context.clearRect(0, 0, canvas.width, canvas.height)
        event.data.forEach(function (rect) {
          if (that.reverse) {
            context.strokeRect(
              295 - rect.x - rect.width,
              rect.y,
              rect.width,
              rect.height
            )
          } else {
            context.strokeRect(rect.x, rect.y, rect.width, rect.height)
          }
          context.strokeStyle = '#fff'
          context.fillStyle = '#fff'
          saveArray.x = rect.x
          saveArray.y = rect.y
          saveArray.width = rect.width
          saveArray.height = rect.height
        })
      })
    },
    // 获取人像照片
    getPhoto() {
      let video = document.getElementById('video')
      let can = document.getElementById('shortCut')
      can.width = video.videoWidth
      can.height = video.videoHeight
      let context2 = can.getContext('2d')
      if (this.reverse) {
        context2.scale(-1, 1)
        context2.translate(-video.videoWidth, 0)
      }
      context2.drawImage(video, 0, 0, video.videoWidth, video.videoHeight)
      this.imgSrc = this.convertCanvasToImage(can).src
      this.steps = 'save'
      this.clearCanvas()
      // 停止侦测
      this.trackerTask.stop()
      // 关闭摄像头
      video.srcObject.getTracks()[0].stop()
      // this.imgView = true
    },
    // 截屏
    screenshot() {
      this.getPhoto()
    },
    // 将canvas转化为图片
    convertCanvasToImage(canvas) {
      let image = new Image()
      image.src = canvas.toDataURL('image/png')
      return image
    },
    //将base64转换为文件,dataurl为base64字符串,filename为文件名(必须带后缀名,如.jpg,.png)
    dataURLtoFile(dataurl, filename) {
      let arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
    },
    // 保存图片
    keepImg() {
      // let can = document.getElementById('shortCut')
      // let context = can.getContext('2d')
      // let imgData = context.getImageData(0, 0, 294, 345)
      // let canvas1 = document.getElementById('canvas1')
      // let context1 = canvas1.getContext('2d')
      // context1.putImageData(imgData, 0, 0)
      // let img = document.getElementById('img')
      // let photoImg = document.createElement('img')
      // photoImg.src = this.convertCanvasToImage(canvas1).src
      // img.appendChild(photoImg)

      // this.imageFile = this.dataURLtoFile(
      //   this.convertCanvasToImage(canvas1).src,
      //   'person.jpg'
      // )
      this.imageFile = this.dataURLtoFile(this.imgSrc, 'person.jpg')
      let formData = new FormData()
      formData.append('file', this.imageFile)
      this.faceloading = true
      individualPhoto(formData, { isUpload: true })
        .then((res) => {
          if (res.success) {
            this.faceloading = false
            this.closeFace()
            this.$emit('close', 'success')
            this.$store
              .dispatch('GetBusinessUser')
              .then((res) => {})
              .catch((err) => {})
          } else {
            this.openVideo()
            this.faceloading = false
            this.imgList = []
          }
        })
        .catch((err) => {
          this.openVideo()
          this.faceloading = false
          this.imgList = []
        })
    },
    clearCanvas() {
      let c = document.getElementById('canvas')
      let c1 = document.getElementById('canvas1')
      let cxt = c.getContext('2d')
      let cxt1 = c1.getContext('2d')
      cxt.clearRect(0, 0, 581, 436)
      cxt1.clearRect(0, 0, 581, 436)
    },
    closeFace() {
      try {
        this.steps = 'open'
        this.clearCanvas()
        // 关闭摄像头
        let video = document.getElementById('video')
        video.srcObject.getTracks()[0].stop()
        // 停止侦测
        this.trackerTask.stop()
      } catch (error) {}
    },
    close() {
      this.closeFace()
      this.$emit('close')
    },
    reverseVideo() {
      this.reverse = !this.reverse
    },
  },
  watch: {
    faceView(v) {
      if (v == false) {
        this.closeFace()
      }
    },
  },
  destroyed() {
    // clearInterval(this.timer)
  },
}
</script>
<style lang="scss">
@import './face.scss';
</style>

样式文件

点击查看样式代码
.face {
  p {
    text-align: center;
    font-size: 16px;
    color: #333333;
  }

  .big-title {
    margin-top: 36PX;
    font-size: 24PX;
    font-weight: 600;
    color: #030229;
    text-align: center;

  }

  .success {
    color: #47BFAF;
  }

  .fail {
    color: #C81223;
  }

  .video-container {
    background: url(~@/icons/img/face.png);
    background-size: cover;
    position: relative;
    width: 295PX;
    height: 345PX;
    border-radius: 4%;
    overflow: hidden;
    margin: 0 auto;
    margin-top: 34PX;

    img,
    video,
    #canvas,
    #shortCut,
    #canvas1 {
      position: absolute;
    }

    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
    video{
      object-fit: cover;
    }
    .icon-camera{
      position: absolute;
      font-size: 32px;
      bottom: 20px;
      right: 20px;
      cursor: pointer;
    }
  }

  .btns {
    padding: 10PX;
    text-align: center;
    margin-top: 6PX;

    .tips {
      font-size: 14PX;
      color: #666;
      margin-top: 16PX;

      line-height: 24PX;
    }
  }

  .imgs {
    padding: 10PX;

    p {
      font-size: 16PX;
    }
  }

  .add-num {
    display: inline-block;
    font-size: 16PX;
    padding: 12PX 14PX;
    margin-right: 4PX;
    border-radius: 4PX;
    color: #ffffff;
    background: #47BFAF;
    cursor: pointer;
  }

  .retake-btn {
    width: 145PX;
    display: inline-block;
    font-size: 16PX;
    padding: 12PX 14PX;
    margin-right: 24PX;
    border-radius: 4PX;
    color: #828282;
    background: #E7E7E7;
    cursor: pointer;
  }

  .w300 {
    width: 300PX;
  }
}

.face-dialog {
  .el-dialog__body {
    padding-top: 0;
    padding-bottom: 15px;
  }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/IAIPython/article/details/130571231

智能推荐

Android Studio使用百度语音合成是TTS时报错: ****.so文件找不到的有关问题_旧版的百度语言合成报错-程序员宅基地

文章浏览阅读2.1k次。使用百度语音合成过程时,一直error : notfint libgnustl_shared.so在项目工程gradle文件中添加如下代码段:sourceSets { main { jniLibs.srcDirs = ['libs'] } }..._旧版的百度语言合成报错

BZOJ1202: [HNOI2005]狡猾的商人_狡猾的商人[hnoi2005]-程序员宅基地

文章浏览阅读425次。Description 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了n个月以来的收入情况,其中第i个月的收入额为Ai(i=1,2,3…n-1,n), 。当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。 刁姹的任务是秘密进行的,为了调查商人的账本,她只好跑到商人那_狡猾的商人[hnoi2005]

HTML5 Web SQL 数据库_方式准则的定义-程序员宅基地

文章浏览阅读1k次。1、HTML5 Web SQL 数据库 Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs。如果你是一个 Web 后端程序员,应该很容易理解 SQL 的操作。Web SQL 数据库可以在最新版的 Safari, Chrome 和 Opera 浏览器中工作。2、核心方法 以下是规范中定义的三个_方式准则的定义

spring Boot 中使用线程池异步执行多个定时任务_springboot启动后自动开启多个线程程序-程序员宅基地

文章浏览阅读4.1k次,点赞2次,收藏6次。spring Boot 中使用线程池异步执行多个定时任务在启动类中添加注解@EnableScheduling配置自定义线程池在启动类中添加注解@EnableScheduling第一步添加注解,这样才会使定时任务启动配置自定义线程池@Configurationpublic class ScheduleConfiguration implements SchedulingConfigurer..._springboot启动后自动开启多个线程程序

Maven编译打包项目 mvn clean install报错ERROR_mvn clean install有errors-程序员宅基地

文章浏览阅读1.1k次。在项目的target文件夹下把之前"mvn clean package"生成的压缩包(我的是jar包)删掉重新执行"mvn clean package"再执行"mvn clean install"即可_mvn clean install有errors

navacate连接不上mysql_navicat连接mysql失败怎么办-程序员宅基地

文章浏览阅读974次。Navicat连接mysql数据库时,不断报1405错误,下面是针对这个的解决办法:MySQL服务器正在运行,停止它。如果是作为Windows服务运行的服务器,进入计算机管理--->服务和应用程序------>服务。如果服务器不是作为服务而运行的,可能需要使用任务管理器来强制停止它。创建1个文本文件(此处命名为mysql-init.txt),并将下述命令置于单一行中:SET PASSW..._nvarchar链接不上数据库

随便推点

微信小程序api视频课程-定时器-setTimeout的使用_微信小程序 settimeout 向上层传值-程序员宅基地

文章浏览阅读1.1k次。JS代码 /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { setTimeout( function(){ wx.showToast({ title: '黄菊华老师', }) },2000 ) },说明该代码只执行一次..._微信小程序 settimeout 向上层传值

uploadify2.1.4如何能使按钮显示中文-程序员宅基地

文章浏览阅读48次。uploadify2.1.4如何能使按钮显示中文博客分类:uploadify网上关于这段话的搜索恐怕是太多了。方法多也试过了不知怎么,反正不行。最终自己想办法给解决了。当然首先还是要有fla源码。直接去管网就可以下载。[url]http://www.uploadify.com/wp-content/uploads/uploadify-v2.1.4...

戴尔服务器安装VMware ESXI6.7.0教程(U盘安装)_vmware-vcsa-all-6.7.0-8169922.iso-程序员宅基地

文章浏览阅读9.6k次,点赞5次,收藏36次。戴尔服务器安装VMware ESXI6.7.0教程(U盘安装)一、前期准备1、下载镜像下载esxi6.7镜像:VMware-VMvisor-Installer-6.7.0-8169922.x86_64.iso这里推荐到戴尔官网下载,Baidu搜索“戴尔驱动下载”,选择进入官网,根据提示输入服务器型号搜索适用于该型号服务器的所有驱动下一步选择具体类型的驱动选择一项下载即可待下载完成后打开软碟通(UItraISO),在“文件”选项中打开刚才下载好的镜像文件然后选择启动_vmware-vcsa-all-6.7.0-8169922.iso

百度语音技术永久免费的语音自动转字幕介绍 -程序员宅基地

文章浏览阅读2k次。百度语音技术永久免费的语音自动转字幕介绍基于百度语音技术,识别率97%无时长限制,无文件大小限制永久免费,简单,易用,速度快支持中文,英文,粤语永久免费的语音转字幕网站: http://thinktothings.com视频介绍 https://www.bilibili.com/video/av42750807 ...

Dyninst学习笔记-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏9次。Instrumentation是一种直接修改程序二进制文件的方法。其可以用于程序的调试,优化,安全等等。对这个词一般的翻译是“插桩”,但这更多使用于软件测试领域。【找一些相关的例子】Dyninst可以动态或静态的修改程序的二进制代码。动态修改是在目标进程运行时插入代码(dynamic binary instrumentation)。静态修改则是直接向二进制文件插入代码(static b_dyninst

在服务器上部署asp网站,部署asp网站到云服务器-程序员宅基地

文章浏览阅读2.9k次。部署asp网站到云服务器 内容精选换一换通常情况下,需要结合客户的实际业务环境和具体需求进行业务改造评估,建议您进行服务咨询。这里仅描述一些通用的策略供您参考,主要分如下几方面进行考虑:业务迁移不管您的业务是否已经上线华为云,业务迁移的策略是一致的。建议您将时延敏感型,有快速批量就近部署需求的业务迁移至IEC;保留数据量大,且需要长期稳定运行的业务在中心云上。迁移方法请参见如何计算隔离独享计算资源..._nas asp网站

推荐文章

热门文章

相关标签