uniapp---app端人脸识别组件(宽屏版1280*800组件,需手动截屏拍人脸识别,踩坑,成长)

news2024/11/24 15:50:33

一、首先记录下踩到的坑

我这边做的是一个挂在门口的门牌机,可以用于扫脸签到,扫码签到,扫脸实现用的是live-pusher组件(代码很长,放在最下面,不能直接用,需要根据实际情况修改)去做的人脸识别,在测试安卓机上一切正常,在安卓宽屏设备(akuvox牌子的门禁机)上出现各种问题,最主要是不能用usb调试!!!只能打包调试太折磨了

坑1:官方live-pusher组件的snapshot方法没有触发回调,原因是该设备不会主动询问是否开启存储权限,需要手动设置如果遇到点击快门没反应,请检查是否主动开启了设备的存储权限,没有的话点击这里,按照这个地址(Dcloud社区)方法去操作

 给懒得跳链接的朋友放个传送门,主要就是下面附带的代码,用于申请设备权限

 图片中的代码:

    "permissionExternalStorage": {  
        "request": "always",  
        "prompt": "应用保存运行状态等信息,需要获取读写手机存储(系统提示为访问设备上的照片、媒体内容和文件)权限,请允许。"  
     }

坑2:获取设备的mac地址 这个真的是几经波折,最后在插件市场找到了救命稻草,mt-device-info - DCloud 插件市场

云插件官方使用指南:uni-app官网


除了踩坑,也有获取到在uniapp在特殊(宽屏)设备上开发app的经验


1、首先设备尺寸是1280*800,我们打算用rpx来画页面,这边还有个需要注意的地方就是,uniapp官方秉承最大程度上保持界面不失真的策略,“限定了可适配的最大屏幕宽度为960px,在这个范围内,rpx可以根据屏幕宽度缩放。一旦超过960,rpx再根据屏幕宽度缩放就变的没有意义了”(也就是设计稿上的图像会失真)

当然也可以自己去手动设置来调整这个“可适配的最大屏幕宽度”,在page.json文件中加入以下属性,这边以我用到的这个设备为例

page.json文件:

2、 HBuilder开发的话 可以去设置px转rpx提示,这个也很方便,具体设置步骤如下

 

这边根据设计稿去配比就好了,最后设置成功效果如下:

 

最后附上代码,截屏页组件代码如下:

<template>
	<view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
		<view class="preview" :style="{ width: windowWidth, height: windowHeight - 10 }">
			<live-pusher id="livePusher" ref="livePusher" class="livePusher" mode="FHD" beauty="1" whiteness="0"
				:aspect="aspect" min-bitrate="1000" audio-quality="16KHz" device-position="back" :auto-focus="true"
				:muted="true" :enable-camera="true" :enable-mic="false" :zoom="false" @statechange="statechange"
				:style="{ width: cameraWidth, height: cameraHeight }"></live-pusher>
			<live-pusher />

			< <!--提示语-->
				<cover-view class="remind">
					<text class="remind-text" style="">{{ message }}</text>
				</cover-view>

				<!--辅助线-->
				<!-- <cover-view class="outline-box" :style="{ width: windowWidth, height: windowHeight - 80 }">
					<cover-image class="outline-img" src="/static/live-camera/outline/idphoto.png" style="">
					</cover-image>
				</cover-view> -->
		</view>

		<view class="menu">
			<!--底部菜单区域背景-->
			<cover-image class="menu-mask" src="/static/live-camera/bar.png"></cover-image>

			<!--返回键-->
			<cover-image class="menu-back" @tap="back" src="/static/live-camera/back.png"></cover-image>

			<!--快门键-->
			<cover-image class="menu-snapshot" @tap="snapshot" src="/static/live-camera/shutter.png"></cover-image>

			<!--反转键-->
			<!-- <cover-image class="menu-flip" @tap="flip" src="/static/live-camera/flip.png"></cover-image> -->
		</view>
	</view>
</template>

<script>
	import config from "@/utils/config.js"
	let _this = null;
	export default {
		data() {
			return {
				// actions: config.VUE_APP_BASE_API + '/jeecg-boot/fjxhx/file/upload/file',
				actions: 'http://172.30.1.132:10038/arcface/user/face/get',
				dotype: 'idphoto', //操作类型
				message: '', //提示
				aspect: '2:3', //比例
				cameraWidth: '', //相机画面宽度
				cameraHeight: '', //相机画面宽度
				windowWidth: '', //屏幕可用宽度
				windowHeight: '', //屏幕可用高度
				camerastate: false, //相机准备好了
				livePusher: null, //流视频对象
				snapshotsrc: null, //快照
				isStopPreview: false // 关闭视频流,轮询不开启。
			};
		},
		onLoad(e) {
			_this = this;
			if (e.dotype != undefined) this.dotype = e.dotype;
			this.initCamera();
		},
		onReady() {
			this.livePusher = uni.createLivePusherContext('livePusher', this);
			// this.startPreview(); //开启预览并设置摄像头
			this.poenCarme();
		},
		methods: {
			//轮询打开
			poenCarme() {
				//#ifdef APP-PLUS
				if (plus.os.name == 'Android') {
					this.poenCarmeInterval = setInterval(function() {
						// console.log(_this.camerastate);
						if (!_this.camerastate) _this.startPreview();
					}, 2500);
				}
				//#endif
			},

			//初始化相机
			initCamera() {
				uni.getSystemInfo({
					success: function(res) {
						_this.windowWidth = res.windowWidth;
						_this.windowHeight = res.windowHeight;
						_this.cameraWidth = res.windowWidth;
						_this.cameraHeight = res.windowWidth / 1.5;
					}
				});
			},

			//开始预览
			startPreview() {
				if (_this.isStopPreview) {
					return
				}
				this.livePusher.startPreview({
					success: a => {
						console.log(a);
					}
				});
			},
			//停止预览
			stopPreview() {
				this.livePusher.stopPreview({
					success: a => {
						_this.camerastate = false; //标记相机未启动
					}
				});
			},

			//状态
			statechange(e) {
				//状态改变
				console.log(e);
				if (e.detail.code == 1007) {
					_this.camerastate = true;
				} else if (e.detail.code == -1301) {
					_this.camerastate = false;
				}
			},

			//返回
			back() {
				uni.navigateBack();
			},

			//抓拍
			snapshot() {

				this.livePusher.snapshot({
					success: e => {

						console.log('snapshot123', e)
						_this.isStopPreview = true
						uni.showLoading({
							title: '上传图片中',
							mask: true
						})
						_this.snapshotsrc = e.message.tempImagePath;
						_this.stopPreview();
						const fileInfo = {
							'fileName': 'wxImg.jpg',
							'fileHash': '1111'
						}
						const formData = {
							// 'file': e,
							'ct': JSON.stringify(fileInfo)
						}
						// this.uploadImg(formData)
						// return
						uni.compressImage({ // 压缩图片
							src: e.message.tempImagePath,
							quality: 20,
							success: res => {
								console.log('res.tempFilePath', res.tempFilePath)
								_this.snapshotsrc = res.tempFilePath;
								this.uploadImg(formData)
							},
							fail: res => {
								console.log(1112)
								_this.uploadFail()
							},
							computed: res => {
								console.log('res.tempFilePath', res.tempFilePath)
								// _this.snapshotsrc = res.tempFilePath;
								// this.uploadImg(formData)
							}
						})
					},
					error: e => {

					}
				});
			},
			// 上传图片
			uploadImg(formData) {
				console.log('_this.actions11133', _this.actions, _this.snapshotsrc)
				uni.uploadFile({
					// url: _this.actions, 
					url: _this.actions,
					// filePath: _this.snapshotsrc,
					files: [{
						uri: _this.snapshotsrc
					}],
					name: 'file',
					formData: formData,
					success: (uploadFileRes) => {
						console.log(uploadFileRes, typeof uploadFileRes.data);
						if (JSON.parse(uploadFileRes.data).code === 200) {
							let data = JSON.parse(uploadFileRes.data).result
							console.log('========uploadFileRes', JSON.parse(uploadFileRes.data).result, JSON
								.parse(uploadFileRes.data).code);
							_this.setImage(JSON.parse(uploadFileRes.data));
							_this.isStopPreview = false
							uni.hideLoading();
							// _this.$utils.nnToast('图片上传成功')
							uni.navigateBack();
						} else {
							_this.uploadFail(JSON.parse(uploadFileRes.data).message)
						}
					},
					fail: () => {
						console.log(1112)
						_this.uploadFail(JSON.parse(uploadFileRes.data).message)
					},
				})

			},
			uploadFail(msg) {
				uni.showLoading({
					title: msg,
					mask: true
				})
				// _this.$utils.nnToast('图片上传失败')
				setTimeout(function() {
					_this.isStopPreview = false
					uni.hideLoading();
					uni.navigateBack();
				}, 2000);
			},
			//反转
			flip() {
				this.livePusher.switchCamera();
			},

			//如果人脸识别成功 则带参数返回上一页进行签到
			setImage(data) {

				console.log('------------------setImage(data) ', data, );
				uni.$emit('setImage', {
					// path: _this.snapshotsrc,
					// dotype: this.dotype,
					userId: data.result.userId
				})
				//直接调用上一个页面的setImage()方法,把数据存到上一个页面中去
				// let pages = getCurrentPages();
				// let prevPage = pages[pages.length - 2]; //上一个页面
				// prevPage.setImage({
				// 	path: _this.snapshotsrc,
				// 	dotype: this.dotype,
				// 	imgId: imgId
				// });
			}
		}
	};
</script>

<style scoped lang="scss">
	.live-camera {
		.preview {
			justify-content: center;
			align-items: center;

			.outline-box {
				position: absolute;
				top: 0;
				left: 0;
				bottom: 0;
				z-index: 99;
				align-items: center;
				justify-content: center;

				.outline-img {
					width: 750px;
					// height: 1125rpx;
				}
			}

			.remind {
				position: absolute;
				top: 880rpx;
				width: 750rpx;
				z-index: 100;
				align-items: center;
				justify-content: center;

				.remind-text {
					color: #dddddd;
					font-weight: bold;
				}
			}
		}

		.menu {
			position: absolute;
			left: 0;
			bottom: 0;
			width: 750rpx;
			height: 60rpx;
			z-index: 98;
			align-items: center;
			justify-content: center;

			.menu-mask {
				position: absolute;
				left: 0;
				bottom: 0;
				width: 750rpx;
				height: 80rpx;
				z-index: 98;
			}

			.menu-back {
				position: absolute;
				left: 30rpx;
				bottom: 0rpx;
				width: 60rpx;
				height: 60rpx;
				z-index: 99;
				align-items: center;
				justify-content: center;
			}

			.menu-snapshot {
				width: 60rpx;
				height: 60rpx;
				z-index: 999999;
				position: absolute;
				bottom: 0rpx;
			}

			.menu-flip {
				position: absolute;
				right: 30rpx;
				bottom: 0rpx;
				width: 80rpx;
				height: 80rpx;
				z-index: 99;
				align-items: center;
				justify-content: center;
			}
		}
	}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/786471.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

处理多维特征的输入

数据的每一列称为&#xff1a;特征/字段 x的数据变为8列&#xff0c;维数8 step one:构建数据集 x_data;y_data&#xff1a;创建两个Tensor step two:定义模型 step three:构造损失和优化器 step four:训练 else 激活函数&#xff1a; 代码更改部分&#xff1a; 转->大佬笔…

基于AutoEncoder自编码器的人脸识别matlab仿真

目录 1.算法理论概述 2.部分核心程序 3.算法运行软件版本 4.算法运行效果图预览 5.算法完整程序工程 1.算法理论概述 人脸识别是计算机视觉领域的重要研究方向&#xff0c;其目标是从图像或视频中准确地识别和识别人脸。传统的人脸识别方法通常基于特征提取和分类器&#…

Java虚拟机——后端编译与优化

编译器无论在何时、何种状态下将Class文件转换成与本地基础设施相关的二进制机器码&#xff0c;它都可以视为整个编译过程的后端。即时编译一直是绝对主流的编译形式&#xff0c;不过提前编译也逐渐被主流JDK支持。 1 即时编译器 目前两款主流的Java虚拟机&#xff08;HotSpo…

【MATLAB绘图】

MATLAB绘图函数&#xff1a;Plot函数详解 介绍 MATLAB是一种常用的科学计算和数据可视化工具&#xff0c;它提供了强大的绘图函数&#xff0c;使用户能够创建各种类型的图表和图形。 基本语法 plot函数的基本语法如下&#xff1a; plot(x, y)其中&#xff0c;x和y是长度相…

HDFS的文件块大小(重点)

HDFS 中的文件在物理上是分块存储 &#xff08;Block &#xff09; &#xff0c; 块的大小可以通过配置参数( dfs.blocksize&#xff09;来规定&#xff0c;默认大小在Hadoop2.x/3.x版本中是128M&#xff0c;1.x版本中是64M。 如果一个文件文件小于128M&#xff0c;该文件会占…

Git 命令行教程:如何在 GitLab 中恢复已删除的分支

在软件开发过程中&#xff0c;版本控制是一个至关重要的环节。Git 是最流行的分布式版本控制系统之一&#xff0c;它能够帮助团队高效地管理代码。然而&#xff0c;有时候会发生意外&#xff0c;例如代码误合、错误的删除等情况&#xff0c;导致重要的开发分支本地和远程不慎被…

vue2踩坑之项目:v-if/else branches must use unique keys.

error: v-if/else branches must use unique keys. if 与 else 的 key 不能相同&#xff0c;在else标签里的key逐步加1 // if 与 else 的 key 不能相同 <div v-for"(item, index) in menuList" :key"item.id"><div v-if"item.name" :k…

js 操作符 in 的使用

1、判断对象中是否有某个属性&#xff0c;返回true/false let person {name: "小明", age: 18, year: 1998}; if ("age" in person){ //属性名必须是字符串形式&#xff0c;因为age不是一个变量console.log("person对象中含有age属性") } els…

(六)如何使用FLUX语言的文档

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 6 章 如何使用FLUX语言的文档 6.1 如何查看函数文档 1、这是FLUX语言的文档 https://docs.influxdata.com…

(七)FLUX查询InfluxDB

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 7 章 FLUX查询InfluxDB 7.1 前言 1、本节内容较为重要 7.2 FLUX查询InfluxDB的语法 1、使用FLUX语言查询…

AbstractMethodError: com.xx.serviceImpl.xxx method is abstract

今日一语&#xff1a; 其实我们没有必要和其他人进行比较&#xff0c;我们要比较的是昨天的自己 只有这样才能得到救赎和解脱&#xff0c;否则就是泥潭中跳跃&#xff0c;山谷中呐喊 在翻阅其他博主的博客时&#xff0c;似乎大多分享的是因为数据源驱动或者中间件的版本太高或者…

SpringCloud - 狂神学习笔记

1. 常见面试题 1.1 什么是微服务&#xff1f; 1.2 微服务之间是如何独立通讯的&#xff1f; 1.3 SpringCloud 和 Dubbo有那些区别&#xff1f; 1.4 SpringBoot 和 SpringCloud&#xff0c;请谈谈你对他们的理解 1.5 什么是服务熔断&#xff1f;什么是服务降级&#xff1f;…

微调模型来完成热狗识别的图像分类任务

我们来实践一个具体的例子&#xff1a;热狗识别。将基于一个小数据集对在ImageNet数据集上训练好的ResNet模型进行微调。该小数据集含有数千张热狗或者其他事物的图像。我们将使用微调得到的模型来识别一张图像中是否包含热狗。 首先&#xff0c;导入实验所需的工具包。 impo…

“铸网-2023” | 持续保障江西省实网应急演练

​​日前&#xff0c;由江西省工业和信息化厅主办&#xff0c;江西省网络安全研究院承办&#xff0c;南京赛宁信息技术有限公司协办并提供全程技术支撑的“铸网-2023”江西省工业领域网络安全实网应急演练在江西南昌圆满收官。 一、应急演练43天 赛宁持续助推工业企业应急能力…

论文精度系列之详解图神经网络

论文地址:A Gentle Introduction to Graph Neural Networks 翻译:图表就在我们身边;现实世界的对象通常根据它们与其他事物的连接来定义。一组对象以及它们之间的连接自然地表示为图形。十多年来&#xff0c;研究人员已经开发了对图数据进行操作的神经网络&#xff08;称为图神…

二叉树题目:从根到叶的二进制数之和

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;从根到叶的二进制数之和 出处&#xff1a;1022. 从根到叶的二进制数之和 难度 3 级 题目描述 要求 给你二叉树…

vue权限按钮的实现

鉴权函数 由于下面几种方式都需要用到鉴权函数&#xff0c;所以将其放置在组件外面&#xff0c;供组件或其他文件调用。 // src/utils/hasPermission.jsimport { usePermissionStore } from /stores import array from lodash/array export const hasPermission (value, def…

火车头采集文章批量伪原创【php源码】

火车头采集是一款基于Python语言开发的网络爬虫工具&#xff0c;用于快速高效地从互联网上采集数据并存储到本地或远程数据库。它简单易用且功能强大&#xff0c;在各行各业广泛应用。 火车头采集器AI伪原创PHP源码&#xff1a; <?php header("Content-type: text/h…

C# WPF项目创建(基于VS 2019介绍)

1.打开VS&#xff0c;选择《创建新项目》 2.选择《WPF应用程序》&#xff0c;如图 3. 项目名称根据需求自行命名&#xff0c;这边以“WpfApp1”来命名&#xff0c;位置自行选择&#xff0c;这边选择了"E:\test"&#xff0c;如图所示&#xff0c;“将解决方案和项目…

【广州华锐互动】VR模拟灭火逃生体验系统

VR模拟灭火逃生体验系统由广州华锐互动开发&#xff0c;是一种基于虚拟现实技术的应急演练与培训系统&#xff0c;可以真实模拟消防逃生场景&#xff0c;让体验者在沉浸式的虚拟环境中&#xff0c;根据正确的消防逃生方法提示&#xff0c;进行自救演练。这种科学普及方法是更加…