更新记录

1.0.11(2025-11-06)

  1. Android兼容一些电子班牌大屏等设备

1.0.10(2025-10-18)

  1. 增加设置摄像头方向接口setCameraOrient

1.0.9(2025-10-16)

  1. 相机视频和静态图片处理分隔开会话处理,以增加识别度
  2. 优化iOS相机长时间识别的性能问题
查看更多

平台兼容性

uni-app(3.6.12)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - 7.0 -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - -

uni-app x(3.6.12)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - 7.0 - -

其他

多语言 暗黑模式 宽屏模式

人脸识别离线识别活体识别

主要功能:

  • 本地离线识别,无需网络
  • 活体识别
  • 相机录入人脸
  • 本地图片/远程图片录入
  • 本地人脸库管理
  • 从人脸库里搜索某个图片
  • 同时识别多人
  • 判断两张图片是否是同一人
  • 实时识别人脸信息(包含人脸数、人脸位置、年龄、性别、人种、眼睛张开、表情、摇头等等)

开发文档

  1. 拷贝demo里的AndroidManifest.xml、Info.plist文件到项目根目录
  2. 集成插件,集成插件步骤请参考 https://www.cnblogs.com/wenrisheng/p/18323027
  3. demo里集成了sqlite数据库https://ext.dcloud.net.cn/plugin?name=wrs-uts-sqlite,用来保存用户名/用户ID等,可以自行选择数据保存方式
  4. 购买激活码/咨询或定制请点击上面"进入交流群"私聊作者

横竖屏切换问题

  • iOS横竖屏切换都没问题
  • Android横竖屏切换:
    1. 由竖屏进入调到识别界面,不切换横屏时可以正常识别,当竖屏切换到横屏时,需要调用下打开相机(startCamera)业务
    2. 由横屏进入到识别界面,切换横竖屏可以正常识别

活体检测问题

  1. 插件支持rgb活体检测和动作活体检测,建议实际项目采用两者相结合的方式来测试,有些手机的相机rgb不是很准确,需要用户动作配合
  2. 动作活体检测可以没次都随机抽取左右睁眼、张嘴、摇头、抬头这几个动作进行随机组合的方式,可以根据项目情况自行处理

图片录入问题

  1. 优先采用本设备相机录入
  2. 批量录入时,如果返回有失败的图片,可以再次使用失败图片重新录入,尽量分多批次来录入
  3. 录入时图片人物不要带口罩、眼镜等容易造成误差的物件

组件


<wrs-uts-face ref="arcfacepro" :style="'width:'+width+'px;height:'+height+'px;'" @onEvent="onEvent"
    :params="params"></wrs-uts-face>
  • 使用了该组件的页面要使用nvue或uvue
  • 从相机录入人脸到本地人脸库,注册结果在onEvent里回调

let imageName = getUserName()
let filePath = plus.io.convertLocalFileSystemURL("_download/" + imageName + ".jpg");
let newParams = {}
newParams.businessArray = [{
    business: "startRegister",
    params: { // 参数可选
        needBase64: false, // 是否返回图片的base64
        filePath: filePath // 是否保存到本地文件
    }
}]
let newParamsStr = this.formatNewParams(newParams)
// android、ios
this.params = newParamsStr
// 鸿蒙
this.options = {
    params: newParamsStr
}
  • 从相机识别识别人脸,识别结果在onEvent里回调

let newParams = {}
newParams.businessArray = [{
    business: "startCompare", // 对比业务
    params: {
        compare: true // true:开始对比,false:停止对比
    }

}]

this.params = JSON.stringify(newParams)
  • 切换摄像头

let newParams = {}
newParams.businessArray = [{
    business: "switchCamera"
}]

this.params = JSON.stringify(newParams)
  • 打开相机

let newParams = {}
newParams.businessArray = [{
    business: "startCamera"
}]
let newParamsStr = this.formatNewParams(newParams)
// android、ios
this.params = newParamsStr
// 鸿蒙
this.options = {
    params: newParamsStr
}
  • 暂停相机

let newParams = {}
newParams.businessArray = [{
    business: "stopCamera"
}]
let newParamsStr = this.formatNewParams(newParams)
// android、ios
this.params = newParamsStr
// 鸿蒙
this.options = {
    params: newParamsStr
}
  • 获取当前视频图片,结果在onEvent里回调

let imageName = getUserName()
let filePath = plus.io.convertLocalFileSystemURL("_download/" + imageName + ".jpg");
let newParams = {}
newParams.businessArray = [{
    business: "getCurImage",
    params: {
        needBase64: false, // 是否返回base64
        filePath: filePath // 是否保存为本地文件
    }
}]
let newParamsStr = this.formatNewParams(newParams)
// android、ios
this.params = newParamsStr
// 鸿蒙
this.options = {
    params: newParamsStr
}
  • 是否开启相机检测属性

let newParams = {}
newParams.businessArray = [{
    business: "setDetectAttri",
    params: {
        rgbLiveness: true, // 是否开启RGB活体识别
        faceMask: true, // 是否开启口罩识别
        faceInteractionState: true, // 是否开启眼睛识别:左右眼睁/闭
        faceInteractionsActions: true, // 是否脸部动作识别:摇头、张嘴、抬头等
        faceAttribute: true, // 是否开启属性识别:年龄、种族、性别
        faceEmotion: true // 是否开启表情识别,喜怒哀乐等
    }
}]
let newParamsStr = this.formatNewParams(newParams)
// android、ios
this.params = newParamsStr
// 鸿蒙
this.options = {
    params: newParamsStr
}
  • onLoadView,视图加载事件
  • onEvent,人脸注册/识别事件

onEvent(e) {
    // console.log("onEvent:" + JSON.stringify(e))
    let detail = e.detail
    let opt = detail.opt
    if (opt != "onDetectFace" && opt != "onRecognize" && opt != "onDetectFace") {
        console.log("onEvent:" + JSON.stringify(e))
    }
    switch (opt) {
        // 加载完视图
        case "onLoadView": {

        }
        break;
        // 获取当前图片的回调
        case "getCurImage": {
            let filePath = detail.filePath

            if (filePath) {
                this.curImageSrc = "file://" + filePath
            }
        }
        break;
        // 注册回调
        case "onRegister": {
            let success = detail.success
            let msg = ""
            if (success) { // 注册成功
                let filePath = detail.filePath
                if (filePath) {
                    this.registerImageSrc = "file://" + filePath
                }
                let id = detail.id
                // 随机生成一个用户名
                let name = getUserName()
                let user = {}
                user.id = id
                user.name = name
                // 保存用户信息到数据库
                insertUser([user], (resp) => {

                })
                msg = "注册成功:" + name
            } else { // 注册失败
                msg = "注册失败:" + JSON.stringify(detail)
            }
            console.log(msg)
            this.showToast(msg)
        }
        break;
        // 对比结果回调
        case "onRecognize": {
            // {
            //  "faceInfo": {
            //      "faceAttribute": {
            //          "ageBracket": [4],
            //          "gender": [0],
            //          "num": 1,
            //          "race": [3]
            //      },
            //      "faceData": {
            //          "angles": [{
            //              "pitch": 33.292926788330078,
            //              "roll": 2.8457748889923096,
            //              "yaw": 10.13283634185791
            //          }],
            //          "detConfidence": [0],
            //          "detectedNum": 1,
            //          "rects": [{
            //              "height": 206,
            //              "width": 193,
            //              "x": 213,
            //              "y": 133
            //          }],
            //          "trackIds": [18]
            //      },
            //      "faceEmotion": {
            //          "emotion": [],
            //          "num": 1
            //      },
            //      "faceInteractionsActions": {
            //          "blink": [0],
            //          "headRaise": [1],
            //          "jawOpen": [0],
            //          "normal": [0],
            //          "num": 1,
            //          "shake": [0]
            //      },
            //      "faceInteractionState": {
            //          "leftEyeStatusConfidence": [1],
            //          "num": 1,
            //          "rightEyeStatusConfidence": [1]
            //      },
            //      "faceMask": {
            //          "confidence": [0.089397557079792023],
            //          "num": 1
            //      },
            //      "rgbLiveness": {
            //          "confidence": [0.9998619556427002],
            //          "num": 1
            //      }
            //  },
            //  "faceList": [{
            //      "bottom": 283.91250610351562,
            //      "id": -1,
            //      "left": 117.38749694824219,
            //      "right": 279.02499389648438,
            //      "top": 111.38749694824219
            //  }],
            //  "viewHeight": 402,
            //  "viewWidth": 414
            // }

            let data = detail.data
            let dataObj = JSON.parse(data)
            let faceNum = 0

            let faceList = dataObj.faceList
            if (faceList) {
                faceNum = faceList.length
            }
            this.dataArray.length = 0
            this.dataArray = []

            let idArray = []
            let faceInfo = dataObj.faceInfo
            if (faceNum > 0) {
                for (let i = 0; i < faceNum; i++) {
                    let userDesc = converFaceInfo(faceList, i, faceInfo, this.recognizedUserArray)
                    this.dataArray.push(userDesc)
                }
            }
        }
        break;
        default:
            break;
    }
},

接口


import {
    UTSFaceMgr
    UTSFaceEngine
} from "@/uni_modules/wrs-uts-face"
  • 激活引擎,激活引擎接口业务一般放到app启动的onLaunch函数里,激活码请进入交流群联系作者

let params = {}
params["activeCode"] = "xxx" // 激活码
UTSFaceEngine.activeEngine(params, (resp) => {
    let code = resp.code
    let str = ""
    if (code == 0) {
        str = "激活成功"
    } else if (code == 11) {
        str = "包名绑定错误code:" + code
    } else if (code == 12) {
        str = "激活码已过期code:" + code
    } else if (code == 13) {
        str = "读写权限未授权code:" + code
    } else if (code == 14) {
        str = "设备指纹错误code:" + code
    } else if (code == 15) {
        str = "产品错误code:" + code
    } else if (code == 16) {
        str = "平台错误code:" + code
    } else {
        str = "激活失败code:" + code
    }
    this.msg = str
    this.showToast(str)
})
  • 获取设备指纹

UTSFaceEngine.getDeviceFinger((resp) => {
    let data = resp.data
    if (data) {
        this.showMsg("设备指纹:" + data)
        this.showToast("指纹已复制到粘贴板")
    } else {
        this.showMsg("获取设备指纹失败")
    }
})
  • 对比两张图片是否是同一个人

let url1 = "/xxx/xxx/xx.jpg"
let url2 = "/sss/xxx/xx.jpg"
UTSFaceEngine.compareFace(url1, url2, (resp)=>{
    // {
    //  "percentage": 0.9221189618110657, // 相似度百分比
    //  "faceNum2": 1, // 第二张图人脸数
    //  "similarity": 0.7389912009239197, // 相似度
    //  "faceNum1": 1 // 第一张图人脸数
    // }
    console.log(JSON.stringify(resp))
    let similarity = resp.similarity 
    if(similarity > 0.48) {
        this.showMsg("两张图片是同一个人")
    } else {
        this.showMsg("两张图片不是同一个人")

    }
})
  • 获取图片人脸信息(包含人脸数、人脸位置、年龄、性别、人种、眼睛张开、表情、摇头等等)

UTSFaceEngine.getFaceInfo(this.url, (resp) => {
    let str = ""
    let faceData = resp.faceData
    if (faceData) {
        let detectedNum = faceData.detectedNum
        if (detectedNum > 0) {
            str = str + "总人数:" + detectedNum + "人\n"
            let faceStr = "人脸坐标:\n"
            for (let i = 0; i < detectedNum; i++) {
                let rect = faceData.rects[i]
                faceStr = faceStr + " 第" + ( i + 1 ) + "人: " + JSON.stringify(rect) + " \n"
            }
            str = str + faceStr + "\n"

            // 眼睛状态
            let faceInteractionState = resp.faceInteractionState
            if (faceInteractionState) {
                // 多少对眼睛
                let eysStr = "眼睛状态:\n"
                let num = faceInteractionState.num
                for (let i = 0; i < num; i++) {
                    let rightEye = faceInteractionState.rightEyeStatusConfidence[i]
                    let leftEye = faceInteractionState.leftEyeStatusConfidence[i]
                    let leftEyeStr = ""
                    let rightEyeStr = ""
                    if (leftEye == 1) {
                        leftEyeStr = "睁开"
                    } else {
                        leftEyeStr = "关闭"
                    }
                    if (rightEye == 1) {
                        rightEyeStr = "睁开"
                    } else {
                        rightEyeStr = "关闭"
                    }
                    eysStr = eysStr + "第" + ( i + 1 ) + "个人:" + "左眼:" + leftEyeStr + " 右眼:" + rightEyeStr +
                        "\n"
                }
                str = str + eysStr + "\n"
            }

            let faceQuality = resp.faceQuality
            if (faceQuality) {
                let num = faceQuality.num
                let faceQualityStr = "人脸质量:\n"
                for (let i = 0; i < num; i++) {
                    let confidence = faceQuality.confidence[i]
                    let str = ""
                    if (confidence > 0.5) {
                        str = "人脸清晰"
                    } else {
                        str = "人脸模糊"
                    }

                    faceQualityStr = faceQualityStr + "第" + ( i + 1 ) + "个人:" + str + "\n"
                }
                str = str + faceQualityStr + "\n"
            }
            let faceEmotion = resp.faceEmotion
            if (faceEmotion) {
                let num = faceEmotion.num
                let emotionStr = "人物表情\n"
                for (let i = 0; i < num; i++) {
                    let emotion = faceEmotion.emotion[i]
                    let str = ""
                    // 0: 没表情 1:开心 2:伤心 3:吃惊 4:恐惧 5:厌恶 6:愤怒
                    switch (emotion) {
                        case 0:
                            str = "没表情"
                            break;
                        case 1:
                            str = "开心"
                            break;
                        case 2:
                            str = "伤心"
                            break;
                        case 3:
                            str = "吃惊"
                            break;
                        case 4:
                            str = "恐惧"
                            break;
                        case 5:
                            str = "厌恶"
                            break;
                        case 6:
                            str = "愤怒"
                            break;
                        default:
                            break;
                    }

                    emotionStr = emotionStr + "第" + ( i + 1 ) + "个人:" + str + "\n"
                }
                str = str + emotionStr + "\n"

            }
            let faceAttribute = resp.faceAttribute
            if (faceAttribute) {
                let num = faceAttribute.num
                let faceAttributeStr = "人物属性:\n"
                for (let i = 0; i < num; i++) {
                    console.log("3.0")
                    let ageBracket = faceAttribute.ageBracket[i]
                    let gender = faceAttribute.gender[i]
                    let race = faceAttribute.race[i]
                    let ageBracketStr = ""
                    switch (ageBracket) {
                        case 0:
                            ageBracketStr = "0~2"
                            break;
                        case 1:
                            ageBracketStr = "3~9"
                            break;
                        case 2:
                            ageBracketStr = "10~19"
                            break;
                        case 3:
                            ageBracketStr = "20~29"
                            break;
                        case 4:
                            ageBracketStr = "30~39"
                            break;
                        case 5:
                            ageBracketStr = "40~49"
                            break;
                        case 6:
                            ageBracketStr = "50~59"
                            break;
                        case 7:
                            ageBracketStr = "60~67"
                            break;
                        case 8:
                            ageBracketStr = "大于70"
                            break;
                        default:
                            break;
                    }
                    let genderStr = ""
                    if (gender == 0) {
                        genderStr = "女"
                    } else {
                        genderStr = "男"
                    }
                    let raceStr = ""
                    console.log("3.2")
                    switch (race) {
                        case 0:
                            raceStr = "黑人"
                            break;
                        case 1:
                            raceStr = "亚洲人"
                            break;
                        case 2:
                            raceStr = "拉丁裔和西班牙裔"
                            break;
                        case 3:
                            raceStr = "中东"
                            break;
                        case 4:
                            raceStr = "白人"
                            break;

                        default:
                            break;
                    }
                    faceAttributeStr = faceAttributeStr + "第" + ( i + 1 ) + "个人:" + " 年龄:" + ageBracketStr +
                        " 性别:" + genderStr + " 种族:" + raceStr + "\n"
                }
                str = str + faceAttributeStr + "\n"
            }

            let faceMask = resp.faceMask
            if (faceMask) {
                let num = faceMask.num
                let faceMaskStr = "口罩:\n"
                for (let i = 0; i < num; i++) {
                    let confidence = faceMask.confidence[i]
                    console.log("口罩阈值:" + confidence)
                    let str = ""
                    if (confidence > 0.5) {
                        str = "有带口罩"
                    } else {
                        str = "没带口罩"
                    }

                    faceMaskStr = faceMaskStr + "第" + ( i + 1 ) + "个人:" + str + "\n"
                }
                str = str + faceMaskStr + "\n"
            }
            let faceInteractionsActions = resp.faceInteractionsActions
            if (faceInteractionsActions) {
                let num = faceInteractionsActions.num
                let faceInteractionsActionsStr = "脸部动作:\n"
                //  "faceInteractionsActions": {
                //      "headRaise": [0], // 抬头
                //      "jawOpen": [0], // 张嘴
                //      "num": 1,
                //      "normal": [1],// 有没有动作
                //      "blink": [0], // 眨眼动作
                //      "shake": [0] // 左右摇头
                //  }
                for (let i = 0; i < num; i++) {
                    let headRaise = faceInteractionsActions.headRaise[i]
                    let jawOpen = faceInteractionsActions.jawOpen[i]
                    let normal = faceInteractionsActions.normal[i]
                    let blink = faceInteractionsActions.blink[i]
                    let shake = faceInteractionsActions.shake[i]

                    let headRaiseStr = ""
                    // 0: 没表情 1:开心 2:伤心 3:吃惊 4:恐惧 5:厌恶 6:愤怒
                    switch (headRaise) {
                        case 0:
                            headRaiseStr = "抬头:无"
                            break;
                        case 1:
                            headRaiseStr = "抬头:有"
                            break;
                        default:
                            break;
                    }
                    let jawOpenStr = ""
                    if (jawOpen == 0) {
                        jawOpenStr = "张嘴:无"
                    } else {
                        jawOpenStr = "张嘴:有"
                    }
                    let normalStr = ""
                    switch (normal) {
                        case 0:
                            normalStr = "动作:无"
                            break;
                        case 1:
                            normalStr = "动作:有"
                            break;
                        default:
                            break;
                    }
                    let blinkStr = ""
                    switch (blink) {
                        case 0:
                            blinkStr = "眨眼:无"
                            break;
                        case 1:
                            blinkStr = "眨眼:有"
                            break;
                        default:
                            break;
                    }
                    let shakeStr = ""
                    switch (shake) {
                        case 0:
                            shakeStr = "摇头:无"
                            break;
                        case 1:
                            shakeStr = "摇头:有"
                            break;
                        default:
                            break;
                    }

                    faceInteractionsActionsStr = faceInteractionsActionsStr + "第" + ( i + 1 ) + "个人:" +
                        headRaiseStr + " " + jawOpenStr + " " + normalStr + " " + blinkStr + " " +
                        shakeStr + "\n"
                }
                str = str + faceInteractionsActionsStr + "\n"
            }
        } else {
            str = "没有检测到人脸"
        }
    }
    console.log(JSON.stringify(resp))
    this.showMsg(str)
    // {
    //  "faceData": { // 人脸信息
    //      "detectedNum": 1, // 人脸数
    //      "trackIds": [-1],
    //      "detConfidence": [0],
    //      "rects": [{ // 人脸位置
    //          "height": 284,
    //          "x": 239,
    //          "y": 272,
    //          "width": 280
    //      }],
    //      "angles": [{ // 角度
    //          "roll": -2.7232625484466553,
    //          "pitch": -8.401390075683594,
    //          "yaw": -10.91862678527832
    //      }]
    //  },
    //  "faceInteractionState": { // 眼睛状态
    //      "rightEyeStatusConfidence": [1], // 所有右眼状态:1:睁开 0:关闭
    //      "num": 1, // 一对眼睛
    //      "leftEyeStatusConfidence": [1] // 所有左眼状态:1:睁开 0:关闭
    //  },
    //  "faceQuality": { // 图片人脸质量
    //      "confidence": [0.820976734161377], // 质量阈值
    //      "num": 1
    //  },
    //  "faceEmotion": { // 表情
    //      "num": 1,
    //      "emotion": [0] // 0: 没表情 1:开心 2:伤心 3:吃惊 4:恐惧 5:厌恶 6:愤怒
    //  },
    //  "faceAttribute": {
    //      "ageBracket": [3], // 年龄区域 0:0~2 1:3~9 2:10~19 3:20~29 4:30~39 5:40~49 6:50~59 7:60~67 8:大于70
    //      "num": 1,
    //      "gender": [0], // 性别 0:女 1:男
    //      "race": [1] // 种族 0:黑人 1:亚洲人 2:拉丁裔和西班牙裔 3:中东 4:白人
    //  },
    //  "rgbLiveness": {
    //      "confidence": [0.8709309101104736],
    //      "num": 1
    //  },
    //  "faceMask": { // 是否带口罩
    //      "confidence": [0.08445872366428375], // 带口罩系数,一般大于0.5认为是带了口罩
    //      "num": 1
    //  },
    //  "faceInteractionsActions": {
    //      "headRaise": [0], // 抬头
    //      "jawOpen": [0], // 张嘴
    //      "num": 1,
    //      "normal": [1],// 有没有动作
    //      "blink": [0], // 眨眼动作
    //      "shake": [0] // 左右摇头
    //  }
    // }
    // this.showMsg(JSON.stringify(resp))
})

人脸库管理

  • 批量注册人脸

let localImagePath = UTSFaceEngine.getResourcePath("/static/yifei.png")
let remoteImagePath = this.remoteImageUrl
let userName = getUserName()
let userNames = [userName + "_1", userName + "_2"]
let params = {}
params.data = [localImagePath, remoteImagePath]
// 源图片路径,支持绝对路径,如:/afa/ss/aa.png或远程网络路径,如:https://ssss/ss.png
UTSFaceMgr.registerUser(params, (resp) => {
    let data = resp.data
    let allSuccess = true
    let length = data.length
    let userArray = []
    for (let i = 0; i < length; i++) {
        let success = data[i].success
        if (success) {
            let id = data[i].id
            let name =  userNames[i]
            let user = {}
            user.id = id
            user.name = name
            userArray.push(user)

        } else {
            allSuccess = false
        }
    }
    if(userArray.length > 0) {
        // 注册成功后保存到本地数据库
        insertUser(userArray, (resp)=>{
            this.refreshFaceData()
        })
    }
});
  • 删除用户

// 根据id删除,注册的时候会返回id
let id = 2 
let params = {}
params.data = [id]
// 删除人脸库
UTSFaceMgr.deleteUser(params, () => {
    let resultArray = resp.data
    let length = resultArray.length;
    let suc = true;
    for(let i = 0; i < length; i ++) {
         suc = resultArray[i]
    }
    if(suc) {
        // 删除数据
        deleteUser(id, (resp)=>{
            this.refreshFaceData()
        })
    }

})
  • 分页获取用户

let page = 1 // 页码
let pageSize = 20 // 每页数量
query(page, pageSize, (userArray)=>{
    this.dataArray.push(...userArray)
    if(userArray.length == 0) {
        this.showToast("没有下一页数据了")
    }
})
  • 获取人脸总数,通过查询数据库数量得到总数

getTotalCount((resp) => {
    let totalCount = resp.data 
    this.showMsg("总数:" + totalCount)
})
  • 判断某张图片是否已经注册到本地人脸库

// path支持本地图片或网络图片
let path = "/xxxx/xxx/xxx.jpg"
UTSFaceMgr.recognizeImage(path, (resp) => {
    this.showMsg(JSON.stringify(resp))
      let isRegistered = false
      let data = resp.data 
      if(data) {
          let length = data.length
          if(length > 0) {
              isRegistered = true
          }
      }
      if(isRegistered) {
          this.showMsg("这张图片已经注册")
      } else {
          this.showMsg("这张图片没有注册")
      }
})

参数设置

  • 设置对比搜索的阈值

let threshold = 0.48 // 大于0.48就认为是同一个人
UTSFaceEngine.setSearchHubThreshold(threshold)
  • 设置摄像头方向

let isFront = true
UTSFaceEngine.setCameraOrient(isFront)
  • 获取摄像头方向

let isFront = UTSFaceEngine.getCameraOrient()

隐私、权限声明

1. 本插件需要申请的系统权限列表:

相机、读写

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率: