微信公众号开发(十三):图片处理器之人脸识别

247 篇文章 1 订阅
29 篇文章 1 订阅
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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值