摘要:微信接入采用的第三方接入微信,具體功能接入還是要看微信公眾號開發文檔,架構則是上面所說的。吐槽一下,騰訊包括微信,他們的文檔確實沒有阿里做得好。人臉融合結尾這一塊騰訊人工智能接入已解釋完畢。
前言要想騎自行車,首先不是要學會如何造自行車,而是學會如何騎行
結合騰訊AI開放平臺群里的demo解析,QQ群號:581197347。
這個項目是我只花費兩天時間做完的,采用的技術是SpringBoot+SpringCloud+MongoDB。
為啥只要兩天呢,現在是微服務快速開發時代,兩天開發一個小型項目真的自己都覺得花費時間太長。
前端框架采用Layui,如果是微信訪問則會跳到微信端的頁面。微信接入采用GitHub的第三方接入微信,
具體功能接入還是要看微信公眾號開發文檔,架構則是上面所說的SpringBoot+SpringCloud。數據庫方面采用MongoDB,因為我只需要存圖片文件不需要采集用戶信息。
這是現在上線的項目,您也可以微信掃碼訪問,都是同一個鏈接。點擊訪問項目
在iphone這邊試了下人臉融合好像不行。因為微信jdk要另外設置。沒ios機...
這里主要詳解如何接入騰訊第三方AI,其他會簡單帶過:騰訊AI官網
為什么選擇騰訊的?而不是選擇阿里,網易,百度呢?主要他們都要認證,要錢。(貧窮限制我的選擇)。
開玩笑,言歸正傳,這是因為開發簡潔通用,只要會一種,其他就換湯不換藥。唯一的缺點就是他不保證并發。如果你只需要一種識別,并且是穩定高并發的,我建議阿里哈。
騰訊AI技術文檔這個文檔的接口鑒權也就是獲取sign我是不建議你們去看的,因為都不知道他在說什么獎杯,我在這里跟大家講如何獲得sign,后面的接入就可以按照文檔來操作了。
ps:吐槽一下,騰訊包括微信,他們的文檔確實沒有阿里做得好。
首先在這里,我說明一下,我會將他作為一個main主函數來運行。我也只講一種方式,其他你真的看懂了,自然而然就會運用了。
首先要知道如何獲得簽名也就是我們所謂的Sign和要求計算的參數
你可以根據官方文檔看到我們需要通過這幾個參數來計算出簽名,然而他們并沒有說明這個text:騰訊AI開放平臺是什么,這個text就是你要接入哪種識別另外要加入的參數,就比如這里我講解人臉融合,人臉融合根據文檔要多傳一個model參數,也就是說這個model也要加入Sign的計算當中。
那么我們知道了sign需要的參數,我們要怎么計算呢。
直接看文檔對于初學者來說,看了等于白看,文檔說要
1. 獲得參數對列表N(字典升級排序)。 2. 按URL鍵值拼接字符串T,參數對列表N的參數對進行URL鍵值拼接,值使用URL編碼,URL編碼算法用大寫字母。 3. 拼接應用密鑰,得到字符串S。 4. 計算MD5摘要,得到簽名字符串。
獲得Sign說實話,第一次我看這個文檔我的main函數運行的不少于100遍的出錯。那要怎么接入呢? 如果你看的懂文檔,請直接略過這端Sign簽名
時間戳time_stamp和隨機字符串nonce_str我們直接可以自己生成的。
String time_stamp = System.currentTimeMillis()/1000+""; String nonce_str = TencentAISign.getRandomString(10);
還有image屬性也就是你上傳的照片,騰訊限定了圖片大小(根據文檔)和要求原始圖片的base64編碼數據
如何限定圖片大小就是你的事了,在這里將如何將圖片進行base64編碼,編碼這里我講兩種,一種是本地路徑編碼,另一種根據Url網絡資源編碼。
這里我寫一個工具類,可以根據本地或者Url分別進行base64編碼
public class UrlMethodUtil { public static byte[] local2byte(String url)throws Exception{ //由本地路徑得到byte byte [] imageData = FileUtil.readFileByBytes(url); return imageData; } public static byte[] url2byte(String url)throws Exception { //由url得到byte byte [] imageData = IoUtil.getImageFromNetByUrl(url); return imageData; } }
FileUtil 就是從本地路徑獲得byte[]數據
public class FileUtil { /** * 根據文件路徑讀取byte[] 數組 */ public static byte[] readFileByBytes(String filePath) throws IOException { File file = new File(filePath); if (!file.exists()) { throw new FileNotFoundException(filePath); } else { ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length()); BufferedInputStream in = null; try { in = new BufferedInputStream(new FileInputStream(file)); short bufSize = 1024; byte[] buffer = new byte[bufSize]; int len1; while (-1 != (len1 = in.read(buffer, 0, bufSize))) { bos.write(buffer, 0, len1); } byte[] var7 = bos.toByteArray(); return var7; } finally { try { if (in != null) { in.close(); } } catch (IOException var14) { var14.printStackTrace(); } bos.close(); } } } }
IoUtil就是從Url獲得byte[]數據
public class IoUtil { /** * 根據地址獲得數據的字節流 * @param strUrl 網絡連接地址 * @return */ public static byte[] getImageFromNetByUrl(String strUrl){ try { URL url = new URL(strUrl); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(10 * 1000); InputStream inStream = conn.getInputStream();//通過輸入流獲取圖片數據 byte[] btImg = readInputStream(inStream);//得到圖片的二進制數據 return btImg; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 從輸入流中獲取數據 * @param inStream 輸入流 * @return * @throws Exception */ public static byte[] readInputStream(InputStream inStream) throws Exception{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while( (len=inStream.read(buffer)) != -1 ){ outStream.write(buffer, 0, len); } inStream.close(); return outStream.toByteArray(); } }
然后就可以很輕松的調用了:
byte [] imageData = UrlMethodUtil.local2byte("E:/demo.png");//本地圖片
byte [] imageData = UrlMethodUtil.url2byte("網絡資源路徑Url");
得到byte數組了我們就可以根據Base64的工具類轉化,這里我貼出來,百度一堆
public class Base64Util { private static final char last2byte = (char) Integer.parseInt("00000011", 2); private static final char last4byte = (char) Integer.parseInt("00001111", 2); private static final char last6byte = (char) Integer.parseInt("00111111", 2); private static final char lead6byte = (char) Integer.parseInt("11111100", 2); private static final char lead4byte = (char) Integer.parseInt("11110000", 2); private static final char lead2byte = (char) Integer.parseInt("11000000", 2); private static final char[] encodeTable = new char[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"}; public Base64Util() { } public static String encode(byte[] from) { StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3); int num = 0; char currentByte = 0; int i; for (i = 0; i < from.length; ++i) { for (num %= 8; num < 8; num += 6) { switch (num) { case 0: currentByte = (char) (from[i] & lead6byte); currentByte = (char) (currentByte >>> 2); case 1: case 3: case 5: default: break; case 2: currentByte = (char) (from[i] & last6byte); break; case 4: currentByte = (char) (from[i] & last4byte); currentByte = (char) (currentByte << 2); if (i + 1 < from.length) { currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6); } break; case 6: currentByte = (char) (from[i] & last2byte); currentByte = (char) (currentByte << 4); if (i + 1 < from.length) { currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4); } } to.append(encodeTable[currentByte]); } } if (to.length() % 4 != 0) { for (i = 4 - to.length() % 4; i > 0; --i) { to.append("="); } } return to.toString(); } }
這樣image的Base64編碼搞定,終于拿到了image屬性了,接下來就可以準備開始簽名啦
我們現在擁有的屬性有:appid,appKey,time_stamp,nonce_str,image。再根據我們要實現的功能需要的參數終于可以實現簽名啦。感覺好麻煩有木有。確實是挺麻煩的,但這也是一種安全驗證的過程。
那我們怎么將這么多參數放在一起計算出Sign呢?答案可想而知,用Map。
Mapperson_Id_body = new HashMap<>(); person_Id_body.put("app_id", String.valueOf(TencentAPI.APP_ID_AI)); person_Id_body.put("time_stamp",time_stamp); person_Id_body.put("nonce_str", nonce_str); person_Id_body.put("image", img64); person_Id_body.put("model","1"); //這是人臉融合需要的參數,1表示模板1.
在這里我將用在騰訊公眾平臺群一位大神發出來的通用簽名工具類來簽名
public class TencentAISignSort { /** * SIGN簽名生成算法-JAVA版本 通用。默認參數都為UTF-8適用 * @param HashMapparams 請求參數集,所有參數必須已轉換為字符串類型 * @return 簽名 * @throws IOException */ public static String getSignature(Map params) throws IOException { // 先將參數以其參數名的字典序升序進行排序 Map sortedParams = new TreeMap<>(params); Set > entrys = sortedParams.entrySet(); // 遍歷排序后的字典,將所有參數按"key=value"格式拼接在一起 StringBuilder baseString = new StringBuilder(); for (Map.Entry param : entrys) { //sign參數 和 空值參數 不加入算法 if(param.getValue()!=null && !"".equals(param.getKey().trim()) && !"sign".equals(param.getKey().trim()) && !"".equals(param.getValue().trim())) { baseString.append(param.getKey().trim()).append("=").append(URLEncoder.encode(param.getValue().trim(),"UTF-8")).append("&"); } } System.err.println("未拼接APPKEY的參數:"+baseString.toString()); if(baseString.length() > 0 ) { baseString.deleteCharAt(baseString.length()-1).append("&app_key="+TencentAPI.APP_KEY_AI); } System.err.println("拼接APPKEY后的參數:"+baseString.toString()); // 使用MD5對待簽名串求簽 try { String sign = MD5.getMD5(baseString.toString()); return sign; } catch (Exception ex) { throw new IOException(ex); } } /** * SIGN簽名生成算法-JAVA版本 針對于基本文本分析接口要求text為GBK的方法 * @param HashMap params 請求參數集,所有參數必須已轉換為字符串類型 * @return 簽名 * @throws IOException */ public static String getSignatureforNLP(HashMap params) throws IOException { // 先將參數以其參數名的字典序升序進行排序 Map sortedParams = new TreeMap<>(params); Set > entrys = sortedParams.entrySet(); // 遍歷排序后的字典,將所有參數按"key=value"格式拼接在一起 StringBuilder baseString = new StringBuilder(); for (Map.Entry param : entrys) { //sign參數 和 空值參數 不加入算法 if(param.getValue()!=null && !"".equals(param.getKey().trim()) && !"sign".equals(param.getKey().trim()) && !"".equals(param.getValue().trim())) { if(param.getKey().equals("text")){ baseString.append(param.getKey().trim()).append("=").append(URLEncoder.encode(param.getValue().trim(),"GBK")).append("&"); }else{ baseString.append(param.getKey().trim()).append("=").append(URLEncoder.encode(param.getValue().trim(),"UTF-8")).append("&"); } } } if(baseString.length() > 0 ) { baseString.deleteCharAt(baseString.length()-1).append("&app_key="+TencentAPI.APP_KEY_AI); } // 使用MD5對待簽名串求簽 try { String sign = MD5.getMD5(baseString.toString()); return sign; } catch (Exception ex) { throw new IOException(ex); } } /** * 獲取拼接的參數 * @param params * @return * @throws IOException */ public static String getParams(HashMap params) throws IOException { // 先將參數以其參數名的字典序升序進行排序 Map sortedParams = new TreeMap<>(params); Set > entrys = sortedParams.entrySet(); // 遍歷排序后的字典,將所有參數按"key=value"格式拼接在一起 StringBuilder baseString = new StringBuilder(); for (Map.Entry param : entrys) { //sign參數 和 空值參數 不加入算法 baseString.append(param.getKey().trim()).append("=").append(URLEncoder.encode(param.getValue().trim(),"UTF-8")).append("&"); } return baseString.toString(); } }
這樣簡單一句話就實現了簽名啦:
向API發送請求String sign = TencentAISignSort.getSignature(person_Id_body);
person_Id_body.put("sign", sign); //將Sign也放入Map中 //這我就不用說了吧,這是頭信息需要的 Mapheaders = new HashMap<>(); //headers頭 headers.put("Content-Type", "application/x-www-form-urlencoded");
HttpResponse responseBD = HttpsUtil4Tencent.doPostTencentAI(TencentAPI.FACEMERGE, headers, person_Id_body); String json = EntityUtils.toString(responseBD.getEntity()); System.out.println(json); //這個就是我們的要的數據了
ps:一堆工具類對不對啊哈哈哈,這才叫快速開發。
//HttpsUtil4Tencent工具類: public class HttpsUtil4Tencent { private static HttpClient wrapClient(String host) { HttpClient httpClient = new DefaultHttpClient(); if (host.startsWith("https://")) { sslClient(httpClient); } return httpClient; } private static void sslClient(HttpClient httpClient) { try { SSLContext ctx = SSLContext.getInstance("TLS"); X509TrustManager tm = new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] xcs, String str) { } public void checkServerTrusted(X509Certificate[] xcs, String str) { } }; ctx.init(null, new TrustManager[] { tm }, null); SSLSocketFactory ssf = new SSLSocketFactory(ctx); ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); ClientConnectionManager ccm = httpClient.getConnectionManager(); SchemeRegistry registry = ccm.getSchemeRegistry(); registry.register(new Scheme("https", 443, ssf)); } catch (KeyManagementException ex) { throw new RuntimeException(ex); } catch (NoSuchAlgorithmException ex) { throw new RuntimeException(ex); } } /** * * @Title doPostBD * @param url 接口地址 * @param method 請求方式 * @param headers * @param bodys * @return response * @throws Exception * @author 小帥帥丶 * @date 2017-3-20 * */ public static HttpResponse doPostTencentAI(String url, Mapheaders, Map bodys) throws Exception { HttpClient httpClient = wrapClient(url); HttpPost request = new HttpPost(url); for (Map.Entry e : headers.entrySet()) { request.addHeader(e.getKey(), e.getValue()); } if (bodys != null) { List nameValuePairList = new ArrayList (); for (String key : bodys.keySet()) { nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); } UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList); formEntity.setContentType("application/x-www-form-urlencoded;charset=UTF-8"); request.setEntity(formEntity); } return httpClient.execute(request); } }
得到的json就是騰訊給我們的數據。那我們要怎么把json數據轉為對象呢。
我的另一篇文章就寫了:Java 跨域 Json字符轉類對象
在人臉識別這塊,他回應的是一串base64的數據,我們應該怎么轉為圖片呢
String xmlImg = persion_id.getImage(); response.setContentType("image/*"); // 設置返回的文件類型 OutputStream toClient = response.getOutputStream(); IoUtil.GenerateImage(xmlImg,toClient);
沒錯,還是工具類IoUtil。
public class TencentAPI { //自己的APPID public static final Integer APP_ID_AI = 0; //自己的APPKEY public static final String APP_KEY_AI = "******"; public static final String PERSON_ID = "https://api.ai.qq.com/fcgi-bin/ocr/ocr_idcardocr"; //身份證識別 public static final String PHOTO_SPEAK = "https://api.ai.qq.com/fcgi-bin/vision/vision_imgtotext"; //看圖說話 public static final String SCENE_RECOGNITION = "https://api.ai.qq.com/fcgi-bin/vision/vision_scener"; //場景識別:對圖行進行場景識別,快速找出圖片中包含的場景信息 public static final String OBJECT_RECOGNITION = "https://api.ai.qq.com/fcgi-bin/vision/vision_objectr"; //物體識別:對圖行進行物體識別,快速找出圖片中包含的物體信息 public static final String IMAGE_LABEL = "https://api.ai.qq.com/fcgi-bin/image/image_tag"; //圖像標簽識別:識別一個圖像的標簽信息,對圖像分類。 public static final String FACEMERGE="https://api.ai.qq.com/fcgi-bin/ptu/ptu_facemerge"; //人臉融合 }結尾
這一塊騰訊人工智能AI接入已解釋完畢。如有什么不懂得可以來問下我。我的郵箱是519286925@qq.com
為什么說這是大專狗終章呢,因為我已經大三了,這是我最后一篇在大專學校寫的文章。即將面臨的面試工作或者插本,前方的路如何,我將何去何從。請等我下篇文章:【插本狗初章】或者【工作狗初章】
世上無難事,只有你會不會,想不想學。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/70743.html
摘要:鑒權實現快速開發第三方騰訊人工智能接入詳解形式目前已經接入文字識別語音識別接口服務調用服務項目結構介紹基類通信相關類簽名公用類類類工具類使用引入即可示例代碼是調用騰訊中的客戶端,為調用騰訊中功能的開發人員提供了一系列的交互方法。 TAIP 是調用騰訊 AI 接口的 Java 客戶端,為調用騰訊 AI 功能的開發人員提供了一系列的交互方法。 Java調用騰訊AI接口服務。鑒權實現Java...
摘要:提到的云計算布局,就不得不提到年月中國領袖峰會上,三位掌門人針對云計算的同臺論道。且從官方有限的披露資料而言,很難對現階段的百度云計算獨立做評判。該計劃提出的發展目標是到年,我國云計算產業規模達到億元。提到BAT的云計算布局,就不得不提到2010年3月中國IT領袖峰會上,BAT三位掌門人針對云計算的同臺論道。坐在臺上的百度和騰訊創始人相繼發言,李彥宏不客氣的說,云計算好比新瓶裝舊酒,技術上沒...
摘要:而道器相融,在我看來,那煉丹就需要一個好的丹爐了,也就是一個優秀的機器學習平臺。因此,一個機器學習平臺要取得成功,最好具備如下五個特點精辟的核心抽象一個機器學習平臺,必須有其靈魂,也就是它的核心抽象。 *本文首發于 AI前線 ,歡迎轉載,并請注明出處。 摘要 2017年6月,騰訊正式開源面向機器學習的第三代高性能計算平臺 Angel,在GitHub上備受關注;2017年10月19日,騰...
閱讀 462·2023-04-25 23:00
閱讀 3492·2021-11-22 13:54
閱讀 1892·2021-10-27 14:14
閱讀 1485·2019-08-30 13:59
閱讀 3510·2019-08-23 16:15
閱讀 1956·2019-08-23 16:06
閱讀 3326·2019-08-23 15:26
閱讀 1256·2019-08-23 13:48