// packageB/pages/AI-test-skin/analyse/analyse.js const app = getApp(); const request = app.request; const os = app.globalData; const setting = os.setting; const ut = require('../../../../utils/util'); import { pluginGD } from '../../../ai_config/config' // , // "plugins": { // "mtSkinSdk": { // "version": "1.4.2", // "provider": "wx3636b350f8484f20" // } // } Page({ /** * 页面的初始数据 */ data: { iurl: setting.imghost, per: 0, timer: 0, img: null, sourceimg: null, err_map: null, skin_type: 0, ce_user_id:0, img_remark:'' }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { if(this.data.skin_type){ var plugin = requirePlugin('mtSkinSdk') plugin.setConfig(pluginGD) } this.setData({img_remark:options.img_remark}) if(options.ce_user_id) this.data.ce_user_id=options.ce_user_id; var th = this; //设置错误码分析 this.set_err_map(); //进度条加载 this.timer(); //接口开始分析 setTimeout(function () { //先检验一下图片 th.data.skin_type ? th.img_check_mt() : th.img_check_bd(); }, 800) }, //定时器 timer: function (func) { var per = this.data.per + 5; var th = this; if (per < 96) { th.setData({ per: per }); setTimeout(function () { th.timer(); }, 400) } }, //错误码表 set_err_map: function () { var map = { "2": "服务暂不可用", "4": "集群超限额", "6": "没有接口权限", "17": "每天流量超限额", "18": "QPS超限额", "19": "请求总量超限额", "100": "无效的access_token参数", "110": "Access Token失效", "111": " Access token过期", "222001": "必要参数未传入", "222002": "参数格式错误", "222003": "参数格式错误", "222004": "参数格式错误", "222005": "参数格式错误", "222006": "参数格式错误", "222007": "参数格式错误", "222008": "参数格式错误", "222009": "参数格式错误", "222010": "参数格式错误", "222011": "参数格式错误", "222012": "参数格式错误", "222013": "参数格式错误", "222014": "参数格式错误", "222015": "参数格式错误", "222016": "参数格式错误", "222017": "参数格式错误", "222018": "参数格式错误", "222019": "参数格式错误", "222020": "参数格式错误", "222021": "参数格式错误", "222022": "身份证号不符合要求,备注:中国大陆身份证号的每一位数字都有其生成规则,不可随意填写。", "222023": "参数格式错误", "222024": "参数格式错误", "222025": "参数格式错误", "222026": "参数格式错误", "222027": "验证码长度错误(最小值大于最大值)", "222028": "参数格式错误", "222029": "参数格式错误", "222030": "参数格式错误", "222039": "参数格式错误", "222200": "该接口需使用application/json的格式进行请求", "222201": "服务端请求失败", "222202": "未识别到单个人脸",//未识别到单个人脸 "222203": "无法解析人脸", "222204": "从图片的url下载图片失败", "222205": "服务端请求失败", "222206": "服务端请求失败", "222207": "未找到匹配的用户", "222208": "图片的数量错误", "222209": "face token不存在", "222210": "人脸库中用户下的人脸数目超过限制", "222300": "人脸图片添加失败", "222301": "获取人脸图片失败", "222302": "服务端请求失败", "222303": "获取人脸图片失败", "222152": "人脸属性编辑,target参数错误", "222514": "人脸属性编辑v2调用服务失败,请重试", "223100": "操作的用户组不存在", "223101": "该用户组已存在", "223102": "找不到该用户", "223103": "找不到该用户", "223104": "group_list包含组数量过多", "223105": "该人脸已存在", "223106": "该人脸不存在", "223107": "人脸库中人脸复制时源组与目标组的scene_type不同", "223110": "uid_list包含数量过多", "223111": "目标用户组不存在", "223112": "quality_conf格式不正确", "223113": "人脸有被遮挡", "223114": "人脸模糊", "223115": "人脸光照不好", "223116": "人脸不完整", "223117": "app_list包含app数量过多", "223118": "质量控制项错误", "223119": "活体控制项错误", "223120": "活体检测未通过", "223121": "质量检测未通过 左眼遮挡程度过高", "223122": "质量检测未通过 右眼遮挡程度过高", "223123": "质量检测未通过 左脸遮挡程度过高", "223124": "质量检测未通过 右脸遮挡程度过高", "223125": "质量检测未通过 下巴遮挡程度过高", "223126": "质量检测未通过 鼻子遮挡程度过高", "223127": "质量检测未通过 嘴巴遮挡程度过高", "222901": "参数校验初始化失败", "222902": "参数校验初始化失败", "222903": "参数校验初始化失败", "222904": "参数校验初始化失败", "222905": "接口初始化失败", "222906": "接口初始化失败", "222907": "缓存处理失败", "222908": "缓存处理失败", "222909": "缓存处理失败", "222910": "数据存储处理失败", "222911": "数据存储处理失败", "222912": "数据存储处理失败", "222913": "接口初始化失败", "222914": "接口初始化失败", "222915": "后端服务连接失败", "222916": "后端服务连接失败", "222304": "图片尺寸太大", "222305": "当前版本不支持图片存储", "223128": "正在清理该用户组的数据", "223136": "该组内存在关联图片,无法新建相同名称组", "222361": "公安服务连接失败", "222046": "参数格式错误", "222101": "参数格式错误", "222102": "参数格式错误", "222307": "图片非法 鉴黄未通过", "222308": "图片非法 含有政治敏感人物", "222211": "人脸融合失败 模板图质量不合格", "222212": "人脸融合失败", "223129": "人脸未面向正前方(人脸的角度信息大于30度)", "223130": "spoofing_control参数格式错误", "223131": "合成图检测未通过", "223201": "请求参数scene_type 格式错误", "223202": "识别时请求的scene_type与group设置的scene_type不匹配", } this.setData({ err_map: map }); }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, //检查图片有没有OK 百度 img_check_bd: function (func) { var th = this; var user_id=this.data.ce_user_id || getApp().globalData.user_id; var data = { "appid": "25521854", "image": getApp().globalData.face_SourceImg, "face_field": "age,expression,face_shape,gender,glasses,landmark,landmark150,quality,eye_status,emotion,face_type,mask,spoofing", "image_type": "URL", "store_id":setting.stoid, "user_id":user_id } //开始调用百度接口,进行对图片进行判断是否符合标准 this.json_post("/api/weshop/baidubce/face/skindetect", data, function (res) { if (res.data.code == 0) { //检查的字段存储 var check_data = th.data.check_data = res.data.data; check_data = check_data.face_list[0]; if(!check_data) { getApp().showWarning('网络繁忙,请稍后再试'); return false; } let fail_result = new Array(); console.log(check_data); //检查睁眼闭眼 var eye_status = check_data.eye_status; console.log('eye_status',eye_status); if (eye_status.left_eye > 0.5 || eye_status.right_eye > 0.5) { // var msg = "未闭眼拍照"; // th.go_error(msg); // return false; fail_result.push({ type: 1, reason: "未闭眼拍摄" }) } //检查是不是有带眼镜 if (check_data.glasses.type != 'none') { // var msg = "有佩戴眼镜"; // th.go_error(msg); // return false; fail_result.push({ type: 2, reason: "未摘下眼镜拍摄" }) } var quality = check_data.quality; //检查框里人脸情况 if (quality.completeness = 0) { // var msg = "人脸未显示完整"; // th.go_error(msg); // return false; fail_result.push({ type: 3, reason: "未识别到单个人脸" }) } //检查环境情况 if (quality.blur > 0.7 || quality.illumination < 40) { // var msg = "图片模糊"; // th.go_error(msg); // return false; fail_result.push({ type: 4, reason: "质量检测未通过" }) } // if (Math.abs(angle.Roll) > 20) { // var msg = "头部的平面角度过大"; // th.go_error(msg); // return false; // } // if (Math.abs(angle.Yaw) > 20) { // var msg = "头部的左右角度过大"; // th.go_error(msg); // return false; // } //开始检查遮挡 var zhe_dnag = 0; var occlusion = check_data.quality.occlusion; if (occlusion.left_eye > 0.6) { // var msg = "左眼被遮挡"; // th.go_error(msg); // return false; zhe_dnag = 1; } if (occlusion.right_eye > 0.6) { // var msg = "右眼被遮挡"; // th.go_error(msg); // return false; zhe_dnag = 1; } if (occlusion.nose > 0.7) { // var msg = "鼻子被遮挡"; // th.go_error(msg); // return false; zhe_dnag = 1; } if (occlusion.mouth > 0.7) { // var msg = "嘴巴被遮挡"; // th.go_error(msg); // return false; zhe_dnag = 1; } if (occlusion.left_cheek > 0.8) { // var msg = "左脸颊被遮挡"; // th.go_error(msg); // return false; zhe_dnag = 1; } if (occlusion.right_cheek > 0.8) { // var msg = "右脸颊被遮挡"; // th.go_error(msg); // return false; zhe_dnag = 1; } if (occlusion.chin_contour > 0.6) { // var msg = "下巴颊被遮挡"; // th.go_error(msg); // return false; zhe_dnag = 1; } if (zhe_dnag) { fail_result.push({ type: 7, reason: "脸部有遮挡物" }) } //检查头部的角度 var angle = check_data.angle; if (Math.abs(angle.Pitch) > 20 || Math.abs(angle.Roll) > 20 || Math.abs(angle.Yaw) > 20) { // var msg = "头部的俯仰角度过大"; // th.go_error(msg); // return false; fail_result.push({ type: 8, reason: "未保持正脸拍摄" }) } // if (quality.illumination < 40) { // var msg = "图像光照不足"; // th.go_error(msg); // return false; // } if (fail_result.length > 0) { fail_result = JSON.stringify(fail_result); th.go_error(fail_result); return false; } //-- 开始调用分析的接口 -- var face_token = check_data.face_token; var data = { "image": face_token, "face_field": "color,smooth,acnespotmole,wrinkle,eyesattr,blackheadpore,skinface,skinquality", "image_type": "FACE_TOKEN" } th.analyse_by_bd(data); } else { var msg = th.data.err_map[res.data.code + ""]; if(msg){ th.go_error1(msg); }else{ wx.showToast({ title:res.data.msg, icon: 'none', duration: 3000 }) setTimeout(function () { ut.wx_back() },2000) } } }) }, //检查图片有没有OK 美图 img_check_mt() { let img_info = getApp().globalData.skin_img_info; var plugin = requirePlugin('mtSkinSdk'); console.log('plugin'); let th = this; plugin.facePoseCorrect({ path: img_info['path'], size: img_info['size'], success(res) { console.log('=========姿态校正 成功==========') console.log('姿态校正结果', res) let fail_result = new Array(); let analyse_info = res.data; //检查闭眼情况 if (analyse_info.analyse_info) { //检查睁眼闭眼 let { left, right } = analyse_info.analyse_info; if (left !== 2 && right !== 2) { fail_result.push({ type: 1, reason: "未闭眼拍摄" }) } } //检查佩戴情况 if (analyse_info.faceGlasses) { let { none, normal, sunglasses } = analyse_info.faceGlasses; if (normal > 0.8 || sunglasses > 0.8 || none < 0.1) { fail_result.push({ type: 2, reason: "未摘下眼镜拍摄" }) } } //检查框里人脸情况 if (analyse_info.faceOutDetect.outBound == 1) { fail_result.push({ type: 3, reason: "未识别到单个人脸" }) } //检查环境情况 if (analyse_info.faceQuality) { let { bright, blur } = analyse_info.faceQuality; if (bright > 80 || bright < 20 || blur < 20) { fail_result.push({ type: 4, reason: "质量检测未通过" }) } } //检查距离 if (analyse_info.faceRatio < 0.2) { fail_result.push({ type: 5, reason: "脸部与摄像头距离过远" }) } if (analyse_info.faceRatio > 0.8) { fail_result.push({ type: 6, reason: "脸部与摄像头距离过近" }) } //检查遮挡物 if (analyse_info.faceVisibility) { let fail = Object.keys(analyse_info.faceVisibility).filter(key => { return analyse_info.faceVisibility[key] <= 80; }) console.log('fail', fail); if (fail.length > 0) { fail_result.push({ type: 7, reason: "脸部有遮挡物" }) } } if (analyse_info.facePoseEuler) { let { pitch, roll, yaw } = analyse_info.facePoseEuler; if (pitch > 20 || roll > 20 || yaw > 20) { fail_result.push({ type: 8, reason: "未保持正脸拍摄" }) } } if (fail_result.length > 0) { fail_result = JSON.stringify(fail_result); th.go_error(fail_result); return false; } th.analyse_by_mt(img_info,analyse_info); }, fail(err) { console.log(err); th.go_error1('识别有误,请重试'); return false; } }) }, //美图测肤接口 analyse_by_mt(img_info,analyse_info) { let th = this; var plugin = requirePlugin('mtSkinSdk') plugin.detectImage({ path: img_info['path'], size: img_info['size'], success(res) { console.log('=========用户传图片链接获取检测结果 成功==========') console.log('检测结果', res); let analyse_data = res.data.face_attributes; analyse_data['face_rectangle'] = res.data.face_rectangle; let req_data = { store_id: setting.stoid, user_id: getApp().globalData.user_id, img: getApp().globalData.face_img, sourceimg: getApp().globalData.face_SourceImg, addtime: ut.gettimestamp(), resultjson: JSON.stringify(analyse_data), detectjson: JSON.stringify(analyse_info), skin_type: 1, img_remark:th.data.img_remark } //要保存一下分析的结果 th.json_post("/api/weshop/face/storeSkinface/save", req_data, function (res) { if (res.data.code == 0) { let url = "/packageD/pages/AI-test-skin/success_result/success_result?id=" + res.data.data.id; //跳到分析页 wx.redirectTo({ url: url }) } else { getApp().showWarning("保存失败"); } }) }, fail(err) { console.error('=========用户传图片链接获取检测结果 失败==========') console.log('error', err) getApp().showWarning(err); } }) }, //百度测肤接口 analyse_by_bd: function (data) { var th = this; var user_id=this.data.ce_user_id || getApp().globalData.user_id; //开始调用接口,进行分析 this.json_post("/api/weshop/baidubce/face/skinAnalyze", data, function (res) { if (res.data.code == 0) { getApp().globalData.face_result = res.data.data; var req_data = { store_id: setting.stoid, user_id: user_id, img: getApp().globalData.face_img, sourceimg: getApp().globalData.face_SourceImg, addtime: ut.gettimestamp(), resultjson: JSON.stringify(res.data.data), detectjson: JSON.stringify(th.data.check_data), skin_type: 0, img_remark:th.data.img_remark } var txt=[]; var face_data = res.data.data.face_list[0]; //痤疮数 var acne_num = face_data.acnespotmole.acne_num; //色斑数 var speckle_num = face_data.acnespotmole.speckle_num; //皱纹数 var wrinkle_num = face_data.wrinkle.wrinkle_num; //黑头数 var blackhead_num = face_data.blackheadpore.blackhead_num; //毛孔数 var pore_num = face_data.blackheadpore.pore_num; //黑眼圈的严重程度 var dark_type = face_data.eyesattr.dark_circle_left_type.length > 0 ? face_data.eyesattr.dark_circle_left_type[0] : -1; var dark_type1 = face_data.eyesattr.dark_circle_right_type.length > 0 ? face_data.eyesattr.dark_circle_right_type[0] : -1; var skin_dryoil_check = face_data.skinquality.skin_dryoil_check; var skin_dryoil_check_type = 0;//干性 var skin_dryoil_check_arr = [] for (let i in skin_dryoil_check) { let item = skin_dryoil_check[i]; if (item != '1' && skin_dryoil_check_arr.indexOf(item) == -1) { skin_dryoil_check_arr.push(item); } } //皮肤干油性的判断 if (skin_dryoil_check_arr.length == 0) skin_dryoil_check_type = 1; else if (skin_dryoil_check_arr.length == 1) skin_dryoil_check_type = parseInt(skin_dryoil_check_arr[0]); else skin_dryoil_check_type = 3; switch (skin_dryoil_check_type) { case 0: txt.push('干性'); break; case 1: txt.push('中性'); break; case 2: txt.push('油性'); break; case 3: txt.push('混合性'); break; } if (acne_num) txt.push('痤疮'); if (speckle_num) txt.push('色斑'); if (wrinkle_num) txt.push('皱纹'); if (blackhead_num) txt.push('黑头'); if (pore_num) txt.push('毛孔'); if (dark_type > -1 || dark_type1 > -1) txt.push('黑眼圈'); //-- 内容传值 -- req_data.resulttext= txt.join('/'); //要保存一下分析的结果 th.json_post("/api/weshop/face/storeSkinface/save", req_data, function (res) { if (res.data.code == 0) { console.log('---ce_id----'); console.log(res.data.data.id); let url = "/packageD/pages/AI-test-skin/success_result/success_result?id=" + res.data.data.id; //跳到分析页 if(th.data.ce_user_id) url+="&ce_user_id="+th.data.ce_user_id; wx.redirectTo({ url: url }) } else { getApp().showWarning("保存失败"); } }) } else { var msg = th.data.err_map[res.data.code + ""]; let url = "/packageD/pages/AI-test-skin/fail_result/fail_result?msg=" + msg; //跳到分析页 if(this.data.ce_user_id) url+="&ce_user_id="+this.data.ce_user_id; wx.redirectTo({ url: url }) } }) }, //跳转到错误页面 美图 go_error: function (fail_result) { let url = `/packageD/pages/AI-test-skin/fail_result/fail_result?fail_result=${fail_result}`; //跳到分析页 if(this.data.ce_user_id) url+="&ce_user_id="+this.data.ce_user_id; wx.redirectTo({ url: url }); }, //跳转到错误页面 go_error1: function (msg) { let url = "/packageD/pages/AI-test-skin/fail_result/fail_result?msg=" + msg; //跳到分析页 if(this.data.ce_user_id) url+="&ce_user_id="+this.data.ce_user_id; wx.redirectTo({ url: url }); }, /** * @param {Object} url //url地址 * @param {Object} data //data入参 * @param {Object} succ //成功的回调 * @param {Object} fail //失败的回调 */ json_post: function (url, data, succ, fail, mathod) { var Mathod = "POST"; if (mathod) Mathod = mathod; if (url.indexOf("http") == -1) url = getApp().globalData.setting.url + url; var str = JSON.stringify(data); wx.request({ url: url, data: str, method: Mathod, header: { 'content-type': 'application/json' },// 设置请求的 header success: function (res) { succ(res); }, fail: function (res) { fail(res); } }) }, })