public class ImageMessageHandler extends DefaultMessageHandler {
@Override
public boolean canDo(Map<String, String> requestMap) {
// 消息类型
String msgType = requestMap.get("MsgType");
return msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE);
}
@Override
public BaseMessage handleByMe(Map<String, String> requestMap) {
// 取得图片地址
String picUrl = requestMap.get("PicUrl");
// 人脸检测
String detectResult = FaceService.detect(picUrl);
return MessageFactory.createTextMessage(fromUserName, toUserName, detectResult);
}
}
/**
* 人脸检测服务
*
* @author 熊诗言
* @date 2015-09-06
*/
public class FaceService {
/**
* 发送http 请求
*
* @param requestUrl 请求地址
* @return String
*/
private static String httpRequest(String requestUrl) {
StringBuffer buffer = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoInput(true);
httpUrlConn.setRequestMethod("GET");
httpUrlConn.connect();
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
/**
* 调用Face++ API 实现人脸检测
*
* @param picUrl 待检测图片的访问地址
* @return List<Face> 人脸列表
*/
private static List<Face> faceDetect(String picUrl) {
List<Face> faceList = new ArrayList<Face>();
try {
// 拼接Face++人脸检测的请求地址
String queryUrl = "http://apicn.faceplusplus.com/v2/detection/detect?url=URL&api_secret=API_SECRET&api_key=API_KEY";
// 对URL 进行编码
queryUrl = queryUrl.replace("URL", java.net.URLEncoder.encode(picUrl, "UTF-8"));
queryUrl = queryUrl.replace("API_KEY", "0aee8f9d31d329ba21670511cb2e72da");
queryUrl = queryUrl.replace("API_SECRET", "rJzF5cQol5UWaj-kwT5Gio9hx-AYITdT");
// 调用人脸检测接口
String json = httpRequest(queryUrl);
// 解析返回json 中的Face 列表
JSONArray jsonArray = JSONObject.fromObject(json).getJSONArray("face");
// 遍历检测到的人脸
for (int i = 0; i < jsonArray.size(); i++) {
// face
JSONObject faceObject = (JSONObject) jsonArray.get(i);
// attribute
JSONObject attrObject = faceObject.getJSONObject("attribute");
// position
JSONObject posObject = faceObject.getJSONObject("position");
Face face = new Face();
face.setFaceId(faceObject.getString("face_id"));
face.setAgeValue(attrObject.getJSONObject("age").getInt("value"));
face.setAgeRange(attrObject.getJSONObject("age").getInt("range"));
face.setGenderValue(genderConvert(attrObject.getJSONObject("gender").getString("value")));
face.setGenderConfidence(attrObject.getJSONObject("gender").getDouble("confidence"));
face.setRaceValue(raceConvert(attrObject.getJSONObject("race").getString("value")));
face.setRaceConfidence(attrObject.getJSONObject("race").getDouble("confidence"));
face.setSmilingValue(attrObject.getJSONObject("smiling").getDouble("value"));
face.setCenterX(posObject.getJSONObject("center").getDouble("x"));
face.setCenterY(posObject.getJSONObject("center").getDouble("y"));
faceList.add(face);
}
// 将检测出的Face 按从左至右的顺序排序
Collections.sort(faceList);
} catch (Exception e) {
faceList = null;
e.printStackTrace();
}
return faceList;
}
/**
* 性别转换(英文->中文)
*
* @param gender
* @return
*/
private static String genderConvert(String gender) {
String result = "男性";
if ("Male".equals(gender))
result = "男性";
else if ("Female".equals(gender))
result = "女性";
return result;
}
/**
* 人种转换(英文->中文)
*
* @param race
* @return
*/
private static String raceConvert(String race) {
String result = "黄色";
if ("Asian".equals(race))
result = "黄色";
else if ("White".equals(race))
result = "白色";
else if ("Black".equals(race))
result = "黑色";
return result;
}
/**
* 根据人脸识别结果组装消息
*
* @param faceList 人脸列表
* @return
*/
private static String makeMessage(List<Face> faceList) {
StringBuffer buffer = new StringBuffer();
// 检测到1 张脸
if (1 == faceList.size()) {
buffer.append("共检测到").append(faceList.size()).append(" 张人脸").append("\n");
for (Face face : faceList) {
buffer.append(face.getRaceValue()).append("人种,");
buffer.append(face.getGenderValue()).append(",");
buffer.append(face.getAgeValue()).append("岁左右").append("\n");
}
}
// 检测到2-10 张脸
else if (faceList.size() > 1 && faceList.size() <= 10) {
buffer.append("共检测到").append(faceList.size()).append(" 张人脸,按脸部中心位置从左至右依次为:").append("\n");
for (Face face : faceList) {
buffer.append(face.getRaceValue()).append("人种,");
buffer.append(face.getGenderValue()).append(",");
buffer.append(face.getAgeValue()).append("岁左右").append("\n");
}
}
// 检测到10 张脸以上
else if (faceList.size() > 10) {
buffer.append("共检测到").append(faceList.size()).append(" 张人脸").append("\n");
// 统计各人种、性别的人数
int asiaMale = 0;
int asiaFemale = 0;
int whiteMale = 0;
int whiteFemale = 0;
int blackMale = 0;
int blackFemale = 0;
for (Face face : faceList) {
if ("黄色".equals(face.getRaceValue()))
if ("男性".equals(face.getGenderValue()))
asiaMale++;
else
asiaFemale++;
else if ("白色".equals(face.getRaceValue()))
if ("男性".equals(face.getGenderValue()))
whiteMale++;
else
whiteFemale++;
else if ("黑色".equals(face.getRaceValue()))
if ("男性".equals(face.getGenderValue()))
blackMale++;
else
blackFemale++;
}
if (0 != asiaMale || 0 != asiaFemale)
buffer.append("黄色人种:").append(asiaMale).append("男").append(asiaFemale).append("女").append("\n");
if (0 != whiteMale || 0 != whiteFemale)
buffer.append("白色人种:").append(whiteMale).append("男").append(whiteFemale).append("女").append("\n");
if (0 != blackMale || 0 != blackFemale)
buffer.append("黑色人种:").append(blackMale).append("男").append(blackFemale).append("女").append("\n");
}
// 移除末尾空格
buffer = new StringBuffer(buffer.substring(0, buffer.lastIndexOf("\n")));
return buffer.toString();
}
/**
* 提供给外部调用的人脸检测方法
*
* @param picUrl 待检测图片的访问地址
* @return String
*/
public static String detect(String picUrl) {
// 默认回复信息
String result = "未识别到人脸,请换一张清晰的照片再试!";
List<Face> faceList = faceDetect(picUrl);
if (null != faceList && faceList.size()>0) {
result = makeMessage(faceList);
}
return result;
}
public static void main(String[] args) {
String picUrl = "http://pic11.nipic.com/20101111/6153002_002722872554_2.jpg";
System.out.println(detect(picUrl));
}
}
/**
* Face Model
*
* @author 熊诗言
* @date 2015-09-06
*/
public class Face implements Comparable<Face> {
// 被检测出的每一张人脸都在Face++系统中的标识符
private String faceId;
// 年龄估计值
private int ageValue;
// 年龄估计值的正负区间
private int ageRange;
// 性别:Male/Female
private String genderValue;
// 性别分析的可信度
private double genderConfidence;
// 人种:Asian/White/Black
private String raceValue;
// 人种分析的可信度
private double raceConfidence;
// 微笑程度
private double smilingValue;
// 人脸框的中心点坐标
private double centerX;
private double centerY;
。。。
// 根据人脸中心点坐标从左至右排序
public int compareTo(Face face) {
int result = 0;
if (this.getCenterX() > face.getCenterX())
result = 1;
else
result = -1;
return result;
}
}
@Override
public boolean canDo(Map<String, String> requestMap) {
// 消息类型
String msgType = requestMap.get("MsgType");
return msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE);
}
@Override
public BaseMessage handleByMe(Map<String, String> requestMap) {
// 取得图片地址
String picUrl = requestMap.get("PicUrl");
// 人脸检测
String detectResult = FaceService.detect(picUrl);
return MessageFactory.createTextMessage(fromUserName, toUserName, detectResult);
}
}
/**
* 人脸检测服务
*
* @author 熊诗言
* @date 2015-09-06
*/
public class FaceService {
/**
* 发送http 请求
*
* @param requestUrl 请求地址
* @return String
*/
private static String httpRequest(String requestUrl) {
StringBuffer buffer = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoInput(true);
httpUrlConn.setRequestMethod("GET");
httpUrlConn.connect();
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
/**
* 调用Face++ API 实现人脸检测
*
* @param picUrl 待检测图片的访问地址
* @return List<Face> 人脸列表
*/
private static List<Face> faceDetect(String picUrl) {
List<Face> faceList = new ArrayList<Face>();
try {
// 拼接Face++人脸检测的请求地址
String queryUrl = "http://apicn.faceplusplus.com/v2/detection/detect?url=URL&api_secret=API_SECRET&api_key=API_KEY";
// 对URL 进行编码
queryUrl = queryUrl.replace("URL", java.net.URLEncoder.encode(picUrl, "UTF-8"));
queryUrl = queryUrl.replace("API_KEY", "0aee8f9d31d329ba21670511cb2e72da");
queryUrl = queryUrl.replace("API_SECRET", "rJzF5cQol5UWaj-kwT5Gio9hx-AYITdT");
// 调用人脸检测接口
String json = httpRequest(queryUrl);
// 解析返回json 中的Face 列表
JSONArray jsonArray = JSONObject.fromObject(json).getJSONArray("face");
// 遍历检测到的人脸
for (int i = 0; i < jsonArray.size(); i++) {
// face
JSONObject faceObject = (JSONObject) jsonArray.get(i);
// attribute
JSONObject attrObject = faceObject.getJSONObject("attribute");
// position
JSONObject posObject = faceObject.getJSONObject("position");
Face face = new Face();
face.setFaceId(faceObject.getString("face_id"));
face.setAgeValue(attrObject.getJSONObject("age").getInt("value"));
face.setAgeRange(attrObject.getJSONObject("age").getInt("range"));
face.setGenderValue(genderConvert(attrObject.getJSONObject("gender").getString("value")));
face.setGenderConfidence(attrObject.getJSONObject("gender").getDouble("confidence"));
face.setRaceValue(raceConvert(attrObject.getJSONObject("race").getString("value")));
face.setRaceConfidence(attrObject.getJSONObject("race").getDouble("confidence"));
face.setSmilingValue(attrObject.getJSONObject("smiling").getDouble("value"));
face.setCenterX(posObject.getJSONObject("center").getDouble("x"));
face.setCenterY(posObject.getJSONObject("center").getDouble("y"));
faceList.add(face);
}
// 将检测出的Face 按从左至右的顺序排序
Collections.sort(faceList);
} catch (Exception e) {
faceList = null;
e.printStackTrace();
}
return faceList;
}
/**
* 性别转换(英文->中文)
*
* @param gender
* @return
*/
private static String genderConvert(String gender) {
String result = "男性";
if ("Male".equals(gender))
result = "男性";
else if ("Female".equals(gender))
result = "女性";
return result;
}
/**
* 人种转换(英文->中文)
*
* @param race
* @return
*/
private static String raceConvert(String race) {
String result = "黄色";
if ("Asian".equals(race))
result = "黄色";
else if ("White".equals(race))
result = "白色";
else if ("Black".equals(race))
result = "黑色";
return result;
}
/**
* 根据人脸识别结果组装消息
*
* @param faceList 人脸列表
* @return
*/
private static String makeMessage(List<Face> faceList) {
StringBuffer buffer = new StringBuffer();
// 检测到1 张脸
if (1 == faceList.size()) {
buffer.append("共检测到").append(faceList.size()).append(" 张人脸").append("\n");
for (Face face : faceList) {
buffer.append(face.getRaceValue()).append("人种,");
buffer.append(face.getGenderValue()).append(",");
buffer.append(face.getAgeValue()).append("岁左右").append("\n");
}
}
// 检测到2-10 张脸
else if (faceList.size() > 1 && faceList.size() <= 10) {
buffer.append("共检测到").append(faceList.size()).append(" 张人脸,按脸部中心位置从左至右依次为:").append("\n");
for (Face face : faceList) {
buffer.append(face.getRaceValue()).append("人种,");
buffer.append(face.getGenderValue()).append(",");
buffer.append(face.getAgeValue()).append("岁左右").append("\n");
}
}
// 检测到10 张脸以上
else if (faceList.size() > 10) {
buffer.append("共检测到").append(faceList.size()).append(" 张人脸").append("\n");
// 统计各人种、性别的人数
int asiaMale = 0;
int asiaFemale = 0;
int whiteMale = 0;
int whiteFemale = 0;
int blackMale = 0;
int blackFemale = 0;
for (Face face : faceList) {
if ("黄色".equals(face.getRaceValue()))
if ("男性".equals(face.getGenderValue()))
asiaMale++;
else
asiaFemale++;
else if ("白色".equals(face.getRaceValue()))
if ("男性".equals(face.getGenderValue()))
whiteMale++;
else
whiteFemale++;
else if ("黑色".equals(face.getRaceValue()))
if ("男性".equals(face.getGenderValue()))
blackMale++;
else
blackFemale++;
}
if (0 != asiaMale || 0 != asiaFemale)
buffer.append("黄色人种:").append(asiaMale).append("男").append(asiaFemale).append("女").append("\n");
if (0 != whiteMale || 0 != whiteFemale)
buffer.append("白色人种:").append(whiteMale).append("男").append(whiteFemale).append("女").append("\n");
if (0 != blackMale || 0 != blackFemale)
buffer.append("黑色人种:").append(blackMale).append("男").append(blackFemale).append("女").append("\n");
}
// 移除末尾空格
buffer = new StringBuffer(buffer.substring(0, buffer.lastIndexOf("\n")));
return buffer.toString();
}
/**
* 提供给外部调用的人脸检测方法
*
* @param picUrl 待检测图片的访问地址
* @return String
*/
public static String detect(String picUrl) {
// 默认回复信息
String result = "未识别到人脸,请换一张清晰的照片再试!";
List<Face> faceList = faceDetect(picUrl);
if (null != faceList && faceList.size()>0) {
result = makeMessage(faceList);
}
return result;
}
public static void main(String[] args) {
String picUrl = "http://pic11.nipic.com/20101111/6153002_002722872554_2.jpg";
System.out.println(detect(picUrl));
}
}
/**
* Face Model
*
* @author 熊诗言
* @date 2015-09-06
*/
public class Face implements Comparable<Face> {
// 被检测出的每一张人脸都在Face++系统中的标识符
private String faceId;
// 年龄估计值
private int ageValue;
// 年龄估计值的正负区间
private int ageRange;
// 性别:Male/Female
private String genderValue;
// 性别分析的可信度
private double genderConfidence;
// 人种:Asian/White/Black
private String raceValue;
// 人种分析的可信度
private double raceConfidence;
// 微笑程度
private double smilingValue;
// 人脸框的中心点坐标
private double centerX;
private double centerY;
。。。
// 根据人脸中心点坐标从左至右排序
public int compareTo(Face face) {
int result = 0;
if (this.getCenterX() > face.getCenterX())
result = 1;
else
result = -1;
return result;
}
}