uniapp中人脸识别图片并圈起人脸

news2024/12/25 1:37:52

在这里插入图片描述
效果如上,我用的是阿里云的人脸识别。首先,我们先封装一个阿里云的请求js文件

faceRecognition.js

import CryptoJS from 'crypto-js'

//SignatureNonce随机数字
function signNRandom() {
  const Rand = Math.random()
  const mineId = Math.round(Rand * 100000000000000)
  return mineId;
};
//Timestamp
function getTimestamp() {
  let date = new Date();
  let YYYY = pad2(date.getUTCFullYear());
  let MM = pad2(date.getUTCMonth() + 1);
  let DD = pad2(date.getUTCDate());
  let HH = pad2(date.getUTCHours());
  let mm = pad2(date.getUTCMinutes());
  let ss = pad2(date.getUTCSeconds());
  return `${YYYY}-${MM}-${DD}T${HH}:${mm}:${ss}Z`;
}
//补位占位
function pad2(num) {
  if (num < 10) {
    return '0' + num;
  }
  return '' + num;
};
// 排序
function ksort(params) {
  let keys = Object.keys(params).sort();
  let newParams = {};
  keys.forEach((key) => {
    newParams[key] = params[key];
  });
  return newParams;
};
// HmacSHA1加密+base64
function createHmac(stringToSign, key) {
  const CrypStringToSign = CryptoJS.HmacSHA1(stringToSign, key);
  const base64 = CryptoJS.enc.Base64.stringify(CrypStringToSign);
  return base64;
};
//编码
function encode(str) {
  var result = encodeURIComponent(str);
  return result.replace(/!/g, '%21')
    .replace(/'/g, '%27')
    .replace(/\(/g, '%28')
    .replace(/\)/g, '%29')
    .replace(/\*/g, '%2A');
};
function sha1(stringToSign, key) {
  return createHmac(stringToSign, key);
};
function getSignature(signedParams, method, secret) {
  var stringToSign = `${method}&${encode('/')}&${encode(signedParams)}`;
  const key = secret + "&";
  return sha1(stringToSign, key);
};
//参数拼接 &
function objToParam(param) {
  if (Object.prototype.toString.call(param) !== '[object Object]') {
    return '';
  }
  let queryParam = '';
  for (let key in param) {
    if (param.hasOwnProperty(key)) {
      let value = param[key];
      queryParam += toQueryPair(key, value);
    }
  }
  return queryParam;
};
function toQueryPair(key, value) {
  if (typeof value == 'undefined') {
    return `&${key}=`;
  }
  return `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
};
function generateUrl(request, httpMethod, endpoint, accessKeySecret) {
  //参数中key排序
  const sortParams = ksort(request);
  //拼成参数
  const sortQueryStringTmp = objToParam(sortParams);
  const sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
  //构造待签名的字符串
  const Signature = getSignature(sortedQueryString, httpMethod, accessKeySecret)
  //签名最后也要做特殊URL编码
  request["Signature"] = encodeURIComponent(Signature);

  //最终生成出合法请求的URL
  const finalUrl = "https://" + endpoint + "/?Signature=" + encodeURIComponent(Signature) + sortQueryStringTmp;
  return finalUrl;
}

const callRecognizeBankCard  =    function (ImageURL,callback) {
  const accessKeyId = '';
  const accessKeySecret = '';
  const endpoint = "facebody.cn-shanghai.aliyuncs.com";
  const Action = "DetectFace";
	
  // API_HTTP_METHOD推荐使用POST
  const API_HTTP_METHOD = "POST";
  const API_VERSION = "2019-12-30";
	

  const request_ = {};
  //系统参数
  request_["SignatureMethod"] = "HMAC-SHA1";
  request_["SignatureNonce"] = signNRandom();
  request_["AccessKeyId"] = accessKeyId;
  request_["SignatureVersion"] = "1.0";
  request_["Timestamp"] = getTimestamp();
  request_["Format"] = "JSON";
  request_["RegionId"] = "cn-shanghai";
  request_["Version"] = API_VERSION;
	
	
  request_["Action"] = Action; 
  request_["ImageURL"] =  ImageURL
  callApiRequest(request_, API_HTTP_METHOD, endpoint, accessKeySecret, callback);
}

var http = {};
http.request = function (option, callback) {
  var url = option.url;
  var method = option.method;
  var data = option.data;
  var timeout = option.timeout || 0;
  //创建XMLhttpRequest对象
  var xhr = new XMLHttpRequest();
  // var xhr = new plus.net.XMLHttpRequest()
	
	// return
  (timeout > 0) && (xhr.timeout = timeout);
  //使用open方法设置和服务器的交互信息
  xhr.open(method, url, true);
  if (typeof data === 'object') {
    try {
      data = JSON.stringify(data);
    } catch (e) { }
  }
  //发送请求
  xhr.send(data);
  //如果请求完成,并响应完成,获取到响应数据
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
      var result = xhr.responseText;
      try { result = JSON.parse(xhr.responseText); } catch (e) { }
      callback && callback(null, result);
    }
  }.bind(this);
  //延时处理
  xhr.ontimeout = function () {
    callback && callback('timeout');
    console.log('error', '连接超时');
  };
};
// post请求
http.post = function (option, callback) {
  option.method = 'post';
  option.contentType = 'application/json;charset=UTF-8'
  this.request(option, callback);
};


// 封装请求方法
function httpRequest(url, data, method, callback) {
    uni.request({
        url: url,
        method: method,
        data: data,
        header: {
            'content-type': 'application/json'
        },
        success: function (res) {
            callback(null, res.data);
        },
        fail: function (err) {
            callback(err, null);
        }
    });
}


//请求数据
const callApiRequest = (request_, API_HTTP_METHOD, endpoint, accessKeySecret, callback) => {
  const url = generateUrl(request_, API_HTTP_METHOD, endpoint, accessKeySecret);
	
	 httpRequest(url, null, 'POST', function (err, result) {
	        if (err) {
	            console.error('Error:', err);
	            callback(null);
	        } else {
	            console.log('Result:', result);
	            callback(result);
	        }
	    });
}

export default callRecognizeBankCard;

请求之后的响应参数都在文档里面有,https://help.aliyun.com/zh/viapi/developer-reference/api-i5236v?spm=a2c4g.11186623.0.i2

然后开始使用

<view class="re-upload" @click="uploadImage">上传图片</view>

  	<u-modal :show="identifyShow" title="" :showConfirmButton="false">
  		<view class="slot-content" style="width: 100%;position: relative;display: flex;justify-content: center;background-color: #00112b;">
			<image class="ai-bg-top" src="" mode=""></image>
			<view class="ai-image" style="width: 330px !important;height: 350px;margin-top: 200rpx;position: relative;">
			<view class="animation" v-show="scanShow">
			<view class="animation-list"></view></view>
			  <image :src="aiAvatar" mode="" style="width: 100% !important;height: 100%;"></image>
			  <view class="faceRectangles" 
			  v-for="(item, index) in avatarPostionList"
			  :key="index"
			  :style="handlefaceRectanglesStyle(item, index)"
			  >
			  </view>
			</view>
			<image class="ai-bg-bottom" src="" mode=""></image>
  		</view>
  	</u-modal>

import faceRecognition from '@/utils/faceRecognition.js'

const identifyShow = ref(false)
const aiAvatar = ref('')
const scanShow = ref(false)
const studentForm = ref({ avatar: '' })
const avatarPostionList = ref([])

const handlefaceRectanglesStyle = (item, index) => {
	return {
		'position': 'absolute',
		'left': `${item[0]}px`,
		'top': `${item[1]}px`,
		'width': `${item[2]}px`,
		'height': `${item[3]}px`
	}
}

const chunkArray = (array, chunkSize) =>  {
  const groupedArray = [];
  for (let i = 0; i < array.length; i += chunkSize) {
    groupedArray.push(array.slice(i, i + chunkSize));
  }
  return groupedArray;
}

const handleClear = (boolean) => {
	avatarPostionList.value = []
	scanShow.value = boolean
	identifyShow.value = boolean
}

const handleFaceRecognition = (path) => {
	faceRecognition(path, avatar => {
		if(avatar.Code) {
			uni.showToast({
				title: avatar.Message,
				icon: 'none',
				duration: 5000
			})
			identifyShow.value = false
			return;
		}
		if(avatar.Data.FaceCount !== 1) {
			const avatarList = chunkArray(avatar.Data.FaceRectangles, 4)
			avatarPostionList.value = avatarList
			scanShow.value  = false
			setTimeout(() => {
				uni.showModal({
					title: '提示',
					content: '当前照片可能存在多张人脸,是否继续上传?',
					success: res => {
						if(res.confirm) {
							studentForm.value.avatar = path
						}else {
							uni.showToast({
								title: '已取消上传',
								icon: 'none'
							})
						}
						identifyShow.value = false
					}
				})
			}, 1000)
		}else {
			avatarPostionList.value = [avatar.Data.FaceRectangles]
			setTimeout(() => {
				handleClear(false)
				studentForm.value.avatar = path
			}, 1000)
		}
	})
}

const uploadImage = () => {
  uni.chooseImage({
    count: 1,
    success: (res) => {
      //uploadFile,封装的上传方法
      uploadFile(res.tempFilePaths[0], 'avatar', (path:string) => {
      // path为图片线上地址
	  const newPath = `${path}?x-oss-process=image/resize,limit_0,m_fill,w_330,h_350/quality,q_100`
	  // newPath 加宽高之后的图片
		aiAvatar.value = newPath
		handleClear(true)
		setTimeout(() => {
			handleFaceRecognition(newPath)
		}, 5000)
      },()=>{})
    }
  });
}

css

:deep(.u-popup__content){
	width: 350px !important;
	// border-radius: 0 !important;
}
:deep(.u-modal) {
	width: 100% !important;
}
.ai-bg-top {
	position: absolute;
	width: 100%;
	height: 200rpx;
	top: 0;
	left: 0;
}
.ai-bg-bottom {
	position: absolute;
	width: 100%;
	height: 200rpx;
	bottom: 0;
	left: 0;
}
.animation{
	  position: absolute;
	  top: 350rpx;
	  left: 0;
	  right: 0;
	  height: 700rpx;
	
	}
	.animation-list{
	  width: 100%;
	  height: 450rpx;
	  background: linear-gradient(to bottom,rgba(216,179,255,0),rgba(216,179,255,1));
	  position: relative;
	  top: 0;
	  animation: myfist 2s linear 1s infinite alternate;
	}
	
	/* 开始执行动画 */
	@keyframes myfist{
	  0%{
	    background: linear-gradient(to bottom,rgba(216,179,255,0),rgba(216,179,255,1));
	    left: 0;
	    top: -400rpx;
	  }
	  25%{
	    left: 0;
	    top: 100rpx;
	  }
	  50%{
	    left: 0;
	    top: 100rpx;
	  }
	  75%{
	    left: 0;
	    top: 100rpx;
	  }
	  100%{
	    left: 0;
	    top: -400rpx;
	  }
	}

.faceRectangles {
	border: 4rpx solid red;
}

:deep(.u-modal__content){
	padding: 0 !important;
	height: 1100rpx;
	width: 100%;
}
:deep(.u-line){
	display: none !important; 
}

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

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

相关文章

UE5 android打包

下载安装JDK https://repo.huaweicloud.com/java/jdk/https://repo.huaweicloud.com/java/jdk/ 选择对应的jdk版本 配置环境变量 编辑Path 验证是否成功 java -version 安装Android Studio https://developer.android.google.cn/studio?hlzh-cnhttps://developer.androi…

EMQX 4.0和EMQX 5.0集群架构实现1亿MQTT连接哪些改进

EMQX 5.0水平扩展能力得到了指数级提升&#xff0c;能够更可靠地承载更大规模的物联网设备连接量。 在EMQX5.0正式发布前的性能测试中&#xff0c;我们通过一个23节点的EMQX集群&#xff0c;全球首个达成了1亿MQTT连接每秒100万消息吞吐&#xff0c;这也使得EMQX 5.0成为目前为…

【C++ 设计模式】简单工厂模式

文章目录 前言一、简单工厂模式是什么&#xff1f;二、实现原理三、UML类图四、简单工厂模式具体代码总结 前言 在软件开发中&#xff0c;设计模式是解决特定问题的可复用解决方案。其中&#xff0c;简单工厂模式是一种创建型设计模式&#xff0c;旨在封装对象的创建过程&…

IDEA开启Run Dashboard

1、Run Dashboard是什么&#xff0c;为什么要使用 Run Dashboard 是 IntelliJ IDEA 中的一个工具窗口&#xff0c;用于管理和监视项目中正在运行的应用程序和配置。它提供了一种集中管理运行和调试过程的方式&#xff0c;可以让开发人员更方便地查看和控制正在运行的应用程序。…

2 Redis的安装与配置

这里是要将 Redis 安装到 Linux 系统中。 1.1 Redis 的安装 1.1.1 克隆并配置主机 修改主机名&#xff1a;/etc/hostname修改网络配置&#xff1a;/etc/sysconfig/network-scripts/ifcfg-ens33 1.1.2 安装前的准备工作 &#xff08;1 &#xff09;安装 gcc &#xff08;2…

如何从 Mac 电脑外部硬盘恢复删除的数据文件

本文向您介绍一些恢复 Mac 外置硬盘数据的快速简便的方法。 Mac 的内部存储空间通常不足以存储所有数据。因此&#xff0c;许多用户通过外部驱动器扩展存储或创建数据备份。然而&#xff0c;与几乎所有其他设备一样&#xff0c;从外部硬盘驱动器丢失有价值的数据并不罕见。由于…

数据库是什么?数据库连接、管理与分析工具推荐

一、数据库是什么&#xff1f; 数据库是一种结构化的数据存储系统&#xff0c;用于有效地组织、存储和管理大量的数据。它是一个集中化的数据存储库&#xff0c;通常由一个或多个数据表组成&#xff0c;每个数据表包含多个行和列&#xff0c;用于存储特定类型的数据。数据表中…

SQLiteC/C++接口详细介绍之sqlite3类(七)

上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;六&#xff09; 下一篇&#xff1a; SQLiteC/C接口详细介绍之sqlite3类&#xff08;八&#xff09;&#xff08;未发表&#xff09; 22.sqlite3_create_collation、sqlite3_create_collation16和sqlite3_creat…

【java工具】Maven的下载配置+setting配置(以3.9.6为例)

本人正在学习spring&#xff0c;还是个小白&#xff0c;也是跟着网课和各种资料学&#xff0c;光学习spring项目的各种配置就花了我不少时间QWQ。在学习spring的每个阶段&#xff0c;我会做好技术总结&#xff0c;不定期分享出来&#xff0c;希望对你有所帮助&#xff0c;有问题…

【Node.js从基础到高级运用】十二、身份验证与授权:JWT

身份验证与授权是现代Web应用中不可或缺的部分。了解如何在Node.js应用中实施这些机制&#xff0c;将使你能够构建更安全、更可靠的应用程序。本文将引导你通过使用JWT实现用户注册、登录和权限控制的过程。 JWT&#xff08;Json Web Token&#xff09; JWT是一种用于双方之间…

COX回归影响因素分析的基本过程与方法

在科学研究中&#xff0c;经常遇到分类的结局&#xff0c;主要是二分类结局&#xff08;阴性/阳性&#xff1b;生存/死亡&#xff09;&#xff0c;研究者可以通过logistic回归来探讨影响结局的因素&#xff0c;但很多时候logistic回归方法无法使用。如比较两种手段治疗新冠肺炎…

报表生成器FastReport .Net用户指南:关于脚本(上)

FastReport的报表生成器&#xff08;无论VCL平台还是.NET平台&#xff09;&#xff0c;跨平台的多语言脚本引擎FastScript&#xff0c;桌面OLAP FastCube&#xff0c;如今都被世界各地的开发者所认可&#xff0c;这些名字被等价于“速度”、“可靠”和“品质”,在美国&#xff…

hive-批量导出表结构,导入表结构

1、导出hive表结构 datastudio可以连接hive库&#xff0c;通过show databases 语句可以显示hive下建了多少数据库名。 使用use 数据库名&#xff0c;进入某个数据库下&#xff0c;通过show tables可显示该数据库下建了多少张表。 将所有库的表数据整理成库名.表名的形式放入…

python基于flask考研学习交流系统30vy7附源码django

考研在线学习与交流平台根据实际情况分为前后台两部分&#xff0c;前台部分主要是让用户使用的&#xff0c;包括用户的注册登录&#xff0c;首页&#xff0c;课程信息&#xff0c;在线讨论&#xff0c;系统公告&#xff0c;后台管理&#xff0c;个人中心等功能&#xff1b;后台…

Qt_vc++崩溃日志分析

环境 Clion &#xff1a;2019.3.6 Qt &#xff1a;5.9.6&#xff08;vc2015&#xff09; 编译工具&#xff1a;vs2015 update3 崩溃日志收集 自行百度&#xff0c;会查到很多&#xff0c;一下代码仅供参考&#xff08;来自https://blog.csdn.net/weixin_45571586/article/…

java的23种设计模式02-创建型模式02-抽象工厂方法

一、抽象工厂方法 1-1、抽象工厂方法的定义 抽象工厂模式是一个比较复杂的创建型模式。 抽象工厂模式和工厂方法不太一样&#xff0c;它要解决的问题比较复杂&#xff0c;不但工厂是抽象的&#xff0c;产品是抽象的&#xff0c;而且&#xff1a;有多个产品需要创建&#xff…

HTML案例-2.标签综合练习

目录 效果 知识点 1.图像标签 2.链接标签 3.锚点定位 4.base标签 源码 页面1 页面2 效果 知识点 1.图像标签 <img src="图像URL" /> 单标签 属性 属性值 描述 src URL 图像的路径 alt 文本

导入csv文件表头字符串出现zwnbsp字符(零宽度空白字符)处理

导入csv文件表头字符串出现zwnbsp字符&#xff08;零宽度空白字符&#xff09;处理 【1】现象描述【2】问题分析【3】原因分析【4】问题解决&#xff08;1&#xff09;修改文件的编码格式&#xff08;2&#xff09;在代码中处理 【1】现象描述 通过easyexcel导入csv文件&#…

9种分布式ID生成之美团(Leaf)实战

​​​​​ 前几天写过一篇《一口气说出 9种 分布式ID生成方式&#xff0c;面试官有点懵了》&#xff0c;里边简单的介绍了九种分布式ID生成方式&#xff0c;但是对于像美团&#xff08;Leaf&#xff09;、滴滴&#xff08;Tinyid&#xff09;、百度&#xff08;uid-generator&…

mac【启动elasticsearch报错:can not run elasticsearch as root

mac【启动elasticsearch报错&#xff1a;can not run elasticsearch as root 问题原因 es默认不能用root用户启动&#xff0c;生产环境建议为elasticsearch创建用户。 解决方案 为elaticsearch创建用户并赋予相应权限。 尝试了以下命令创建用户&#xff0c;adduser esh 和u…