赞
踩
效果如上,我用的是阿里云的人脸识别。首先,我们先封装一个阿里云的请求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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。