├── .gitignore ├── .npmignore ├── index.js ├── package.json ├── README.md └── lib └── youtu.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | tests 3 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var Youtu = require('./lib/youtu'); 2 | 3 | module.exports = Youtu; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "youtu", 3 | "version": "0.2.0", 4 | "description": "Third-part SDK of Tencent youtu.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/TooBug/youtu.git" 12 | }, 13 | "keywords": [ 14 | "tencent", 15 | "youtu", 16 | "face", 17 | "detect" 18 | ], 19 | "author": "TooBug", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/TooBug/youtu/issues" 23 | }, 24 | "homepage": "https://github.com/TooBug/youtu#readme", 25 | "dependencies": { 26 | "restler": "^3.3.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 腾讯优图开放平台第三方SDK 2 | 3 | ## 特性 4 | 5 | - 包含所有官方API接口 6 | - Promise接口 7 | - 支持使用相对路径或buffer指定图片 8 | 9 | ## 安装 10 | 11 | ```sh 12 | npm install youtu 13 | ``` 14 | 15 | ## Demo 16 | 17 | ``` 18 | var Youtu = require('youtu'); 19 | var youtu = new Youtu({ 20 | appId:'1000xxxx', 21 | secretId:'xxxx', 22 | secretKey:'xxxx' 23 | }); 24 | 25 | youtu.detectFace('./demo.jpg').then(function(data){ 26 | // detectFace result 27 | }); 28 | ``` 29 | 30 | ## API及参数 31 | 32 | - 人脸识别API 33 | - 人脸检测 detectFace(image) 34 | - 五官定位 faceShape(image) 35 | - 人脸对比 faceCompare(imageA, imageB) 36 | - 人脸验证 faceVerify(image, person_id) 37 | - 人脸识别 FaceIdentify(image, group_id) 38 | - 个体(Person)管理 39 | - 个体创建 newPerson(image, person_id, group_ids) 40 | - 删除个体 delPerson(person_id) 41 | - 增加人脸 addFace(images, person_id) 42 | - 删除人脸 delFace(person_id, face_ids) 43 | - 设置信息 setInfo(person_name, person_id) 44 | - 获取信息 getInfo(person_id) 45 | - 信息查询 46 | - 获取组列表 getGroupIds() 47 | - 获取人列表 getPersonIds(group_id) 48 | - 获取人脸列表 getFaceIds(person_id) 49 | - 获取人脸信息 getFaceInfo(face_id) 50 | - 图片识别 51 | - 模糊图片检测 fuzzyDetect(image) 52 | - 美食图片识别 foodDetect(image) 53 | - 图像标签识别 imageTag(image) 54 | - 色情图像检测 imagePorn(image) 55 | - OCR识别 56 | - 身份证OCR识别 idCardOcr(image,card_type) 57 | - 名片OCR识别 nameCardOcr(image) 58 | 59 | ## 错误处理 60 | 61 | HTTP层面错误会走到Promise错误处理流程,应用层面错误码暂未解析,需应用自行处理。 62 | 63 | ## Todo 64 | 65 | - [ ] 完善文档 66 | - [ ] 错误码解析 67 | - [ ] 支持传入远程图片地址 68 | - [ ] 可选参数处理 69 | 70 | ## 版本历史 71 | 72 | ### 0.2.0 2016-06-14 73 | 74 | - 跟进官方API,添加五官检测、图片识别、OCR识别API 75 | 76 | ### 0.1.0 2015-07-26 77 | 78 | - 整理API,初始版本发布 79 | 80 | ## LICENSE 81 | 82 | MIT 83 | -------------------------------------------------------------------------------- /lib/youtu.js: -------------------------------------------------------------------------------- 1 | var Youtu = function(options){ 2 | 3 | if(!options.appId || !options.secretId || !options.secretKey){ 4 | throw new Error('appId,secretId,secretKey must be specified.'); 5 | } 6 | 7 | this.appId = options.appId; 8 | this.secretId = options.secretId; 9 | this.secretKey = options.secretKey; 10 | this.userId = 0; // 预留 11 | 12 | }; 13 | 14 | var version = require('../package.json').version; 15 | 16 | Youtu.prototype._server = 'http://api.youtu.qq.com/'; 17 | Youtu.prototype._ua = 'Youtu SDK/' + version + ' (npm module youtu) by TooBug'; 18 | Youtu.prototype._expire = 1800; 19 | 20 | Youtu.prototype._getSign = function(){ 21 | 22 | var crypto = require('crypto'); 23 | var now = parseInt(Date.now() / 1000); 24 | var rdm = parseInt(Math.random() * Math.pow(2, 32)); 25 | 26 | // the order of every key is not matter verify 27 | var plainText = 'a=' + this.appId + 28 | '&k=' + this.secretId + 29 | '&e=' + (now + this._expire) + 30 | '&t=' + now + 31 | '&r=' + rdm + 32 | '&u=' + this.userId; 33 | 34 | var data = new Buffer(plainText,'utf8'); 35 | 36 | var res = crypto.createHmac('sha1',this.secretKey).update(data).digest(); 37 | 38 | var bin = Buffer.concat([res,data]); 39 | 40 | var sign = bin.toString('base64'); 41 | 42 | return sign; 43 | }; 44 | 45 | Youtu.prototype._doRequest = function(type, apiItem, args){ 46 | 47 | var _this = this; 48 | 49 | var baseUrl = _this._server; 50 | var urlMap = { 51 | faceAPI:'youtu/api/', 52 | imageAPI:'youtu/imageapi/', 53 | ocrAPI:'youtu/ocrapi/' 54 | }; 55 | baseUrl += urlMap[type]; 56 | 57 | var getImageData = function(pathOrBuffer){ 58 | var buffer = pathOrBuffer; 59 | 60 | if(typeof pathOrBuffer === 'string'){ 61 | var fs = require('fs'); 62 | buffer = fs.readFileSync(pathOrBuffer); 63 | } 64 | 65 | return buffer.toString('base64'); 66 | 67 | }; 68 | 69 | return new Promise(function(resolve,reject){ 70 | var restler = require('restler'); 71 | var url = baseUrl + apiItem.name.toLowerCase(); 72 | var postData = { 73 | app_id:_this.appId 74 | }; 75 | apiItem.params.forEach(function(param, index){ 76 | if(typeof param === 'string'){ 77 | var key = param; 78 | param = { 79 | key: key, 80 | type: 'default' 81 | }; 82 | } 83 | if(param.type === 'image'){ 84 | var imagePath = args[index]; 85 | var imageData = getImageData(imagePath); 86 | postData[param.key] = imageData; 87 | }else if(param.type === 'imageArray'){ 88 | var arr = args[index].map(function(imagePath){ 89 | return getImageData(imagePath); 90 | }); 91 | postData[param.key] = arr; 92 | }else{ 93 | postData[param.key] = args[index]; 94 | } 95 | }); 96 | restler.post(url,{ 97 | headers:{ 98 | Authorization:_this._getSign(), 99 | 'User-Agent':_this._ua, 100 | 'Content-Type':'text/json' 101 | }, 102 | data:JSON.stringify(postData) 103 | }).on('complete', function(data, response){ 104 | if(data instanceof Error){ 105 | reject(data); 106 | }else{ 107 | resolve(data); 108 | } 109 | }); 110 | }); 111 | }; 112 | 113 | var apiList = [{ 114 | name:'detectFace', 115 | params:[{ 116 | key:'image', 117 | type:'image' 118 | }] 119 | },{ 120 | name:'faceShape', 121 | params:[{ 122 | key:'image', 123 | type:'image' 124 | }] 125 | },{ 126 | name:'faceCompare', 127 | params:[{ 128 | key:'imageA', 129 | type:'image' 130 | },{ 131 | key:'imageB', 132 | type:'image' 133 | }] 134 | },{ 135 | name:'faceVerify', 136 | params:[{ 137 | key:'image', 138 | type:'image' 139 | },'person_id'] 140 | },{ 141 | name:'FaceIdentify', 142 | params:[{ 143 | key:'image', 144 | type:'image' 145 | },'group_id'] 146 | },{ 147 | name:'newPerson', 148 | params:[{ 149 | key:'image', 150 | type:'image' 151 | },'person_id','group_ids'] 152 | },{ 153 | name:'delPerson', 154 | params:['person_id'] 155 | },{ 156 | name:'addFace', 157 | params:[{ 158 | key:'images', 159 | type:'imageArray' 160 | },'person_id'] 161 | },{ 162 | name:'delFace', 163 | params:['person_id','face_ids'] 164 | },{ 165 | name:'setInfo', 166 | params:['person_name','person_id'] 167 | },{ 168 | name:'getInfo', 169 | params:['person_id'] 170 | },{ 171 | name:'getGroupIds', 172 | params:[] 173 | },{ 174 | name:'getPersonIds', 175 | params:['group_id'] 176 | },{ 177 | name:'getFaceIds', 178 | params:['person_id'] 179 | },{ 180 | name:'getFaceInfo', 181 | params:['face_id'] 182 | },{ 183 | name:'fuzzyDetect', 184 | type:'imageAPI', 185 | params:[{ 186 | key:'image', 187 | type:'image' 188 | }] 189 | },{ 190 | name:'foodDetect', 191 | type:'imageAPI', 192 | params:[{ 193 | key:'image', 194 | type:'image' 195 | }] 196 | },{ 197 | name:'imageTag', 198 | type:'imageAPI', 199 | params:[{ 200 | key:'image', 201 | type:'image' 202 | }] 203 | },{ 204 | name:'imagePorn', 205 | type:'imageAPI', 206 | params:[{ 207 | key:'image', 208 | type:'image' 209 | }] 210 | },{ 211 | name:'idCardOcr', 212 | type:'ocrAPI', 213 | params:[{ 214 | key:'image', 215 | type:'image' 216 | },'card_type'] 217 | },{ 218 | name:'nameCardOcr', 219 | type:'ocrAPI', 220 | params:[{ 221 | key:'image', 222 | type:'image' 223 | }] 224 | }]; 225 | 226 | apiList.forEach(function(apiItem){ 227 | 228 | Youtu.prototype[apiItem.name] = function(apiItem){ 229 | var type = apiItem.type || 'faceAPI'; 230 | return function(){ 231 | return this._doRequest(type,apiItem,arguments); 232 | }; 233 | }(apiItem); 234 | 235 | }); 236 | 237 | module.exports = Youtu; 238 | --------------------------------------------------------------------------------