java版 利用人臉識別猜年齡 基於ArcFace2.0的 demo
首先感謝虹軟,是你們提供這麼好的SDK支撐了我們的想象力!
這是一個用javav編寫的視覺化應用,使用者通過自己的臉和計算機進行互動,計算機則通過萌萌女孩的語音和使用者對話。
核心程式就是利用ArcFace2.0識別性別、年齡,但是為了獲得正面臉,會根據ArcFace2.0的人臉3D角度、用語音提醒使用者,這是一個的互動環節。最後,程式會幽默的、萌萌的告訴使用者他的性別、年齡。
獲取SDK請戳這裡
完整的專案原始碼、可執行程式,放在百度網盤:連結:https://pan.baidu.com/s/1eHF6...
提取碼: ffag
其中主要的3個java檔案,程式碼如下:
===================================== HowOldAreU.java ===================================== package app; import java.awt.EventQueue; import javax.swing.JFrame; import java.io.File; import java.io.FileNotFoundException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.awt.BorderLayout; import com.alibaba.fastjson.JSONArray; import com.arcsoft.face.FaceEngine; import com.github.sarxos.webcam.Webcam; import com.github.sarxos.webcam.WebcamPanel; import tools.MyFunc; import javax.swing.JOptionPane; /*這是一個用javav編寫的視覺化應用,使用者通過自己的臉和計算機進行互動,計算機則通過萌萌女孩的語音和使用者對話。 核心程式就是利用ArcFace2.0識別性別、年齡,但是為了獲得正面臉,會根據ArcFace2.0的人臉3D角度、用語音提醒使用者,這是一個的互動環節。 最後,程式會幽默的、萌萌的告訴使用者他的性別、年齡。 作者:[email protected] */ public class HowOldAreU { //應用根目錄 public static String fs = File.separator; public final static String localPath = System.getProperty("user.dir")+fs; public final static String soundDir = localPath+"sound"+fs; // public static Webcam camera = null; private JFrame frame; // public static FaceEngine faceEngine = null; @SuppressWarnings("rawtypes") public static List FaceFeature = new ArrayList<Map<String, String>>(); public static JSONArray aryFFTime = new JSONArray(); public static JSONArray aryFFCnt = new JSONArray(); public static String lastTime = "2019-01-09 13:30:00"; public static int faceCnt = 0; /** * Launch the application. */ public static void main(String[] args) { //判斷程式是否已經執行 String s = localPath+"lockApp.txt"; // RandomAccessFile raf = null; try { raf = new RandomAccessFile(new File(s), "rws"); } catch (FileNotFoundException e1) { JOptionPane.showMessageDialog(null, "獨佔檔案時發生異常。"+e1, "錯誤",JOptionPane.ERROR_MESSAGE); System.exit(0); } FileChannel fcin = raf.getChannel(); FileLock flin = null; try { flin = fcin.tryLock(); } catch (Exception e) { JOptionPane.showMessageDialog(null, "鎖檔案時發生異常:"+e, "錯誤",JOptionPane.ERROR_MESSAGE); System.exit(0); } if (flin == null) { JOptionPane.showMessageDialog(null, "程式已在執行,不可重複。", "錯誤",JOptionPane.ERROR_MESSAGE); System.exit(0); } s = "D:\\Dev\\ec_workspace\\cs1914age"; if(!s.equals(System.getProperty("user.dir"))) { if(args.length == 0) { JOptionPane.showMessageDialog(null, "沒有入參,程式將終止。", "錯誤",JOptionPane.ERROR_MESSAGE); System.exit(0); return; } if(!"age".equals(MyFunc.strTrim(args[0]).toLowerCase())) { JOptionPane.showMessageDialog(null, "入參錯誤,程式將終止。", "錯誤",JOptionPane.ERROR_MESSAGE); System.exit(0); return; } } //獲取攝像頭 camera = Webcam.getDefault(); if (camera == null) { JOptionPane.showMessageDialog(null, "攝像頭獲取失敗。", "錯誤",JOptionPane.ERROR_MESSAGE); return; } //初始化人臉引擎 s = HowOldAreUAs.initEngine(); if(!"".equals(s)) { JOptionPane.showMessageDialog(null, s, "錯誤",JOptionPane.ERROR_MESSAGE); System.exit(0); return; } //啟動窗體 EventQueue.invokeLater(new Runnable() { public void run() { try { HowOldAreU window = new HowOldAreU(); window.frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the application. */ public HowOldAreU() { initialize(); } /** * Initialize the contents of the frame. */ private void initialize() { // frame = new JFrame(); frame.setTitle("猜年齡"); frame.setBounds(100, 100, 610, 370); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().setLayout(new BorderLayout(0, 0)); frame.setExtendedState(JFrame.MAXIMIZED_BOTH); frame.setUndecorated(true);//去邊框 //攝像頭載入到面板 WebcamPanel panel = new WebcamPanel(camera); frame.getContentPane().add(panel, BorderLayout.CENTER); //啟動聲音 HowOldAreUAs.playSound(100); //執行緒(識別頻率:毫秒) Timer timerMain = new Timer(); timerMain.scheduleAtFixedRate(new TimerTask() { public void run() { if (camera != null) { HowOldAreUAs.photo(); } } }, 0, 500); } }
==================================== HowOldAreUAs ==================================== package app; import java.awt.image.BufferedImage; import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Random; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.arcsoft.face.AgeInfo; import com.arcsoft.face.Face3DAngle; import com.arcsoft.face.FaceFeature; import com.arcsoft.face.FaceInfo; import com.arcsoft.face.FaceSimilar; import com.arcsoft.face.FunctionConfiguration; import com.arcsoft.face.GenderInfo; import com.arcsoft.face.Rect; import com.arcsoft.face.enums.ImageFormat; import com.sun.jna.Platform; import app.FaceAbout.ImageInfo; import tools.MyFunc; import tools.SoundPlay; public class HowOldAreUAs { public static final int recoFreq = 60;//同一人不重複識別時間(秒) public static final int scoreThreshold = 70;//人臉相似度閥值 //3D角度閥值 public static final BigDecimal yes3d = new BigDecimal("5"); //拍照 @SuppressWarnings("unchecked") public static void photo() { int rtn=-1,sex=-1,age=-1; //當前時間 String nowTime = MyFunc.getSvrTime("yyyy-MM-dd HH:mm:ss"); //不重複識別時間(去除過期的) for(int n=HowOldAreU.aryFFTime.size()-1;n>=0;n--) { if(MyFunc.datetimeSub(HowOldAreU.aryFFTime.get(n).toString(), nowTime) >= recoFreq) { HowOldAreU.aryFFTime.remove(n); HowOldAreU.aryFFCnt.remove(n); HowOldAreU.FaceFeature.remove(n); } } //拍照 BufferedImage cameraImg = HowOldAreU.camera.getImage(); //找臉 List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>(); ImageInfo imageInfo = new FaceAbout().bufferedImage2ImageInfo(cameraImg); HowOldAreU.faceEngine.detectFaces(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList); int cnt = faceInfoList.size(); if (cnt == 0) { //5分鐘後,如果沒有人來,則呼喚 if(MyFunc.datetimeSub(HowOldAreU.lastTime, nowTime) > 300) { HowOldAreU.lastTime = nowTime; playSound(200); } return; } HowOldAreU.lastTime = nowTime; //找最大臉(第一張臉即為最大臉) FaceInfo oneFace = faceInfoList.get(0); //提取臉紋 FaceFeature CmFeature = new FaceFeature(); rtn = HowOldAreU.faceEngine.extractFaceFeature(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, oneFace, CmFeature); if (rtn !=0) { playSound(250); return; } //是否剛剛識別過 int rfe = 0; int dSimilScore = 0; FaceSimilar faceSimilar = new FaceSimilar(); for(int n=0;n<HowOldAreU.aryFFTime.size();n++) { rtn = HowOldAreU.faceEngine.compareFaceFeature(CmFeature, (FaceFeature) HowOldAreU.FaceFeature.get(n), faceSimilar); if (rtn != 0) { return; } //得分 dSimilScore = new BigDecimal(faceSimilar.getScore()).multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); //大於閥值 if(dSimilScore >= scoreThreshold){ if(MyFunc.datetimeSub(HowOldAreU.aryFFTime.get(n).toString(), nowTime) < recoFreq) { rfe = 1; int hdt = Integer.parseInt( HowOldAreU.aryFFCnt.get(n).toString() ); if(hdt >= 1 && hdt <= 3) { playSound(180+hdt); HowOldAreU.aryFFCnt.set(n, hdt+1 ); //停頓一下 try { Thread.sleep(3000); } catch(InterruptedException ex) { Thread.currentThread().interrupt(); } } break; } } } //最近識別過 if(rfe == 1) {return;} //識別過10個人後,做一次自我介紹 if(HowOldAreU.faceCnt == 11) { HowOldAreU.faceCnt = 0; } if(HowOldAreU.faceCnt == 0) { playSound(150); HowOldAreU.faceCnt ++; } //停頓一下 try { Thread.sleep(1000); } catch(InterruptedException ex) { Thread.currentThread().interrupt(); } //原型 faceInfoList.add(oneFace); rtn = HowOldAreU.faceEngine.process(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList, FunctionConfiguration.builder().supportAge(true).supportFace3dAngle(true).supportGender(true).build()); if (rtn !=0) { playSound(250); return; } //3D資訊提取 List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>(); rtn = HowOldAreU.faceEngine.getFace3DAngle(face3DAngleList); if (rtn !=0) { playSound(250); return; } if(face3DAngleList.size() == 0) { playSound(250); return; } //0: 正常,其他數值:檢測結果不可信 int status3d = face3DAngleList.get(0).getStatus(); if(status3d != 0) {return;} BigDecimal pitch = new BigDecimal("0"); BigDecimal roll = new BigDecimal("0"); BigDecimal yaw = new BigDecimal("0"); BigDecimal yes3db = new BigDecimal("0").subtract(yes3d); //俯仰角 pitch = new BigDecimal(face3DAngleList.get(0).getPitch()).setScale(7, BigDecimal.ROUND_HALF_UP); if(pitch.compareTo(yes3d) == 1) { playSound(301); return; } if(pitch.compareTo(yes3db) == -1) { playSound(302); return; } //橫滾角 roll = new BigDecimal(face3DAngleList.get(0).getRoll()).setScale(7, BigDecimal.ROUND_HALF_UP); if(roll.compareTo(yes3d) == 1) { playSound(311); return; } if(roll.compareTo(yes3db) == -1) { playSound(312); return; } //偏航角 yaw = new BigDecimal(face3DAngleList.get(0).getYaw()).setScale(7, BigDecimal.ROUND_HALF_UP); if(yaw.compareTo(yes3d) == 1) { playSound(321); return; } if(yaw.compareTo(yes3db) == -1) { playSound(322); return; } //年齡提取 List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>(); rtn = HowOldAreU.faceEngine.getAge(ageInfoList); if (rtn !=0) { playSoundSexAge(-1,-1); return; } age = ageInfoList.get(0).getAge(); if(age > 120) {age = 120;} //性別提取 List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>(); rtn = HowOldAreU.faceEngine.getGender(genderInfoList); if (rtn !=0) { playSoundSexAge(-1,age); return; } sex = genderInfoList.get(0).getGender(); // if(sex == -1 && age == -1) { playSound(360); return; } //播報 playSoundSexAge(sex,age); //記錄人臉,防止重複識別同一個人 HowOldAreU.FaceFeature.add(CmFeature); HowOldAreU.aryFFTime.add(nowTime); HowOldAreU.aryFFCnt.add("1"); //記錄已識別數量 HowOldAreU.faceCnt ++; //System.out.println(HowOldAreU.faceCnt+" "+now_time); } public static void playSoundSexAge(int sex,int age) { //不同年齡段,不同稱謂 String agename = "frend"; if(sex >= 0) { if(age >= 0 && age <= 2) { agename = "00-"+sex; }else if(age >= 3 && age <= 18) { agename = "03-"+sex; }else if(age >= 19 && age <= 45) { agename = "19-"+sex; }else if(age >= 46 && age <= 75) { agename = "46-"+sex; }else if(age >= 76 && age <= 120) { agename = "76-"+sex; } } SoundPlay.playSoundFile(HowOldAreU.soundDir+"agename"+HowOldAreU.fs+"agename-"+agename+".mp3", null); //推測用語 JSONArray ary = new JSONArray(); ary.add("401");//你,大概 ary.add("402");//我猜你 ary.add("403");//我估計你 ary.add("404");//我看你 ary.add("405");//你看起來 int cnt = ary.size(); //隨機選擇一個 int idx = 0; if(cnt > 1) { Random random = new Random(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3", null); //年齡 SoundPlay.playSoundFile(HowOldAreU.soundDir+"age"+HowOldAreU.fs+"age"+age+".mp3", null); //停頓一下 try { Thread.sleep(1000); } catch(InterruptedException ex) { Thread.currentThread().interrupt(); } //確認 ary = new JSONArray(); ary.add("481");//對不對啊? ary.add("482");//是不是呢? ary.add("483");//準嗎? ary.add("484");//差不多嗎? ary.add("485");//靠譜吧? cnt = ary.size(); idx = 0; if(cnt > 1) { Random random = new Random(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3", null); //停頓一下 try { Thread.sleep(2000); } catch(InterruptedException ex) { Thread.currentThread().interrupt(); } //笑一個 ary = new JSONArray(); ary.add("501");//哈哈! ary.add("502");//嘻嘻! cnt = ary.size(); idx = 0; if(cnt > 1) { Random random = new Random(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3", null); //如果錯了 ary = new JSONArray(); ary.add("521");//如果我說錯了, ary.add("522");//要是我沒有說對, cnt = ary.size(); idx = 0; if(cnt > 1) { Random random = new Random(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3", null); //別生氣 ary = new JSONArray(); ary.add("541");//你可別生氣哦! ary.add("542");//你別往心裡去啊! ary.add("543");//你千萬別介意哈! cnt = ary.size(); idx = 0; if(cnt > 1) { Random random = new Random(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3", null); //停頓一下 try { Thread.sleep(2000); } catch(InterruptedException ex) { Thread.currentThread().interrupt(); } //下一個 ary = new JSONArray(); ary.add("561");//來,下一個! ary.add("562");//請下一位朋友! ary.add("563");//下一位,誰來? cnt = ary.size(); idx = 0; if(cnt > 1) { Random random = new Random(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3", null); } public static void playSound(int sound_kind) { //http://ai.baidu.com/tech/speech/tts JSONArray ary = new JSONArray(); //檔案集 switch(sound_kind) { case 100: ary.add("101");//秋語已經啟動,就要工作啦! break; case 150: //大家好,我是機器人。主人給我取名:秋語,他還幫我訓練了一雙火眼金睛, //看一眼就能識別出你們人類的性別和年齡。有人想過來試一試嗎? ary.add("150"); break; case 181: ary.add("181");//你來過的,一分鐘之後再來,好嗎? break; case 182: ary.add("182");//你來過的,一分鐘之後再來,好嗎? break; case 183: ary.add("183");//你怎麼還來呀?跟你說了等一分鐘的!你真是個急性子,不理你了。 break; case 200: //沒有發現人臉時 ary.add("201");//怎麼沒有人來跟我玩兒? ary.add("202");//有人嗎?快來和我玩啦! ary.add("203");//我知道你幾歲了,過來試試吧! ary.add("204");//你們人呢?都到哪兒去了? ary.add("205");//我等了老半天,怎麼連個人影也沒看到! break; case 250: //看不請人臉或無法提取臉紋時 ary.add("251");//嗨!靠近一點兒,我想看看你呢! ary.add("252");//喂!過來一點嘛,我都看不清你! ary.add("253");//hello,離我近一點兒,會有驚喜的! break; //3D角度過大 case 301://俯仰角過大:請低一下頭! case 302://俯仰角過大:把頭抬一下! case 311://橫滾角過大:頭向左轉一下! case 312://橫滾角過大:向右轉一下頭! case 321://偏航角過大:脖子向左歪一下! case 322://偏航角過大:向右歪一下脖子! ary.add(sound_kind); break; case 360: //性別、年齡均未知 ary.add("361");//你太神祕了,我實在猜不出你幾歲! ary.add("362");//你到底幾歲呢?我絞盡腦汁也想不出來! ary.add("363");//我無法識別你的年齡,我要請主人繼續進化我。 break; } int cnt = ary.size(); if(cnt == 0) {return;} //隨機選擇一個 int idx = 0; if(cnt > 1) { Random random = new Random(); idx = random.nextInt(cnt)%(cnt+1); } //播放 SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3", null); } public static String initEngine() { JSONObject parm = MyFunc.GetAllProperties("config/parm.properties"); String s = MyFunc.strTrim(parm.getString("err")); if(!"".equals(s)) {return "引數檔案讀取失敗。"+s;} //APPID String APPID = MyFunc.strTrim(parm.getString("APP_ID")); if("".equals(APPID)){return "終端APPID缺失,程式將終止。";} //SDKKEY String WIN_SDKKEY = MyFunc.strTrim(parm.getString("WIN_SDKKEY")); String LIN_SDKKEY = MyFunc.strTrim(parm.getString("LIN_SDKKEY")); String SDKKEY = WIN_SDKKEY; if(!Platform.isWindows()) {SDKKEY = LIN_SDKKEY;} if("".equals(SDKKEY)){return "終端SDKKEY缺失,程式將終止。";} //載入動態庫 s = FaceAbout.loadDllSo(); if(!"".equals(s)) { return "動態庫載入失敗,程式將終止。"+s; } //人臉引擎初始化 try { HowOldAreU.faceEngine = FaceAbout.initFaceEngine(APPID, SDKKEY); } catch (IOException e) { return "人臉引擎初始化失敗,程式將終止。"+e; } return ""; } }
==================================== FaceAbout.java ==================================== package app; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorConvertOp; import java.awt.image.DataBufferByte; import java.io.File; import java.io.IOException; import java.util.ArrayList; import com.arcsoft.face.EngineConfiguration; import com.arcsoft.face.FaceEngine; import com.arcsoft.face.FunctionConfiguration; import com.sun.jna.Platform; import tools.FileOpe; public class FaceAbout { //載入本地庫 public static String loadDllSo() { String fileType = "",s="",s2=""; //路徑 String dllPath = HowOldAreU.localPath+"ArcSoft"; //新增到系統路徑 addDirToPath(dllPath); //處理依賴庫 if(Platform.isWindows()) { String[] files = new String[2]; files[0] = "msvcp120.dll"; files[1] = "msvcr120.dll"; for(int i=0;i<files.length;i++) { s = dllPath+HowOldAreU.fs+files; s2 = "C:\\Windows\\System32\\"+files; if(!new File(s2).exists()) { try { new FileOpe().copyFile(new File(s), new File(s2)); } catch (IOException e) { return "依賴庫複製失敗("+s+" -> "+s2+")。"+e; } } } } //檔案型別 if(Platform.isWindows()) { fileType = ".dll"; }else { fileType = ".so"; } ArrayList<String> ary = new ArrayList<String>(); ary.add("libarcsoft_face"); ary.add("libarcsoft_face_engine"); ary.add("libarcsoft_face_engine_jni"); //載入 for(int i=0;i<ary.size();i++) { s = dllPath+HowOldAreU.fs+ary.get(i)+fileType; try { System.load(s); }catch (Exception e) { return "動態庫("+s+")載入失敗。"+e; } } return ""; } //新增路徑 private static void addDirToPath(String s) { try { //獲取系統path變數物件 java.lang.reflect.Field field = ClassLoader.class.getDeclaredField("sys_paths"); //設定此變數物件可訪問 field.setAccessible(true); //獲取此變數物件的值 String[] path = (String[])field.get(null); //是否已經存在 for(int i=0;i<path.length;i++) { if(s.equals(path)) { field.setAccessible(false); return; } } //建立字串陣列,在原來的陣列長度上增加一個,用於存放增加的目錄 String[] tem = new String[path.length+1]; //將原來的path變數複製到tem中 System.arraycopy(path,0,tem,0,path.length); //將增加的目錄存入新的變數陣列中 tem[path.length] = s; //將增加目錄後的陣列賦給path變數物件 field.set(null,tem); } catch (Exception e) { e.printStackTrace(); } } //初始化 public static FaceEngine initFaceEngine(String APPID, String SDKKEY) throws IOException { //初始化人臉引擎 FaceEngine faceEngine = new FaceEngine(); faceEngine.active(APPID, SDKKEY); //引擎配置 EngineConfiguration engineConfiguration = EngineConfiguration.builder().functionConfiguration( FunctionConfiguration.builder() .supportAge(true) .supportFace3dAngle(true) .supportFaceDetect(true) .supportFaceRecognition(true) .supportGender(true) .build()).build(); //初始化引擎 faceEngine.init(engineConfiguration); return faceEngine; } //錯誤碼 public static String errCodeList(int codeNo) { String infoStr = ""; switch(codeNo) { case 0: infoStr = "成功";break; case 1: infoStr = "錯誤原因不明";break; case 2: infoStr = "無效的引數";break; case 3: infoStr = "引擎不支援";break; case 4: infoStr = "記憶體不足";break; case 5: infoStr = "狀態錯誤";break; case 6: infoStr = "使用者取消相關操作";break; case 7: infoStr = "操作時間過期";break; case 8: infoStr = "使用者暫停操作";break; case 9: infoStr = "緩衝上溢";break; case 10: infoStr = "緩衝下溢";break; case 11: infoStr = "存貯空間不足";break; case 12: infoStr = "元件不存在";break; case 13: infoStr = "全域性資料不存在";break; case 28673: infoStr = "無效的AppId";break; case 28674: infoStr = "無效的SDKkey";break; case 28675: infoStr = "AppId和SDKKey不匹配";break; case 28676: infoStr = "SDKKey和使用的SDK不匹配";break; case 28677: infoStr = "系統版本不被當前SDK所支援";break; case 28678: infoStr = "SDK有效期過期,需要重新下載更新";break; case 73729: infoStr = "無效的輸入記憶體";break; case 73730: infoStr = "無效的輸入影象引數";break; case 73731: infoStr = "無效的臉部資訊";break; case 73732: infoStr = "當前裝置無GPU可用";break; case 73733: infoStr = "待比較的兩個人臉特徵的版本不一致";break; case 81921: infoStr = "人臉特徵檢測錯誤未知";break; case 81922: infoStr = "人臉特徵檢測記憶體錯誤";break; case 81923: infoStr = "人臉特徵檢測格式錯誤";break; case 81924: infoStr = "人臉特徵檢測引數錯誤";break; case 81925: infoStr = "人臉特徵檢測結果置信度低";break; case 86017: infoStr = "Engine不支援的檢測屬性";break; case 86018: infoStr = "需要檢測的屬性未初始化";break; case 86019: infoStr = "待獲取的屬性未在process中處理過";break; case 86020: infoStr = "ROCESS不支援的檢測屬性,例如FR,有自己獨立的處理函式";break; case 86021: infoStr = "無效的輸入影象";break; case 86022: infoStr = "無效的臉部資訊";break; case 90113: infoStr = "SDK啟用失敗,請開啟讀寫許可權";break; case 90114: infoStr = "SDK已啟用";break; case 90115: infoStr = "SDK未啟用";break; case 90116: infoStr = "detectFaceScaleVal不支援";break; case 90117: infoStr = "SDK版本不匹配";break; case 90118: infoStr = "裝置不匹配";break; case 90119: infoStr = "唯一標識不匹配";break; case 90120: infoStr = "引數為空";break; case 90121: infoStr = "活體檢測功能已過期";break; case 90122: infoStr = "版本不支援";break; case 90123: infoStr = "簽名錯誤";break; case 90124: infoStr = "資料庫插入錯誤";break; case 90125: infoStr = "唯一識別符號校驗失敗";break; case 90126: infoStr = "顏色空間不支援";break; case 90127: infoStr = "圖片寬度或高度不支援";break; case 90128: infoStr = "android.permission.READ_PHONE_STATE許可權被拒絕";break; case 90129: infoStr = "啟用資料被破壞,請刪除啟用檔案,重新進行啟用";break; case 94209: infoStr = "無法解析主機地址";break; case 94210: infoStr = "無法連線伺服器";break; case 94211: infoStr = "網路連線超時";break; case 94212: infoStr = "網路未知錯誤";break; case 98305: infoStr = "無法連線啟用碼伺服器";break; case 98306: infoStr = "伺服器系統錯誤";break; case 98307: infoStr = "請求引數錯誤";break; case 98308: infoStr = "啟用碼正確,且未被使用,但和傳入的APPID及APPKEY不匹配";break; case 98309: infoStr = "傳入的KEY值雖然正確,但此KEY已經被啟用";break; case 98310: infoStr = "KEY格式不對,一般來說是KEY錯誤或者未傳入KEY值";break; } return infoStr; } // public ImageInfo bufferedImage2ImageInfo(BufferedImage image) { ImageInfo imageInfo = new ImageInfo(); int width = image.getWidth(); int height = image.getHeight(); // 使圖片居中 width = width & (~3); height = height & (~3); imageInfo.width = width; imageInfo.height = height; //根據原圖片資訊新建一個圖片緩衝區 BufferedImage resultImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); //得到原圖的rgb畫素矩陣 int[] rgb = image.getRGB(0, 0, width, height, null, 0, width); //將畫素矩陣 繪製到新的圖片緩衝區中 resultImage.setRGB(0, 0, width, height, rgb, 0, width); //進行資料格式化為可用資料 BufferedImage dstImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR); if (resultImage.getType() != BufferedImage.TYPE_3BYTE_BGR) { ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); ColorConvertOp colorConvertOp = new ColorConvertOp(cs, dstImage.createGraphics().getRenderingHints()); colorConvertOp.filter(resultImage, dstImage); } else { dstImage = resultImage; } //獲取rgb資料 imageInfo.rgbData = ((DataBufferByte) (dstImage.getRaster().getDataBuffer())).getData(); return imageInfo; } // public class ImageInfo { public byte[] rgbData; public int width; public int height; public byte[] getRgbData() { return rgbData; } public void setRgbData(byte[] rgbData) { this.rgbData = rgbData; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } } }
==============
程式在Windows7 64位 可以執行起來。裡面呼叫攝像頭的包,連結:https://github.com/sarxos/web...
程式之中的不當之處,還請社群的技術專家和各位同仁批評指正,謝謝。