本文詳細介紹自己如何在JavaWeb項目中通過調用API實現證件識別。
一,Face++使用簡介
二,兩種方式(圖片URL與本地上傳)實現證件識別
一,Face++使用簡介
Face++曠視人工智能開放平台,核心技術有人臉識別,人體識別,文字識別以及圖像識別。具體詳情可查看官方網站
首先需要在官方網站上注冊,然后在API應用管理創建API Key,便可得到API Key和API Secret。兩者是之后調用API的必要請求參數。
具體操作方式也可查看API文檔


API調用原理:使用者向服務器發起HTTP請求,並加上合適的參數,服務器將會對請求進行處理,得到結果將會返回給使用者。
API調用鑒權:帳號下每創建一個應用程序會生成一組對應的API Key和API Secret,用於識別用戶是否有權限調用API,所有的API調用必須提供對應的一組API Key和API Secret。
API調用參數:調用每個API需要根據需求傳輸不同的參數,身份證識別需要的必須參數有API的URL,API Key,API Secret,image_url或image_file或image_base64以及可選參數legality。
API調用提示:為了避免因網絡問題而造成的阻塞,建議將API調用放進異步線程里執行。
二,兩種方式(圖片URL與本地上傳)實現證件識別
不管是通過URL方式還是通過本地上傳,調用API之前首先需要將圖片轉為字節型數組byte[]。官方給的案例只介紹了通過本地上傳,我在其基礎上添加了一個函數 'getBytesFromInputStream'實現將輸入流轉為字節型數組,代碼如下。
①通過URL方式
當輸入圖片URL,點擊檢測按鈕,觸發js的click事件,首先根據URL完成修改img標簽的背景圖片,並將其傳給 'readPhoto1' 函數。該函數將URL通過AJAX異步請求傳至Controller層,Controller層通過URL首先建立網絡連接得到輸入流,輸入流通過上述代碼轉為字節型數組,並put至HashMap中作為參數之一。另外兩個參數已經是規定好的,這時再調用post函數,得到返回值轉為JSON格式返回至 'readPhoto1' 函數,該函數再取值通過id賦值給相應的標簽。參考代碼如下。
1 $("#bg-model4_button2").click(function(){ 2 var photoURL = document.getElementById("bg-model4_input").value; 3 document.getElementById('bg-model4_img').src = photoURL; 4 readPhoto1(photoURL); 5 });
1 /*通過URL讀取圖片*/ 2 function readPhoto1(photoURL){ 3 $.post("readPhotoInfo1.do",{photoURL},function(data){ 4 document.getElementById("name").innerHTML = data.cards[0].name; 5 document.getElementById("sex").innerHTML = data.cards[0].gender; 6 document.getElementById("race").innerHTML = data.cards[0].race; 7 document.getElementById("birthday").innerHTML = data.cards[0].birthday; 8 document.getElementById("address").innerHTML = data.cards[0].address; 9 document.getElementById("idcard_num").innerHTML = data.cards[0].id_card_number; 10 if(data.cards[0].side == "front"){ 11 document.getElementById("admin_side").innerHTML = "人像面"; 12 }else{ 13 document.getElementById("admin_side").innerHTML = "國徽面"; 14 } 15 document.getElementById("admin_time_used").innerHTML = data.time_used + "ms"; 16 },"json"); 17 }
1 private String photoInfo; //身份證信息 2 3 //根據圖片URL讀取圖片內容信息 4 @RequestMapping(value="/readPhotoInfo1.do",method=RequestMethod.POST) 5 public String readPhotoInfo1(HttpServletRequest request,HttpServletResponse response) throws IOException{ 6 response.setContentType("text/html; charset=utf-8"); 7 //js里通過ajax傳遞過來的圖片URL 8 String photoURL = request.getParameter("photoURL"); 9 URL photo_url = new URL(photoURL); 10 HttpURLConnection conn = (HttpURLConnection)photo_url.openConnection(); 11 conn.setConnectTimeout(3*1000); 12 //防止屏蔽程序抓取而返回403錯誤 13 conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); 14 //得到輸入流 15 InputStream inputStream = conn.getInputStream(); 16 byte[] buff = CertificateRecognition.getBytesFromInputStream(inputStream); 17 18 //API的地址 19 String url = "https://api-cn.faceplusplus.com/cardpp/v1/ocridcard"; 20 HashMap<String, String> map = new HashMap<>(); 21 HashMap<String, byte[]> byteMap = new HashMap<>(); 22 map.put("api_key", "你的api_key"); 23 map.put("api_secret", "你的api_secret"); 24 map.put("return_landmark", "1"); 25 map.put("return_attributes", "gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus"); 26 byteMap.put("image_file", buff); 27 PrintWriter out = response.getWriter(); 28 29 callPost(url, map, byteMap, out); 30 out.close(); 31 return null; 32 }
1 //調用CertificateRecognition中的post方法 2 private void callPost(String url, HashMap<String, String> map, HashMap<String, byte[]> byteMap, PrintWriter pw) { 3 try{ 4 byte[] bacd = CertificateRecognition.post(url, map, byteMap); 5 this.photoInfo = new String(bacd); 6 pw.println(photoInfo); 7 System.out.println(photoInfo); 8 }catch (Exception e) { 9 e.printStackTrace(); 10 } 11 }
②通過本地上傳方式
當選擇本地圖片,由於綁定js的change事件,首先完成修改img標簽的背景圖片,這里的js得到的是本地圖片的base64編碼,並將其傳給'readPhoto2'函數。該函數將的base64編碼通過AJAX異步請求傳至Controller層,Controller層首先需要對圖片的base64編碼進行截取(前綴data:image/ jpeg; base64,為無效字符串),並調整異常數據,再將其寫入本地一個規定的絕對路徑。然后同理通過上述代碼轉為字節型數組,並將其put至HashMap中作為參數之一。這時再調用post函數,得到返回值並轉為JSON格式返回至' readPhoto2'函數,該函數再取值通過id賦值給相應的標簽。參考代碼如下。
1 $("#admin_upload_photo").change(function(){ 2 if(window.FileReader){ //chrome,firefox7+,opera,IE10,IE9,IE9也可以用濾鏡來實現 3 oFReader = new FileReader(); 4 oFReader.readAsDataURL(this.files[0]); 5 oFReader.onload = function (oFREvent) { 6 document.getElementById('bg-model4_img').src = oFREvent.target.result; 7 var base64 = oFREvent.target.result; 8 alert(base64); 9 readPhoto2(base64); 10 }; 11 } 12 });
1 /*通過絕對路徑讀取圖片*/ 2 function readPhoto2(base64){ 3 $.post("readPhotoInfo2.do",{base64},function(data){ 4 document.getElementById("name").innerHTML = data.cards[0].name; 5 document.getElementById("sex").innerHTML = data.cards[0].gender; 6 document.getElementById("race").innerHTML = data.cards[0].race; 7 document.getElementById("birthday").innerHTML = data.cards[0].birthday; 8 document.getElementById("address").innerHTML = data.cards[0].address; 9 document.getElementById("idcard_num").innerHTML = data.cards[0].id_card_number; 10 if(data.cards[0].side == "front"){ 11 document.getElementById("admin_side").innerHTML = "人像面"; 12 }else{ 13 document.getElementById("admin_side").innerHTML = "國徽面"; 14 } 15 document.getElementById("admin_time_used").innerHTML = data.time_used + "ms"; 16 },"json"); 17 }
1 //根據圖片絕對路徑讀取圖片內容信息 2 @RequestMapping(value="/readPhotoInfo2.do",method=RequestMethod.POST) 3 public String readPhotoInfo2(HttpServletRequest request,HttpServletResponse response) throws IOException{ 4 response.setContentType("text/html; charset=utf-8"); 5 //js里通過ajax傳遞過來的圖片base64編碼 6 String base64 = request.getParameter("base64"); 7 int size = base64.indexOf(","); //截取第一個,號后面的字符串 8 System.out.println(size); //21 9 10 String substr = base64.substring(22); 11 12 BASE64Decoder decoder = new BASE64Decoder(); 13 try 14 { 15 byte[] b = decoder.decodeBuffer(substr); 16 for(int i=0;i<b.length;++i) //調整異常數據 17 { 18 if(b[i]<0){ 19 b[i] += 256; 20 } 21 } 22 String imgFilePath = "e:/base.png"; //新生成的圖片存放路徑 23 OutputStream out = new FileOutputStream(imgFilePath); 24 out.write(b); 25 out.flush(); 26 out.close(); 27 28 File file = new File(imgFilePath); 29 byte[] buff = CertificateRecognition.getBytesFromFile(file); 30 31 //API的地址 32 String url = "https://api-cn.faceplusplus.com/cardpp/v1/ocridcard"; 33 HashMap<String, String> map = new HashMap<>(); 34 HashMap<String, byte[]> byteMap = new HashMap<>(); 35 map.put("api_key", "你的api_key"); 36 map.put("api_secret", "你的api_secret"); 37 map.put("return_landmark", "1"); 38 map.put("return_attributes", "gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus"); 39 byteMap.put("image_file", buff); 40 PrintWriter pw = response.getWriter(); 41 42 callPost(url, map, byteMap, pw); 43 pw.close(); 44 45 } 46 catch (Exception e){ 47 e.printStackTrace(); 48 } 49 return null; 50 }
項目效果圖如下(證件圖片是在網上任意找的一張圖片,不針對於任何人)。
如有疏漏錯誤之處,還請不吝賜教!