首先感谢虹软,是你们提供这么好的SDK支撑了我们的想象力!
这是一个用javav编写的可视化应用,用户通过自己的脸和计算机进行交互,计算机则通过萌萌女孩的语音和用户对话。
核心程序就是利用ArcFace2.0识别性别、年龄,但是为了获得正面脸,会根据ArcFace2.0的人脸3D角度、用语音提醒用户,这是一个的互动环节。最后,程序会幽默的、萌萌的告诉用户他的性别、年龄。
获取SDKhttps://ai.arcsoft.com.cn/index.htm?utm_source=csdn&utm_medium=referral
完整的项目源码、可执行程序,放在百度网盘:链接:https://pan.baidu.com/s/1eHF66l111S3Rs0VaS7v_LA
提取码: ffag
其中主要的3个java文件,代码如下:
HowOldAreU.javapackageapp;importjava.awt.EventQueue;importjavax.swing.JFrame;importjava.io.File;importjava.io.FileNotFoundException;importjava.io.RandomAccessFile;importjava.nio.channels.FileChannel;importjava.nio.channels.FileLock;importjava.util.ArrayList;importjava.util.List;importjava.util.Map;importjava.util.Timer;importjava.util.TimerTask;importjava.awt.BorderLayout;importcom.alibaba.fastjson.JSONArray;importcom.arcsoft.face.FaceEngine;importcom.github.sarxos.webcam.Webcam;importcom.github.sarxos.webcam.WebcamPanel;importtools.MyFunc;importjavax.swing.JOptionPane;/*这是一个用javav编写的可视化应用,用户通过自己的脸和计算机进行交互,计算机则通过萌萌女孩的语音和用户对话。
核心程序就是利用ArcFace2.0识别性别、年龄,但是为了获得正面脸,会根据ArcFace2.0的人脸3D角度、用语音提醒用户,这是一个的互动环节。
最后,程序会幽默的、萌萌的告诉用户他的性别、年龄。
*/publicclassHowOldAreU{//应用根目录publicstaticString fs = File.separator;publicfinalstaticString localPath = System.getProperty("user.dir")+fs;publicfinalstaticString soundDir = localPath+"sound"+fs;//publicstaticWebcam camera =null;privateJFrame frame;//publicstaticFaceEngine faceEngine =null;@SuppressWarnings("rawtypes")publicstaticList FaceFeature =newArrayList>();publicstaticJSONArray aryFFTime =newJSONArray();publicstaticJSONArray aryFFCnt =newJSONArray();publicstaticString lastTime ="2019-01-09 13:30:00";publicstaticintfaceCnt =0;/**
* Launch the application.
*/publicstaticvoidmain(String[] args){//判断程序是否已经运行String s = localPath+"lockApp.txt";//RandomAccessFile raf =null;try{ raf =newRandomAccessFile(newFile(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(newRunnable() {publicvoidrun(){try{ HowOldAreU window =newHowOldAreU(); window.frame.setVisible(true); }catch(Exception e) { e.printStackTrace(); } } }); }/**
* Create the application.
*/publicHowOldAreU(){ initialize(); }/**
* Initialize the contents of the frame.
*/privatevoidinitialize(){//frame =newJFrame(); frame.setTitle("猜年龄"); frame.setBounds(100,100,610,370); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().setLayout(newBorderLayout(0,0)); frame.setExtendedState(JFrame.MAXIMIZED_BOTH); frame.setUndecorated(true);//去边框//摄像头加载到面板WebcamPanel panel =newWebcamPanel(camera); frame.getContentPane().add(panel, BorderLayout.CENTER);//启动声音HowOldAreUAs.playSound(100);//线程(识别频率:毫秒)Timer timerMain =newTimer(); timerMain.scheduleAtFixedRate(newTimerTask() {publicvoidrun(){if(camera !=null) { HowOldAreUAs.photo(); } } },0,500); }
====================================HowOldAreUAs====================================packageapp;importjava.awt.image.BufferedImage;importjava.io.IOException;importjava.math.BigDecimal;importjava.util.ArrayList;importjava.util.List;importjava.util.Random;importcom.alibaba.fastjson.JSONArray;importcom.alibaba.fastjson.JSONObject;importcom.arcsoft.face.AgeInfo;importcom.arcsoft.face.Face3DAngle;importcom.arcsoft.face.FaceFeature;importcom.arcsoft.face.FaceInfo;importcom.arcsoft.face.FaceSimilar;importcom.arcsoft.face.FunctionConfiguration;importcom.arcsoft.face.GenderInfo;importcom.arcsoft.face.Rect;importcom.arcsoft.face.enums.ImageFormat;importcom.sun.jna.Platform;importapp.FaceAbout.ImageInfo;importtools.MyFunc;importtools.SoundPlay;publicclassHowOldAreUAs{publicstaticfinalintrecoFreq =60;//同一人不重复识别时间(秒)publicstaticfinalintscoreThreshold =70;//人脸相似度阀值//3D角度阀值publicstaticfinalBigDecimal yes3d =newBigDecimal("5");//拍照@SuppressWarnings("unchecked")publicstaticvoidphoto(){intrtn=-1,sex=-1,age=-1;//当前时间String nowTime = MyFunc.getSvrTime("yyyy-MM-dd HH:mm:ss");//不重复识别时间(去除过期的)for(intn=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 faceInfoList =newArrayList(); ImageInfo imageInfo =newFaceAbout().bufferedImage2ImageInfo(cameraImg); HowOldAreU.faceEngine.detectFaces(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, faceInfoList);intcnt = 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 =newFaceFeature(); rtn = HowOldAreU.faceEngine.extractFaceFeature(imageInfo.getRgbData(), imageInfo.getWidth(), imageInfo.getHeight(), ImageFormat.CP_PAF_BGR24, oneFace, CmFeature);if(rtn !=0) { playSound(250);return; }//是否刚刚识别过intrfe =0;intdSimilScore =0; FaceSimilar faceSimilar =newFaceSimilar();for(intn=0;n= scoreThreshold){if(MyFunc.datetimeSub(HowOldAreU.aryFFTime.get(n).toString(), nowTime) < recoFreq) { rfe =1;inthdt = 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 face3DAngleList =newArrayList(); rtn = HowOldAreU.faceEngine.getFace3DAngle(face3DAngleList);if(rtn !=0) { playSound(250);return; }if(face3DAngleList.size() ==0) { playSound(250);return; }//0: 正常,其他数值:检测结果不可信intstatus3d = face3DAngleList.get(0).getStatus();if(status3d !=0) {return;} BigDecimal pitch =newBigDecimal("0"); BigDecimal roll =newBigDecimal("0"); BigDecimal yaw =newBigDecimal("0"); BigDecimal yes3db =newBigDecimal("0").subtract(yes3d);//俯仰角pitch =newBigDecimal(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 =newBigDecimal(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 =newBigDecimal(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 ageInfoList =newArrayList(); rtn = HowOldAreU.faceEngine.getAge(ageInfoList);if(rtn !=0) { playSoundSexAge(-1,-1);return; } age = ageInfoList.get(0).getAge();if(age >120) {age =120;}//性别提取List genderInfoList =newArrayList(); 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);}publicstaticvoidplaySoundSexAge(intsex,intage){//不同年龄段,不同称谓String agename ="frend";if(sex >=0) {if(age >=0&& age <=2) { agename ="00-"+sex; }elseif(age >=3&& age <=18) { agename ="03-"+sex; }elseif(age >=19&& age <=45) { agename ="19-"+sex; }elseif(age >=46&& age <=75) { agename ="46-"+sex; }elseif(age >=76&& age <=120) { agename ="76-"+sex; } } SoundPlay.playSoundFile(HowOldAreU.soundDir+"agename"+HowOldAreU.fs+"agename-"+agename+".mp3",null);//推测用语JSONArray ary =newJSONArray(); ary.add("401");//你,大概ary.add("402");//我猜你ary.add("403");//我估计你ary.add("404");//我看你ary.add("405");//你看起来intcnt = ary.size();//随机选择一个intidx =0;if(cnt >1) { Random random =newRandom(); 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 =newJSONArray(); 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 =newRandom(); 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 =newJSONArray(); ary.add("501");//哈哈!ary.add("502");//嘻嘻!cnt = ary.size(); idx =0;if(cnt >1) { Random random =newRandom(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3",null);//如果错了ary =newJSONArray(); ary.add("521");//如果我说错了,ary.add("522");//要是我没有说对,cnt = ary.size(); idx =0;if(cnt >1) { Random random =newRandom(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3",null);//别生气ary =newJSONArray(); ary.add("541");//你可别生气哦!ary.add("542");//你别往心里去啊!ary.add("543");//你千万别介意哈!cnt = ary.size(); idx =0;if(cnt >1) { Random random =newRandom(); 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 =newJSONArray(); ary.add("561");//来,下一个!ary.add("562");//请下一位朋友!ary.add("563");//下一位,谁来?cnt = ary.size(); idx =0;if(cnt >1) { Random random =newRandom(); idx = random.nextInt(cnt)%(cnt+1); } SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3",null); }publicstaticvoidplaySound(intsound_kind){// http://ai.baidu.com/tech/speech/ttsJSONArray ary =newJSONArray();//文件集switch(sound_kind) {case100: ary.add("101");//秋语已经启动,就要工作啦!break;case150://大家好,我是机器人。主人给我取名:秋语,他还帮我训练了一双火眼金睛,//看一眼就能识别出你们人类的性别和年龄。有人想过来试一试吗?ary.add("150");break;case181: ary.add("181");//你来过的,一分钟之后再来,好吗?break;case182: ary.add("182");//你来过的,一分钟之后再来,好吗?break;case183: ary.add("183");//你怎么还来呀?跟你说了等一分钟的!你真是个急性子,不理你了。break;case200://没有发现人脸时 ary.add("201");//怎么没有人来跟我玩儿? ary.add("202");//有人吗?快来和我玩啦! ary.add("203");//我知道你几岁了,过来试试吧! ary.add("204");//你们人呢?都到哪儿去了? ary.add("205");//我等了老半天,怎么连个人影也没看到!break;case250://看不请人脸或无法提取脸纹时 ary.add("251");//嗨!靠近一点儿,我想看看你呢!ary.add("252");//喂!过来一点嘛,我都看不清你! ary.add("253");//hello,离我近一点儿,会有惊喜的!break;//3D角度过大case301://俯仰角过大:请低一下头!case302://俯仰角过大:把头抬一下!case311://横滚角过大:头向左转一下!case312://横滚角过大:向右转一下头!case321://偏航角过大:脖子向左歪一下!case322://偏航角过大:向右歪一下脖子!ary.add(sound_kind);break;case360://性别、年龄均未知 ary.add("361");//你太神秘了,我实在猜不出你几岁! ary.add("362");//你到底几岁呢?我绞尽脑汁也想不出来! ary.add("363");//我无法识别你的年龄,我要请主人继续进化我。break; }intcnt = ary.size();if(cnt ==0) {return;}//随机选择一个intidx =0;if(cnt >1) { Random random =newRandom(); idx = random.nextInt(cnt)%(cnt+1); }//播放SoundPlay.playSoundFile(HowOldAreU.soundDir+ary.get(idx)+".mp3",null); }publicstaticStringinitEngine(){ JSONObject parm = MyFunc.GetAllProperties("config/parm.properties"); String s = MyFunc.strTrim(parm.getString("err"));if(!"".equals(s)) {return"参数文件读取失败。"+s; }//APPIDString APPID = MyFunc.strTrim(parm.getString("APP_ID"));if("".equals(APPID)){return"终端APPID缺失,程序将终止。";}//SDKKEYString 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====================================packageapp;importjava.awt.color.ColorSpace;importjava.awt.image.BufferedImage;importjava.awt.image.ColorConvertOp;importjava.awt.image.DataBufferByte;importjava.io.File;importjava.io.IOException;importjava.util.ArrayList;importcom.arcsoft.face.EngineConfiguration;importcom.arcsoft.face.FaceEngine;importcom.arcsoft.face.FunctionConfiguration;importcom.sun.jna.Platform;importtools.FileOpe;publicclassFaceAbout{//加载本地库publicstaticStringloadDllSo(){ String fileType ="",s="",s2="";//路径String dllPath = HowOldAreU.localPath+"ArcSoft";//添加到系统路径addDirToPath(dllPath);//处理依赖库if(Platform.isWindows()) { String[] files =newString[2]; files[0] ="msvcp120.dll"; files[1] ="msvcr120.dll";for(inti=0;i ary =newArrayList(); ary.add("libarcsoft_face"); ary.add("libarcsoft_face_engine"); ary.add("libarcsoft_face_engine_jni");//加载for(inti=0;i
程序在Windows7 64位 可以运行起来。里面调用摄像头的包,链接:https://github.com/sarxos/webcam-capture
程序之中的不当之处,还请社区的技术专家和各位同仁批评指正,谢谢。
作者:Bokeh_JS
链接:https://www.jianshu.com/p/9b1c727ff041
来源:
著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。