阿里人臉檢測實踐以及阿里雲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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章