成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java快速開發(fā)第三方——騰訊人工智能AI接入詳解(大專狗終章)

evin2016 / 2449人閱讀

摘要:微信接入采用的第三方接入微信,具體功能接入還是要看微信公眾號開發(fā)文檔,架構(gòu)則是上面所說的。吐槽一下,騰訊包括微信,他們的文檔確實沒有阿里做得好。人臉融合結(jié)尾這一塊騰訊人工智能接入已解釋完畢。

要想騎自行車,首先不是要學(xué)會如何造自行車,而是學(xué)會如何騎行

前言

結(jié)合騰訊AI開放平臺群里的demo解析,QQ群號:581197347。
這個項目是我只花費兩天時間做完的,采用的技術(shù)是SpringBoot+SpringCloud+MongoDB。
為啥只要兩天呢,現(xiàn)在是微服務(wù)快速開發(fā)時代,兩天開發(fā)一個小型項目真的自己都覺得花費時間太長。
前端框架采用Layui,如果是微信訪問則會跳到微信端的頁面。微信接入采用GitHub的第三方接入微信,
具體功能接入還是要看微信公眾號開發(fā)文檔,架構(gòu)則是上面所說的SpringBoot+SpringCloud。數(shù)據(jù)庫方面采用MongoDB,因為我只需要存圖片文件不需要采集用戶信息。

項目

這是現(xiàn)在上線的項目,您也可以微信掃碼訪問,都是同一個鏈接。點擊訪問項目
在iphone這邊試了下人臉融合好像不行。因為微信jdk要另外設(shè)置。沒ios機...

為什么選擇騰訊

這里主要詳解如何接入騰訊第三方AI,其他會簡單帶過:騰訊AI官網(wǎng)
為什么選擇騰訊的?而不是選擇阿里,網(wǎng)易,百度呢?主要他們都要認證,要錢。(貧窮限制我的選擇)。

開玩笑,言歸正傳,這是因為開發(fā)簡潔通用,只要會一種,其他就換湯不換藥。唯一的缺點就是他不保證并發(fā)。如果你只需要一種識別,并且是穩(wěn)定高并發(fā)的,我建議阿里哈。
騰訊AI技術(shù)文檔這個文檔的接口鑒權(quán)也就是獲取sign我是不建議你們?nèi)タ吹模驗槎疾恢浪谡f什么獎杯,我在這里跟大家講如何獲得sign,后面的接入就可以按照文檔來操作了。
ps:吐槽一下,騰訊包括微信,他們的文檔確實沒有阿里做得好。

開始接入

首先在這里,我說明一下,我會將他作為一個main主函數(shù)來運行。我也只講一種方式,其他你真的看懂了,自然而然就會運用了。

首先要知道如何獲得簽名也就是我們所謂的Sign和要求計算的參數(shù)
你可以根據(jù)官方文檔看到我們需要通過這幾個參數(shù)來計算出簽名,然而他們并沒有說明這個text:騰訊AI開放平臺是什么,這個text就是你要接入哪種識別另外要加入的參數(shù),就比如這里我講解人臉融合,人臉融合根據(jù)文檔要多傳一個model參數(shù),也就是說這個model也要加入Sign的計算當中。

那么我們知道了sign需要的參數(shù),我們要怎么計算呢。

直接看文檔對于初學(xué)者來說,看了等于白看,文檔說要

1. 獲得參數(shù)對列表N(字典升級排序)。
2. 按URL鍵值拼接字符串T,參數(shù)對列表N的參數(shù)對進行URL鍵值拼接,值使用URL編碼,URL編碼算法用大寫字母。
3. 拼接應(yīng)用密鑰,得到字符串S。
4. 計算MD5摘要,得到簽名字符串。
說實話,第一次我看這個文檔我的main函數(shù)運行的不少于100遍的出錯。那要怎么接入呢?
如果你看的懂文檔,請直接略過這端Sign簽名
獲得Sign

時間戳time_stamp和隨機字符串nonce_str我們直接可以自己生成的。

String time_stamp = System.currentTimeMillis()/1000+"";
String nonce_str = TencentAISign.getRandomString(10);

還有image屬性也就是你上傳的照片,騰訊限定了圖片大小(根據(jù)文檔)和要求原始圖片的base64編碼數(shù)據(jù)
如何限定圖片大小就是你的事了,在這里將如何將圖片進行base64編碼,編碼這里我講兩種,一種是本地路徑編碼,另一種根據(jù)Url網(wǎng)絡(luò)資源編碼。
這里我寫一個工具類,可以根據(jù)本地或者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[]數(shù)據(jù)

public class FileUtil {
    /**
     * 根據(jù)文件路徑讀取byte[] 數(shù)組
     */
    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[]數(shù)據(jù)

public class IoUtil {
    /**
     * 根據(jù)地址獲得數(shù)據(jù)的字節(jié)流
     * @param strUrl 網(wǎng)絡(luò)連接地址
     * @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();//通過輸入流獲取圖片數(shù)據(jù)
            byte[] btImg = readInputStream(inStream);//得到圖片的二進制數(shù)據(jù)
            return btImg;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 從輸入流中獲取數(shù)據(jù)
     * @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();
    }
}

然后就可以很輕松的調(diào)用了:

byte [] imageData = UrlMethodUtil.local2byte("E:/demo.png");//本地圖片
byte [] imageData = UrlMethodUtil.url2byte("網(wǎng)絡(luò)資源路徑Url");

得到byte數(shù)組了我們就可以根據(jù)Base64的工具類轉(zhuǎn)化,這里我貼出來,百度一堆

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屬性了,接下來就可以準備開始簽名啦
我們現(xiàn)在擁有的屬性有:appid,appKey,time_stamp,nonce_str,image。再根據(jù)我們要實現(xiàn)的功能需要的參數(shù)終于可以實現(xiàn)簽名啦。感覺好麻煩有木有。確實是挺麻煩的,但這也是一種安全驗證的過程。
那我們怎么將這么多參數(shù)放在一起計算出Sign呢?答案可想而知,用Map。

        Map person_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");  //這是人臉融合需要的參數(shù),1表示模板1.

在這里我將用在騰訊公眾平臺群一位大神發(fā)出來的通用簽名工具類來簽名

public class TencentAISignSort {
    /**
     * SIGN簽名生成算法-JAVA版本 通用。默認參數(shù)都為UTF-8適用
     * @param HashMap params 請求參數(shù)集,所有參數(shù)必須已轉(zhuǎn)換為字符串類型
     * @return 簽名
     * @throws IOException
     */
    public static String getSignature(Map params) throws IOException {
            // 先將參數(shù)以其參數(shù)名的字典序升序進行排序
            Map sortedParams = new TreeMap<>(params);
            Set> entrys = sortedParams.entrySet();
            // 遍歷排序后的字典,將所有參數(shù)按"key=value"格式拼接在一起
            StringBuilder baseString = new StringBuilder();
            for (Map.Entry param : entrys) {
                //sign參數(shù) 和 空值參數(shù) 不加入算法
                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的參數(shù):"+baseString.toString());
            if(baseString.length() > 0 ) {
                baseString.deleteCharAt(baseString.length()-1).append("&app_key="+TencentAPI.APP_KEY_AI);
            }
            System.err.println("拼接APPKEY后的參數(shù):"+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 請求參數(shù)集,所有參數(shù)必須已轉(zhuǎn)換為字符串類型
     * @return 簽名
     * @throws IOException
     */
    public static String getSignatureforNLP(HashMap params) throws IOException {
            // 先將參數(shù)以其參數(shù)名的字典序升序進行排序
            Map sortedParams = new TreeMap<>(params);
            Set> entrys = sortedParams.entrySet();
            // 遍歷排序后的字典,將所有參數(shù)按"key=value"格式拼接在一起
            StringBuilder baseString = new StringBuilder();
            for (Map.Entry param : entrys) {
                
                //sign參數(shù) 和 空值參數(shù) 不加入算法
                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);
            }
        }
    /**
     * 獲取拼接的參數(shù)
     * @param params
     * @return
     * @throws IOException
     */
    public static String getParams(HashMap params) throws IOException {
        //  先將參數(shù)以其參數(shù)名的字典序升序進行排序
        Map sortedParams = new TreeMap<>(params);
        Set> entrys = sortedParams.entrySet();
        // 遍歷排序后的字典,將所有參數(shù)按"key=value"格式拼接在一起
        StringBuilder baseString = new StringBuilder();
        for (Map.Entry param : entrys) {
            //sign參數(shù) 和 空值參數(shù) 不加入算法
           baseString.append(param.getKey().trim()).append("=").append(URLEncoder.encode(param.getValue().trim(),"UTF-8")).append("&");
        }
       return baseString.toString();
    }
}

這樣簡單一句話就實現(xiàn)了簽名啦:

String sign = TencentAISignSort.getSignature(person_Id_body);

向API發(fā)送請求
    person_Id_body.put("sign", sign);  //將Sign也放入Map中
    //這我就不用說了吧,這是頭信息需要的
    Map headers = 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);  //這個就是我們的要的數(shù)據(jù)了

ps:一堆工具類對不對啊哈哈哈,這才叫快速開發(fā)。

//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, 
            Map headers, 
            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就是騰訊給我們的數(shù)據(jù)。那我們要怎么把json數(shù)據(jù)轉(zhuǎn)為對象呢。
我的另一篇文章就寫了:Java 跨域 Json字符轉(zhuǎn)類對象
在人臉識別這塊,他回應(yīng)的是一串base64的數(shù)據(jù),我們應(yīng)該怎么轉(zhuǎn)為圖片呢

     String xmlImg = persion_id.getImage();
                response.setContentType("image/*"); // 設(shè)置返回的文件類型
                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";  //人臉融合
}
結(jié)尾

這一塊騰訊人工智能AI接入已解釋完畢。如有什么不懂得可以來問下我。我的郵箱是[email protected]
為什么說這是大專狗終章呢,因為我已經(jīng)大三了,這是我最后一篇在大專學(xué)校寫的文章。即將面臨的面試工作或者插本,前方的路如何,我將何去何從。請等我下篇文章:【插本狗初章】或者【工作狗初章】

世上無難事,只有你會不會,想不想學(xué)。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70743.html

相關(guān)文章

  • 【Taip】Java快速開發(fā)騰訊人工智能AI接入

    摘要:鑒權(quán)實現(xiàn)快速開發(fā)第三方騰訊人工智能接入詳解形式目前已經(jīng)接入文字識別語音識別接口服務(wù)調(diào)用服務(wù)項目結(jié)構(gòu)介紹基類通信相關(guān)類簽名公用類類類工具類使用引入即可示例代碼是調(diào)用騰訊中的客戶端,為調(diào)用騰訊中功能的開發(fā)人員提供了一系列的交互方法。 TAIP 是調(diào)用騰訊 AI 接口的 Java 客戶端,為調(diào)用騰訊 AI 功能的開發(fā)人員提供了一系列的交互方法。 Java調(diào)用騰訊AI接口服務(wù)。鑒權(quán)實現(xiàn)Java...

    winterdawn 評論0 收藏0
  • BAT的云計算布局

    摘要:提到的云計算布局,就不得不提到年月中國領(lǐng)袖峰會上,三位掌門人針對云計算的同臺論道。且從官方有限的披露資料而言,很難對現(xiàn)階段的百度云計算獨立做評判。該計劃提出的發(fā)展目標是到年,我國云計算產(chǎn)業(yè)規(guī)模達到億元。提到BAT的云計算布局,就不得不提到2010年3月中國IT領(lǐng)袖峰會上,BAT三位掌門人針對云計算的同臺論道。坐在臺上的百度和騰訊創(chuàng)始人相繼發(fā)言,李彥宏不客氣的說,云計算好比新瓶裝舊酒,技術(shù)上沒...

    justCoding 評論0 收藏0
  • 道器相融,由Angel論一個優(yōu)秀機器學(xué)習(xí)平臺的自我修養(yǎng)

    摘要:而道器相融,在我看來,那煉丹就需要一個好的丹爐了,也就是一個優(yōu)秀的機器學(xué)習(xí)平臺。因此,一個機器學(xué)習(xí)平臺要取得成功,最好具備如下五個特點精辟的核心抽象一個機器學(xué)習(xí)平臺,必須有其靈魂,也就是它的核心抽象。 *本文首發(fā)于 AI前線 ,歡迎轉(zhuǎn)載,并請注明出處。 摘要 2017年6月,騰訊正式開源面向機器學(xué)習(xí)的第三代高性能計算平臺 Angel,在GitHub上備受關(guān)注;2017年10月19日,騰...

    leo108 評論0 收藏0

發(fā)表評論

0條評論

evin2016

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<