uniapp使用live-pusher实现模拟人脸识别效果
需求:
1、前端实现模拟用户人脸识别,识别成功后抓取视频流或认证的一张静态图给服务端。
2、服务端调用第三方活体认证接口,验证前端传递的人脸是否存在,把认证结果反馈给前端。
3、前端根据服务端返回的状态,显示在页面上用于提示用户。
难点:
1、前端APP如果要实现人脸活体校验验证,需要对接大厂的SDK实现。
2、一开始我采用用使用在App内嵌套H5来单独部署一套人脸验证,把结果通过webview与APP进行数据交互,但是H5试了使用好用高效的effet.js 库人脸识别 目前仅支持H5(但是发现最后在手机上识别人像整个人被压缩似得,而且是反向镜头,跟作者已反馈,等待作者持续更新)。
3、抛弃了使用App嵌套H5方法,因此最终选择了使用原生live-pusher直播流来模拟实现人脸识别效果。本打算给大家写成组件方便大家直接调用来着,但是发现组件内获取实例仅支持在onReady页面生命周期使用。
实现思路
1、首先需要获取手机是否有录音以及相机权限,没有的话引导用户前去设置页主动设置。
2、其次创建live-pusher实例,根据业务需求实现自己的模拟人脸识别思路(目前我们这是在用户手动点击5s后进行自动抓拍的)。
3、前端拿到抓拍最后一帧图片调用接口给服务端传递,服务端调用第三方进行人脸活体检测,一般是需要付费的哈。
4、最后前端把服务端返回的识别状态展示在页面上,方便后续用户操作。
代码步骤(当前是vue3项目示例,最低sdk 21版本并且勾选livepusher)


1、获取当前手机是否允许开启相机和录音权限。(建议直接使用官方大佬写的js sdk)App权限判断和提示

引入js sdk插件(vue3版本需要转换为export function,vue2版本直接按照官方大佬的直接使用即可)
import {requestAndroidPermission,gotoAppPermissionSetting} from '@/js_sdk/wa-permission/permission.js'
2、创建live-pusher实例,根据业务需求写业务逻辑(注意:一定要用nvue页面哈,cover-image覆盖一个矢量图在直播流画面上)。
ilve-pusher详细参数说明具体看live-pusher官方文档
<template><view class="container"><live-pusher id='livePusher' ref="livePusher" class="livePusher" url="" mode="FHD" :muted="true":enable-camera="true" :auto-focus="true" :beauty="2" whiteness="2" aspect="9:16" local-mirror="disable"@statechange="statechange" @error="error" @netstatus="netstatus" :style="[{width:'400rpx',height: '400rpx',marginLeft: '175rpx',marginTop:'20rpx',}]"></live-pusher><cover-image style="width: 400rpx;height: 400rpx;transform: scale(1.01);position: absolute;left: 175rpx;top: 190.5rpx;" src="@/static/circleBg.png" /></view>
</template>
<script>
export default{onReady() {//需要在onReady页面生命周期函数来写this.livePusher = uni.createLivePusherContext("livePusher", this);},
}
</script>
3、5s后抓拍最后一帧图片给服务端,人脸识别成功即登录系统,识别失败跳转认证失败页面(这里跟服务端对接采用的formdata格式上传文件流,你也可以采取转成base64)
临时路径转base64
// 定时器 几秒后自动抓拍handleSetTime() {this.timeFlag = setInterval(async () => {if (this.timeOut > 0) {this.timeOut--this.titleTips = this.countDownTimerStartTipsthis.buttonTip = `${this.countDownTimerStartBtnTips} ${this.timeOut}秒`}if (this.timeOut == 1) {this.livePusher.snapshot({success: (res) => {this.snapshotInfo = res.message}})}// 进行快照人脸认证if (this.timeOut == 0) {clearInterval(this.timeFlag);this.titleTips = this.countDownTimerZeroTipsthis.buttonTip = this.countDownTimerZeroBtnTipsuni.showLoading({title: this.countDownTimerZeroBtnTips})uni.uploadFile({url: 'http://192.168.60.2:8080/bsCheckImage/checkImg',filePath: this.snapshotInfo.tempImagePath,name: "file",success: (uploadFileRes) => {const jxStrData = JSON.parse(uploadFileRes.data)console.log(jxStrData)const resResultCode = jxStrData.codeconst resResultData = jxStrData.dataif (resResultCode !== '00000') {uni.navigateTo({url: '/pages/liveb-result/liveb-result?failResultObj=' +this.passData(jxStrData)})this.handleStop()return}if (resResultCode == '00000' && resResultData.score >= 0.8) {uni.showToast({title: this.faceSucessTips})this.buttonTip = this.faceSucessTipsthis.handleStop()return}if (resResultCode == '00000' && resResultData.score < 0.8) {const paramsData = {success: false,code: 'A9901',message: '人脸校验失败,请将人脸正对取景框内重新认证',failCode: 'A9901',faceScore: resResultData.score}uni.navigateTo({url: '/pages/liveb-result/liveb-result?failResultObj=' +this.passData(paramsData)})this.handleStop()return}},fail: (error) => {uni.hideLoading()uni.navigateTo({url: '/pages/liveb-result/liveb-result',animationType: 'zoom-out',animationDuration: 1000})this.handleStop()},complete: () => {uni.hideLoading()clearInterval(this.timeFlag) // 清除定时器,防止再次执行}});}}, 1000)},
4、人脸认证失败服务端返回状态,前端跳转认证失败页面,返回时给上个页面传递监听参数。(liveb-result.vue页面)
<template><view class="container"><view class="result-area"><view class="result-icon"><image class="result-icon-pic" src="../../static/fece_result.png"></image></view><view class="result-tips">{{failInfos.message}}</view><view class="result-button" @click="handleRetryFace">重新认证</view></view></view>
</template><script setup>import {ref} from 'vue'import {onLoad,onBackPress} from '@dcloudio/uni-app'const faceStatus = ref('')const failInfos = ref({})const failResultMsg = (() => {const data = {code: '3698',msg: '人脸认证失败'}uni.$emit('failResult', data);})onLoad((options) => {if (options.failResultObj) {const resultObj = JSON.parse(decodeURIComponent(options.failResultObj));failInfos.value = resultObj}})const handleRetryFace = (() => {console.log('handleRetryFace')failResultMsg()uni.navigateBack()})onBackPress((e) => {failResultMsg()})
</script><style lang="scss" scoped>.container {width: 750rpx;.result-area {position: absolute;top: 44%;left: 50%;transform: translate(-50%, -50%);.result-icon {display: flex;align-items: center;justify-content: center;.result-icon-pic {width: 140rpx;height: 140rpx;}}.result-tips {font-weight: 600;text-align: center;font-size: 32rpx;color: #515151;margin-top: 20rpx;margin-bottom: 60rpx;}.result-button {padding: 20rpx 100rpx;background-color: rgba(12, 75, 158, 1);border-radius: 60rpx;color: #eeeeee;}}}
</style>
人脸识别页面所有代码(liveb.nvue)
<template><view class="container"><view class="header"><view class="header-title"><text class="header-title-tips">{{titleTips}}</text><view class="header-title-carmera"><image class="header-title-img" src="../../static/change_camera.png" @click="handleChangeCrame"></image></view></view></view><live-pusher id='livePusher' ref="livePusher" class="livePusher" url="" mode="FHD" :muted="true":enable-camera="true" :auto-focus="true" :beauty="2" whiteness="2" aspect="9:16" local-mirror="disable"@statechange="statechange" @error="error" @netstatus="netstatus" :style="[{width:'400rpx',height: '400rpx',marginLeft: '175rpx',marginTop:'20rpx',}]"></live-pusher><cover-image style="width: 400rpx;height: 400rpx;transform: scale(1.01);position: absolute;left: 175rpx;top: 190.5rpx;" src="@/static/circleBg.png" /><view class="footer"><view class="footer-tips"><text class="footer-tips-first">{{footerTipsFirst}}</text><text class="footer-tips-second">{{footerTipsSecond}}</text></view><view class="footer-required"><view class="footer-required-row"><view class="row-area" v-for="(item,index) in tipList" :key="index"><image class="row-area-img" :src="item.icon"></image><text class="row-area-tip">{{item.name}}</text></view></view></view></view><!-- 手动抓拍 --><view class="start-button" :style="{marginTop:footerBtnStyle.marginTop}"><view class="button-hover":style="{width:footerBtnStyle.width,padding:footerBtnStyle.padding,borderRadius:footerBtnStyle.borderRadius,backgroundColor:footerBtnStyle.btnBackground}"@click="startFace"><text class="button-tip" :style="{fontSize:footerBtnStyle.fontSize,color:footerBtnStyle.textColor}">{{buttonTip}}</text></view></view></view>
</template><script>import {requestAndroidPermission,gotoAppPermissionSetting} from '@/js_sdk/wa-permission/permission.js'export default {name: 'sevenq-faceLiver',props: {//是否默认开启抓拍isDeaultStartLive: {type: Boolean,default: false},//默认开启的话需要设置延迟时间(毫秒级)defaultStartDelayTime: {type: Number,default: 600},//是否需要监听结果页传递的事件needListenResultPage: {type: Boolean,default: true},//是否开启可以翻转摄像头isCanChangeCarame: {type: Boolean,default: true},//抓拍倒计时 (如果默认开启需要+1)snapCountdownTimer: {type: Number,default: 6},//如果不允许翻转摄像头 提示词notAllowChangeCarameMsg: {type: String,default: "刷脸认证仅支持前置摄像头"},//顶部提示词topTitleTips: {type: String,default: "请把人脸放在圆圈内拍摄脸部,开始人脸识别"},//提示词 1 footerTipsFirst: {type: String,default: "确认为您本人照片"},//提示词 2footerTipsSecond: {type: String,default: "保持正脸在取景框中系统将在5s后自动抓拍"},//提示展示列表tipList: {type: Object,default: [{icon: "../../static/img3.png",name: '正对手机'},{icon: "../../static/img2.png",name: '光线充足'},{icon: "../../static/img1.png",name: '脸无遮挡'},]},//抓拍倒计时开始时提示词countDownTimerStartTips: {type: String,default: "请保存人脸在实景框中,正在进行抓拍"},//抓拍倒计时为0时提示词countDownTimerZeroTips: {type: String,default: "正在人脸认证中,请稍等..."},//按钮默认文本buttonTips: {type: String,default: "开始人脸识别"},//抓拍倒计时开始时按钮显示提示词countDownTimerStartBtnTips: {type: String,default: "正在抓拍中"},//抓拍倒计时为0时按钮提示词countDownTimerZeroBtnTips: {type: String,default: "人脸认证中...."},//认证成功按钮提示词faceSucessTips: {type: String,default: "认证成功"},//权限提示开启提示词premissonTips: {type: String,default: "当前应用需要使用相机权限进行拍照,但相机权限暂未开启。是否前往应用设置打开相机权限?"},//底部按钮样式footerBtnStyle: {type: Object,default: {marginTop: '120rpx',width: '480rpx',padding: '24rpx',btnBackground: 'rgba(12, 75, 158, 1)',borderRadius: '300rpx',textColor: '#dfdfdf',fontSize: '32rpx'}}},data() {return {titleTips: this.topTitleTips,buttonTip: this.buttonTips,livePusher: '', // livePusher实例snapshotInfo: '', // 快照信息showCountDown: false, // 拍摄倒计时timeOut: this.snapCountdownTimer, // 签到倒计时timeFlag: null, // 定时器isPass: null, // 是否通过人脸认证phoneSysInfos: {}, //当前手机系统信息}},onReady() {this.livePusher = uni.createLivePusherContext("livePusher", this);},onShow() {//监听结果页面传递的失败事件if (this.needListenResultPage) {uni.$on('failResult', (resultData) => {if (resultData.code == '3698') {clearInterval(this.timeFlag)this.resertAll()this.livePusher.startPreview()}});}},async mounted() {const that_ = thisif (!that_.showCountDown) {setTimeout(function() {that_.getCarmeraPremisson()}, this.defaultStartDelayTime)}that_.getPhoneSys()},onUnload() {if (this.needListenResultPage) {uni.$off('failResult');}clearInterval(this.timeFlag)uni.hideLoading();},onHide() {console.log('页面隐藏')},methods: {//校验是否获取相机权限async getCarmeraPremisson() {const currentSystem = uni.getSystemInfoSync().platformif (currentSystem == 'android') {const result = await requestAndroidPermission("android.permission.CAMERA")if (result == 1) {if (this.isDeaultStartLive) { //如果打开页面就进行抓拍this.showCountDown = true}this.startPreview()} else {uni.showModal({title: '提示',content: this.premissonTips,confirmText: '去设置',cancelText: '取消',success: function(res) {if (res.confirm) {gotoAppPermissionSetting()} else if (res.cancel) {uni.showToast({icon: 'error',title: '暂无相机权限'})}}});}}},//重置初始化值 需要在认证失败时候再次调用resertAll() {this.titleTips = this.topTitleTipsthis.buttonTip = this.buttonTipsthis.snapshotInfo = '' // 快照信息this.showCountDown = false // 拍摄倒计时this.timeOut = this.snapCountdownTimer // 签到倒计时this.timeFlag = null // 定时器this.isPass = null // 是否通过人脸认证},//手动翻转摄像头handleChangeCrame() {if (!this.isCanChangeCarame) {uni.showToast({icon: 'none',title: this.notAllowChangeCarameMsg})return}this.livePusher.switchCamera({success: (a) => {uni.showToast({icon: 'none',title: '摄像头翻转成功'})}});},//手动开始人脸识别startFace() {const that_ = thisif (!that_.showCountDown) {that_.showCountDown = trueif (that_.showCountDown) {const {platform,osVersion} = that_.phoneSysInfosif (platform == 'android' && osVersion < 10) { //判断兼容安卓10以下效果that_.startPreview()return}that_.handleSetTime()}}},// 开始预览直播流startPreview() {const _that = thisthis.livePusher.startPreview({success: (res) => {if (_that.showCountDown) {_that.handleSetTime()}}})},// 定时器 几秒后自动抓拍handleSetTime() {this.timeFlag = setInterval(async () => {if (this.timeOut > 0) {this.timeOut--this.titleTips = this.countDownTimerStartTipsthis.buttonTip = `${this.countDownTimerStartBtnTips} ${this.timeOut}秒`}if (this.timeOut == 1) {this.livePusher.snapshot({success: (res) => {this.snapshotInfo = res.message}})}// 进行快照人脸认证if (this.timeOut == 0) {clearInterval(this.timeFlag);this.titleTips = this.countDownTimerZeroTipsthis.buttonTip = this.countDownTimerZeroBtnTipsuni.showLoading({title: this.countDownTimerZeroBtnTips})// this.$emit(handleStartFaceApi, {// code: '4364',// msg: '开始人脸与服务端进行人脸',// currentTempImagePath: this.snapshotInfo.tempImagePath// })uni.uploadFile({url: 'http://192.168.60.2:8080/bsCheckImage/checkImg',filePath: this.snapshotInfo.tempImagePath,name: "file",success: (uploadFileRes) => {const jxStrData = JSON.parse(uploadFileRes.data)console.log(jxStrData)const resResultCode = jxStrData.codeconst resResultData = jxStrData.dataif (resResultCode !== '00000') {uni.navigateTo({url: '/pages/liveb-result/liveb-result?failResultObj=' +this.passData(jxStrData)})this.handleStop()return}if (resResultCode == '00000' && resResultData.score >= 0.8) {uni.showToast({title: this.faceSucessTips})this.buttonTip = this.faceSucessTipsthis.handleStop()return}if (resResultCode == '00000' && resResultData.score < 0.8) {const paramsData = {success: false,code: 'A9901',message: '人脸校验失败,请将人脸正对取景框内重新认证',failCode: 'A9901',faceScore: resResultData.score}uni.navigateTo({url: '/pages/liveb-result/liveb-result?failResultObj=' +this.passData(paramsData)})this.handleStop()return}},fail: (error) => {uni.hideLoading()uni.navigateTo({url: '/pages/liveb-result/liveb-result',animationType: 'zoom-out',animationDuration: 1000})this.handleStop()},complete: () => {uni.hideLoading()clearInterval(this.timeFlag) // 清除定时器,防止再次执行}});}}, 1000)},//向下个页面传递参数passData(obj) {let passDataStr = JSON.stringify(obj)let newPassDataStr = passDataStr.replace(/%/g, '%25');return encodeURIComponent(newPassDataStr);},//抛出停止推流 在调用成功与失败都得调用handleStop() {this.livePusher.stop()},//监听直播流状态变化statechange(val) {console.log(val, '监听直播流变化')},//监听直播流警告error(err) {console.log(err, '监听直播流警告')},//监听网络状态netstatus(status) {console.log(status, '监听直播流网络状态')},//获取手机型号getPhoneSys() {const system = uni.getDeviceInfo()this.phoneSysInfos = system}}}
</script><style lang="scss" scoped>.container {width: 750rpx;}
</style>
效果图如下所示

注意:代码仅可自己使用,不可进行二次转载哈,有问题在请私信我哦
相关文章:
uniapp使用live-pusher实现模拟人脸识别效果
需求: 1、前端实现模拟用户人脸识别,识别成功后抓取视频流或认证的一张静态图给服务端。 2、服务端调用第三方活体认证接口,验证前端传递的人脸是否存在,把认证结果反馈给前端。 3、前端根据服务端返回的状态,显示在…...
【JavaSE】【网络原理】初识网络
目录 一、网络互联二、局域网与广域网三、网络通信基础3.1 IP地址3.2 端口号3.3 网络协议3.4 五元组 四、协议分层4.1 OSI七层网络模型4.2 TCP/IP五层(四层)网络模型4.3 网络设备 五、网络数据通信基本流程。5.1 封装和分用5.2 简述过程 一、网络互联 网络互联: 网…...
鸿蒙之路的坑
1、系统 Windows 10 家庭版不可用模拟器 对应的解决方案【坑】 升级系统版本 直接更改密钥可自动升级系统 密钥找对应系统的(例:windows 10专业版) 升级完之后要激活 坑1、升级完后事先创建好的模拟器还是无法启动 解决:删除模拟…...
Python生日祝福烟花
1. 实现效果 2. 素材加载 2个图片和3个音频 shoot_image pygame.image.load(shoot(已去底).jpg) # 加载拼接的发射图像 flower_image pygame.image.load(flower.jpg) # 加载拼接的烟花图 烟花不好去底 # 调整图像的像素为原图的1/2 因为图像相对于界面来说有些大 shoo…...
Ubuntu环境 nginx.conf详解(二)
1、nginx.conf 结构详解: http 块:用于配置 HTTP 服务器的相关设置,包括处理 HTTP 和 HTTPS。 stream 块:用于配置 TCP/UDP 代理服务器,适用于需要进行四层负载均衡的情况。 ... # 全局块 events {...} …...
shardingsphere分库分表项目实践4-sql解析sql改写
为什么要sql解析重写? 如果我们的系统数据库实现了分表,那么我们的sql中表名需要根据参数动态确定,那么代码怎么写? 方案1: 自己手动拼接, 比如 update t_user_${suffix} , ${suffix} 作为一个变量传递…...
mysql数据库中,一棵3层的B+树,假如数据节点大小是1k,那这棵B+可以存多少条记录(2100万的由来)
在MySQL中,3层的B树可以存储的数据量取决于多个因素,包括页大小、每行数据的大小以及索引项的大小。以下是一个详细的计算过程: 一、假设条件 页大小:在InnoDB存储引擎中,B树的每个节点(页)大…...
Git 操作全解:从基础命令到高级操作的实用指南
文章目录 1.基本命令1.初始化仓库2.克隆远程仓库3.查看当前仓库状态4.查看提交日志5.添加文件到暂存区6.提交更改7.查看仓库的配置信息 2.分支操作1.查看所有分支2.创建新分支3.切换名称4.创建并切换到新分支5.删除分支6.查看当前分支 3.合并分支1.合并分支2.解决合并冲突 4.远…...
华院计算参与项目再次被《新闻联播》报道
12月17日,央视《新闻联播》播出我国推进乡村振兴取得积极进展。其中,华院计算参与的江西省防止返贫监测帮扶大数据系统被报道,该系统实现了由原来的“人找人”向“数据找人”的转变,有效提升监测帮扶及时性和有效性,守…...
从一次线上故障聊聊接口自动化测试
1、背景 3月初,运营同事配置了个还未上线的页面到网站首页 banner,导致用户点了报错。尽管这次很明确是运营人为操作失误引起的故障,但过往此类核心页面的访问异常,我们已不是第一次遇见。 从平台整体利益触发,我们各…...
Element-ui的使用教程 基于HBuilder X
文章目录 1.Element-ui简介2.使用HBuilderX 创建一个基于Vue3的项目 (由于是使用的基于Vue3的Element-ui)3.安装element-ui4.在项目里完全引用element-ui5.引用组件6.运行项目 1.Element-ui简介 Element,一套为开发者、设计师和产品经理准备…...
Chapter 03 复合数据类型-1
1.列表 Python内置的一种有序、可变的序列数据类型; 列表的定义: [ ]括起来的逗号分隔的多个元素组成的序列 列表对象的创建: (1)直接赋值 >>> list1 []#创建一个空列表赋值给list1 >>> list…...
【Python知识】Python面向对象编程知识
Python面向对象编程知识 概述1. 类(Class)2. 对象(Object)3. 封装(Encapsulation)4. 继承(Inheritance)5. 多态(Polymorphism)6. 抽象(Abstractio…...
CSharp: Oracle Stored Procedure query table
存储过程查询postgreSQL,Oracle 和sql server,Mysql 有区别。程序调用也是有区别。 oracle sql script: CREATE OR REPLACE PROCEDURE procSelectSchool(paramSchoolId IN char,p_cursor OUT SYS_REFCURSOR ) AS BEGINOPEN p_cursor FORSELECT *FROM SchoolWHERE SchoolId p…...
“协同过滤技术实战”:网上书城系统的设计与实现
2.1 JSP技术介绍 Java Server Pages这三个英文词汇的首字母的组合就是JSP。所以JSP是一个简写的名字,代表动态网页开发技术。JSP与Java的关系可以使用公式表示,即:JSP HTMLJava,HTML就是编写静态内容的标记语言。JSP则是可以编写网…...
Dhatim FastExcel 读写 Excel 文件
Dhatim FastExcel 读写 Excel 文件 一、说明1、主要特点2、应用场景 二、使用方法1、引入依赖2、Sheet 数据3、读取 Excel4、写入 Excel 一、说明 Github 地址:Dhatim FastExcel Dhatim FastExcel是一个高性能、轻量级的Java库,专门用于读取和写入Exce…...
YOLO11全解析:从原理到实战,全流程体验下一代目标检测
前言 一、模型介绍 二、网络结构 1.主干网络(Backbone) 2.颈部网络(Neck) 3.头部网络(Head) 三、算法改进 1.增强的特征提取 2.优化的效率和速度 3.更高的准确性与更少的参数 4.环境适应性强 5.…...
深度学习领域的主要神经网络架构综述
阅读本文前请先按照顺序阅读: Coursera吴恩达《神经网络与深度学习》课程笔记(1)-- 深度学习概述_吴恩达深度学习课程-CSDN博客 https://blog.csdn.net/red_stone1/article/details/77799014 完结篇 | 吴恩达deeplearning.ai专项课程精炼笔…...
【Nginx系列】---Nginx配置tcp转发
参考 Nginx 配置文件: error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;events {worker_connections 1024; }stream {# 第一个服务转发upstream mysqltest {server 172.16.187.142:9000;}server {listen 9000;proxy_pass mysqltest;}…...
Java抽象工厂+单例模式
在前端时间开发过程中,有这样一个业务场景:A;B两家厂商设备进行设备信息的同步功能。 根据实际场景,做了抽象工厂+单例模式实现调用工厂时,生成不同的具体业务引用对象,实现方法的调用。 概念: 抽象工厂模式通过接口或抽象类来创建一系列相关或依赖对象。它定义了一组工…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...
