阿里人脸检测实践以及阿里云OSS数据库图片上传

阿里人脸检测实践

java实现调用阿里人脸识别服务实现人脸检测。在springboot项目中应用,根据前端传回的经过Base64编码的图片,直接调用阿里人脸检测服务实现检测,并将检测成功的图片存入阿里云OSS数据库 ,并存储返回的图片url。

依赖

<!--阿里云OSS依赖-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

 <!--阿里云SDK,人脸检测-->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>3.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-cms</artifactId>
            <version>7.0.3</version>
        </dependency>

方向枚举类

此处根据个人需要,用其主要为了满足自身需要存储上下左右四个方向的图片。

public enum Direction {
    UP, DOWN, LEFT, RIGHT
}

人脸检测类

package com.tjkj.tongjiankeji.component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.CommonsRequestLoggingFilter;

//import com.aliyuncs.CommonRequest;
//import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import sun.misc.BASE64Encoder;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;

/**
 * @Created with qml
 * @author:qml
 * @Date: 2019/9/4
 * @Time: 9:44
 * @Description
 */
@Component
public class FaceDetection {


    //自己阿里云的keyId
    @Value("${oss.keyid}")
    private static String accessKeyId;
    //自己阿里云的keySecert
    @Value("${oss.keysecret}")
    private static String accessKeySecret;

    //人脸检测URL
    //可根据自己的需要使用人脸属性检测,人脸识别接口,阿里均已提供
    private static String detectUrl = "https://dtplus-cn-shanghai.data.aliyuncs.com/face/detect";

    //人脸角度阈值(用以判断识别出的人脸,在我们需要的角度范围内,角度不能太大)
    private static float faceThreshold = 30;

    //DefaultProfile.getProfile的参数分别是地域,access_key_id, access_key_secret
    public static DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", accessKeyId, accessKeySecret);
    public static DefaultAcsClient client = new DefaultAcsClient(profile);

    //此方法可忽略,为测试方法
    public static void main(String[] args) {
        //若要使用本地图片,需要转换成BASE64编码
        String image_url = "网络图片链接";
        String url = "https://dtplus-cn-shanghai.data.aliyuncs.com/face/detect";
        //请求头,根据官方文档设定参数。type=0时,为网络图片,即image_url为图片链接
        //type-1时,为转成Base64编码的图片,body="{\"type\": "+1+", \"content\": \"" + 图片的String类型编码 + "\"}";
        String body = "{\"type\":\"0\", \"image_url\":\"https://chiyikou.oss-cn-beijing.aliyuncs.com/faceImage/face1.jpg\"}";
        try {
            FaceDetection faceDetection = new FaceDetection();
//            System.out.println(faceDetection.sendPost(url, body, accessKeyId, accessKeySecret));
            System.out.println(faceDetection.detection(body, Direction.UP));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 检测图片是不是
     * @param body
     * @param direction
     * @return   -2: 未知异常  -1:检测失败   0:方向不正确      1:检测成功      2:检测到的人脸不是1个
     */
    public int detection(String body, Direction direction) {
        try {
            JSONObject jsonObject = JSONObject.parseObject(sendPost(detectUrl, body, accessKeyId, accessKeySecret));
            System.out.println("检测结果:" + jsonObject.toString());
            if (jsonObject.getInteger("errno") == 0) {
                if (jsonObject.getInteger("face_num") == 1) {
                    JSONArray jsonArray = jsonObject.getJSONArray("pose");
//                    System.out.println(jsonArray.getFloat(0));
                    //左右角度
                    float x = jsonArray.getFloat(0);
                    //上下角度
                    float y = jsonArray.getFloat(1);
                    System.out.println("x:" + x + "     y:" + y);
                    switch (direction) {
                        case UP:
                            return -faceThreshold < y && y <= 0 && y < x && x < faceThreshold ? 1 : 0;
                        case DOWN:
                            return 0 <= y && y <= faceThreshold && y > x && x > -faceThreshold ? 1 : 0;
                        case LEFT:
                            return -faceThreshold < x && x <= 0 && x < y && y < faceThreshold ? 1 : 0;
                        case RIGHT:
                            return 0 <= x && x <= faceThreshold && x > y && y > -faceThreshold ? 1 : 0;
                        default:
                            return -2;
                    }
                }else {
                    return 2;
                }
            }else {
                System.out.println("检测失败!");
                return -1;
            }

        } catch (Exception e) {
            e.printStackTrace();
            return -2;
        }
    }

//    /**
//     * DetectFace API 人脸检测定位
//     *
//     * @param imageUrl  检测人脸图片的URL
//     */
//    public static void DetectFace(String imageUrl) {
//        CommonsRequest request = new CommonRequest();
//        request.setMethod(MethodType.POST);
//        request.setDomain("face.cn-shanghai.aliyuncs.com");
//        request.setVersion("2018-12-03");
//        request.setAction("DetectFace");
//        request.putBodyParameter("ImageUrl", imageUrl);
////        request.putBodyParameter("Content", "/9j/4AAQSkZJRgABA...");  //检测图片的内容,Base64编码
//        CommonResponse response = null;
//        try {
//            response = client.getCommonResponse(request);
//        } catch (ClientException e) {
//            e.printStackTrace();
//        }
//        System.out.println(response.getData());
//    }


    /*
     * 计算MD5+BASE64
     */
    public String MD5Base64(String s) {
        if (s == null) {
            return null;
        }
        String encodeStr = "";
        byte[] utfBytes = s.getBytes();
        MessageDigest mdTemp;
        try {
            mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(utfBytes);
            byte[] md5Bytes = mdTemp.digest();
            BASE64Encoder b64Encoder = new BASE64Encoder();
            encodeStr = b64Encoder.encode(md5Bytes);
        } catch (Exception e) {
            throw new Error("Failed to generate MD5 : " + e.getMessage());
        }
        return encodeStr;
    }
    /*
     * 计算 HMAC-SHA1
     */
    public String HMACSha1(String data, String key) {
        String result;
        try {
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(data.getBytes());
            result = (new BASE64Encoder()).encode(rawHmac);
        } catch (Exception e) {
            throw new Error("Failed to generate HMAC : " + e.getMessage());
        }
        return result;
    }
    /*
     * 等同于javaScript中的 new Date().toUTCString();
     */
    public String toGMTString(Date date) {
        SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
        df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
        return df.format(date);
    }
    /*
     * 发送POST请求
     */
    public String sendPost(String url, String body, String ak_id, String ak_secret) throws Exception {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        int statusCode = 200;
        try {
            URL realUrl = new URL(url);
            /*
             * http header 参数
             */
            String method = "POST";
            String accept = "application/json";
            String content_type = "application/json";
            String path = realUrl.getFile();
            String date = toGMTString(new Date());
            // 1.对body做MD5+BASE64加密
            String bodyMd5 = MD5Base64(body);
            String stringToSign = method + "\n" + accept + "\n" + bodyMd5 + "\n" + content_type + "\n" + date + "\n"
                    + path;
            // 2.计算 HMAC-SHA1
            String signature = HMACSha1(stringToSign, ak_secret);
            // 3.得到 authorization header
            String authHeader = "Dataplus " + ak_id + ":" + signature;
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", accept);
            conn.setRequestProperty("content-type", content_type);
            conn.setRequestProperty("date", date);
            conn.setRequestProperty("Authorization", authHeader);
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(body);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            statusCode = ((HttpURLConnection)conn).getResponseCode();
            if(statusCode != 200) {
                in = new BufferedReader(new InputStreamReader(((HttpURLConnection)conn).getErrorStream()));
            } else {
                in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            }
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        if (statusCode != 200) {
            throw new IOException("\nHttp StatusCode: "+ statusCode + "\nErrorMessage: " + result);
        }
        return result;
    }
    /*
     * GET请求
     */
    public String sendGet(String url, String ak_id, String ak_secret) throws Exception {
        String result = "";
        BufferedReader in = null;
        int statusCode = 200;
        try {
            URL realUrl = new URL(url);
            /*
             * http header 参数
             */
            String method = "GET";
            String accept = "application/json";
            String content_type = "application/json";
            String path = realUrl.getFile();
            String date = toGMTString(new Date());
            // 1.对body做MD5+BASE64加密
            // String bodyMd5 = MD5Base64(body);
            String stringToSign = method + "\n" + accept + "\n" + "" + "\n" + content_type + "\n" + date + "\n" + path;
            // 2.计算 HMAC-SHA1
            String signature = HMACSha1(stringToSign, ak_secret);
            // 3.得到 authorization header
            String authHeader = "Dataplus " + ak_id + ":" + signature;
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", accept);
            connection.setRequestProperty("content-type", content_type);
            connection.setRequestProperty("date", date);
            connection.setRequestProperty("Authorization", authHeader);
            connection.setRequestProperty("Connection", "keep-alive");
            // 建立实际的连接
            connection.connect();
            // 定义 BufferedReader输入流来读取URL的响应
            statusCode = ((HttpURLConnection)connection).getResponseCode();
            if(statusCode != 200) {
                in = new BufferedReader(new InputStreamReader(((HttpURLConnection)connection).getErrorStream()));
            } else {
                in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            }
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (statusCode != 200) {
            throw new IOException("\nHttp StatusCode: "+ statusCode + "\nErrorMessage: " + result);
        }
        return result;
    }
}

阿里OSS上传图片类

package com.tjkj.tongjiankeji.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.PutObjectResult;
import org.springframework.beans.factory.annotation.Value;

import java.io.InputStream;
import java.util.Date;

/**
 * @Created with qml
 * @author:qml
 * @Date: 2019/8/28
 * @Time: 10:06
 * @Description
 */

public class OSSUtil {
    //从OSS数据库获得
    @Value("${oss.endpoint}")
    private static String endpoint;
    @Value("${oss.keyid}")
    private static String accessKeyId;
    @Value("${oss.keysecret}")
    private static String accessKeySecret;
    @Value("${oss.buckname}")
    private static String bucketName";
    @Value("${oss.facefloder}")
    private static String floder;

    private static String key = "https://chiyikou.oss-cn-beijing.aliyuncs.com/";

    /**
     * 上传单个图片
     * @param filename
     * @param inputStream
     * @return
     */
    public String uploadImageToOSS(String filename, InputStream inputStream) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

        try {

            ossClient.putObject(bucketName, floder + "/" + filename, inputStream);
            String url = key + floder + "/" + filename;
            return url;
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            ossClient.shutdown();
        }
        return null;
    }

    /**
     * 上传多个图片
     * @param filename
     * @param inputStream
     * @return
     */
    public String[] uploadImageToOSS(String[] filename, InputStream[] inputStream) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

        try {
            String []url = new String[filename.length];
            for (int i = 0; i < filename.length; i++) {
                ossClient.putObject(bucketName, floder + "/" +filename[i], inputStream[i]);
                url[i] = key + floder + "/" + filename[i];
            }
            return url;
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            ossClient.shutdown();
        }
        return null;
    }
}

发布了7 篇原创文章 · 获赞 3 · 访问量 8704
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章