java版 利用人脸识别猜年龄 基于ArcFace2.0的 demo

32次阅读

共计 19459 个字符,预计需要花费 49 分钟才能阅读完成。

首先感谢虹软,是你们提供这么好的 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 角度、用语音提醒用户,这是一个的互动环节。
最后,程序会幽默的、萌萌的告诉用户他的性别、年龄。

作者:huanghua8080@126.com
*/

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…
程序之中的不当之处,还请社区的技术专家和各位同仁批评指正,谢谢。

正文完
 0