1. 程式人生 > >百度AI 人臉檢測

百度AI 人臉檢測

  本文主要說一下百度AI的人臉檢測

 首先進入百度AI官網 登入帳號 點選控制檯

進入控制檯後 點選左側導航欄 人臉識別

 右側建立應用

隨便起個名字 立即建立 

回到剛才的選單 點選管理應用

點選管理應用 可以看到你剛才建立的應用詳情

 

 點選右邊操作欄的管理 可以看到你所有應用的訪問連結 我這個是v3版本的 人臉檢測 因為訪問連結裡面有v3這個字眼 這個是百度定的 疑惑的話請看API 引用自百度AI幫助文件 https://ai.baidu.com/docs#/Face-Detect-V3/top

重點說明 :

注意下圖中 你建立的應用詳情 的關鍵資料 

第一個 :API key 第二個:secret key

這兩個很重要 是用來獲取官網驗證 access_token 沒有這個 你的人臉檢測程式是無法執行的

第三個是下面的API列表 你用到的所有應用的訪問介面的url 都在這裡

前期工作做好以後下面說下具體細節

所謂人臉檢測就是你把一張人物圖片提交給百度人臉檢測的API(介面) 百度AI會智慧的幫你檢測出這張人物照片裡面人物的年齡 顏值 性別 種族 表情 等一系列資料 當然現在的AI檢測的真實性是相對的 種族 性別是非常準確的

至於年齡 顏值 是否帶眼睛 表情 臉型 等其他數值 都是相對準確 這個很好理解 就拿顏值來說 怎麼可能有一種演算法能夠絕對的衡量一個人的美與醜呢 這個美醜都是相對的 就算是數學家 生物學家 他也沒有辦法絕對衡量 所以

演算法也就是相對的 希望大家能夠明白 

因為我申請到的是V3版本的人臉識別 所以下文中的程式碼結構只適用於V3版本 

下面看一下我門需要完成的類

因為我是一個springboot專案 先說service層

 

 一共七個類 全部都有用 一會我會一個個附上程式碼和說明

先說utils包下面的6個工具類

第一個Auth 這個就是獲得官網認證 access_token的類 以下是程式碼

public class Auth {
    /**
     * 獲取許可權token
     *
     */
    public static String getAccessToken() {
        // 官網獲取的 API Key 更新為你註冊的
        String clientId = "xxxxxxxxxxx";
        // 官網獲取的 Secret Key 更新為你註冊的
        String clientSecret = "xxxxxxxxxxxxxxx ";
        return getAuth(clientId, clientSecret);
    }

    /**
     * 獲取API訪問token
     * 該token有效期30天,需要自行管理,當失效時需重新獲取.
     *
     * @param ak - 百度雲官網獲取的 API Key
     * @param sk - 百度雲官網獲取的 Securet Key
     *
     */
    public static String getAuth(String ak, String sk) {
        // 獲取token地址
        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
        String getAccessTokenUrl = authHost
                // 1. grant_type為固定引數
                + "grant_type=client_credentials"
                // 2. 官網獲取的 API Key
                + "&client_id=" + ak
                // 3. 官網獲取的 Secret Key
                + "&client_secret=" + sk;
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 開啟和URL之間的連線
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 獲取所有響應頭欄位
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍歷所有的響應頭欄位
            for (String key : map.keySet()) {
                System.err.println(key + "--->" + map.get(key));
            }
            // 定義 BufferedReader輸入流來讀取URL的響應
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            /**
             * 返回結果示例
             */
            System.err.println("result:" + result);
            JSONObject jsonObject = new JSONObject(result);
            String access_token = jsonObject.getString("access_token");
            return access_token;
        } catch (Exception e) {
            System.err.printf("獲取token失敗!");
            e.printStackTrace(System.err);
        }
        return null;
    }

    public static void main(String[] args) {
        getAccessToken();
    }
}

 通過你建立應用的API key 和 secret key 可以得到access_token 而且說的很明白這個token的生命週期是30天 所以我們在使用他的時候完全可以把

這個token變成一個常量使用 所以上面這個類的程式碼你只需要執行一次 控制檯輸出token後 複製一下 再寫一個類用來儲存常量  我建立的這個類就是utils包下的Constant

constant

public class Constant {
    /* POST_URL引數
    * 你在百度AI官網控制檯建立的應用裡有相關介面的訪問地址
    * 自己開啟看上文中截圖也有說明
    * 此處用到人臉檢測那就把人臉檢測的訪問地址複製過來
    *
    * */
    public static final String POST_URL = "";
    //官網認證的token   
    public static final String ACCESS_TOKEN =
            "此處是你通過上面的類執行獲得的access_token的值";
}

Base64Util  

public class Base64Util {
    private static final char last2byte = (char) Integer.parseInt("00000011", 2);
    private static final char last4byte = (char) Integer.parseInt("00001111", 2);
    private static final char last6byte = (char) Integer.parseInt("00111111", 2);
    private static final char lead6byte = (char) Integer.parseInt("11111100", 2);
    private static final char lead4byte = (char) Integer.parseInt("11110000", 2);
    private static final char lead2byte = (char) Integer.parseInt("11000000", 2);
    private static final char[] encodeTable = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};

    public Base64Util() {
    }
    //通過檔案資訊的位元組資料轉換成base64資料
    public static String encode(byte[] from) {
        StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);
        int num = 0;
        char currentByte = 0;

        int i;
        for (i = 0; i < from.length; ++i) {
            for (num %= 8; num < 8; num += 6) {
                switch (num) {
                    case 0:
                        currentByte = (char) (from[i] & lead6byte);
                        currentByte = (char) (currentByte >>> 2);
                    case 1:
                    case 3:
                    case 5:
                    default:
                        break;
                    case 2:
                        currentByte = (char) (from[i] & last6byte);
                        break;
                    case 4:
                        currentByte = (char) (from[i] & last4byte);
                        currentByte = (char) (currentByte << 2);
                        if (i + 1 < from.length) {
                            currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);
                        }
                        break;
                    case 6:
                        currentByte = (char) (from[i] & last2byte);
                        currentByte = (char) (currentByte << 4);
                        if (i + 1 < from.length) {
                            currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);
                        }
                }

                to.append(encodeTable[currentByte]);
            }
        }

        if (to.length() % 4 != 0) {
            for (i = 4 - to.length() % 4; i > 0; --i) {
                to.append("=");
            }
        }

        return to.toString();
    }
}

  這個類其實就幹一件事 把你識別圖片的位元組資訊轉換成一個base64值 不懂base64的可以百度一下 很簡單 我在這裡就不多費口舌了 希望理解

那既然他是把圖片資訊的位元組轉換成base64 那麼圖片的資訊怎麼轉換成位元組呢 大家都知道 我們首先獲得的檔案資訊 不管是在伺服器上還是前端給我們傳送過來的 其實都是一個file file其實是一個bolb物件 大家可以理解成“流”資訊

所以我們要通過IO 把他解析成位元組物件 也就是byte物件 那下面這個類就是幹這個事情的 

  FileUtil

 

public class FileUtil {

    /**
     * 讀取檔案內容,作為字串返回
     */
    public static String readFileAsString(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        } 

        if (file.length() > 1024 * 1024 * 1024) {
            throw new IOException("File is too large");
        } 

        StringBuilder sb = new StringBuilder((int) (file.length()));
        // 建立位元組輸入流  
        FileInputStream fis = new FileInputStream(filePath);  
        // 建立一個長度為10240的Buffer
        byte[] bbuf = new byte[10240];  
        // 用於儲存實際讀取的位元組數  
        int hasRead = 0;  
        while ( (hasRead = fis.read(bbuf)) > 0 ) {  
            sb.append(new String(bbuf, 0, hasRead));  
        }  
        fis.close();  
        return sb.toString();
    }

    /**
     * 根據檔案路徑讀取byte[] 陣列
     */
    public static byte[] readFileByBytes(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        } else {
            ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
            BufferedInputStream in = null;

            try {
                in = new BufferedInputStream(new FileInputStream(file));
                short bufSize = 1024;
                byte[] buffer = new byte[bufSize];
                int len1;
                while (-1 != (len1 = in.read(buffer, 0, bufSize))) {
                    bos.write(buffer, 0, len1);
                }

                byte[] var7 = bos.toByteArray();
                return var7;
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException var14) {
                    var14.printStackTrace();
                }

                bos.close();
            }
        }
    }
}

  兩個方法 一個讀取檔案 也就是你檔案上傳後在伺服器的路徑地址 通過這個路徑地址 把檔案轉成string另一個方法轉換成byte陣列

GsonUtil

/**
 * Json工具類.gson是谷歌提供的一個工具類 很強大 號稱可以解決所有物件之間的轉換
 */
public class GsonUtils {
    private static Gson gson = new GsonBuilder().create();
    //物件轉json
    public static String toJson(Object value) {
        return gson.toJson(value);
    }
    //json物件轉實體類
    public static <T> T fromJson(String json, Class<T> classOfT) throws JsonParseException {
        return gson.fromJson(json, classOfT);
    }
    //json物件轉各種資料型別 例如 map list
    public static <T> T fromJson(String json, Type typeOfT) throws JsonParseException {
        return (T) gson.fromJson(json, typeOfT);
    }
}

 HttpUtil

/**
 * http 工具類
 */
public class HttpUtil {

    public static String post(String requestUrl, String accessToken, String params)
            throws Exception {
        String contentType = "application/x-www-form-urlencoded";
        return HttpUtil.post(requestUrl, accessToken, contentType, params);
    }

    public static String post(String requestUrl, String accessToken, String contentType, String params)
            throws Exception {
        String encoding = "UTF-8";
        if (requestUrl.contains("nlp")) {
            encoding = "GBK";
        }
        return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding);
    }

    public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding)
            throws Exception {
        String url = requestUrl + "?access_token=" + accessToken;
        return HttpUtil.postGeneralUrl(url, contentType, params, encoding);
    }

    public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding)
            throws Exception {
        URL url = new URL(generalUrl);
        // 開啟和URL之間的連線
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        // 設定通用的請求屬性
        connection.setRequestProperty("Content-Type", contentType);
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setUseCaches(false);
        connection.setDoOutput(true);
        connection.setDoInput(true);

        // 得到請求的輸出流物件
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        out.write(params.getBytes(encoding));
        out.flush();
        out.close();

        // 建立實際的連線
        connection.connect();
        // 獲取所有響應頭欄位
        Map<String, List<String>> headers = connection.getHeaderFields();
        // 遍歷所有的響應頭欄位
        for (String key : headers.keySet()) {
            System.err.println(key + "--->" + headers.get(key));
        }
        // 定義 BufferedReader輸入流來讀取URL的響應
        BufferedReader in = null;
        in = new BufferedReader(
                new InputStreamReader(connection.getInputStream(), encoding));
        String result = "";
        String getLine;
        while ((getLine = in.readLine()) != null) {
            result += getLine;
        }
        in.close();
        System.err.println("result:" + result);
        return result;
    }
}

    這個類我就不多說了 主要是用在提交請求的 因為你是java程式 你最終的人臉檢測是通過百度AI提供的API進行檢測的 所以就意味著你一定會向百度提交http請求 當然你還有附帶相應的引數 那就肯定是post請求了

6個工具類說完 下面說 業務類 這個業務類和我們平時寫的service層的業務類還是有區別的 因為他的方法必須是static 也就是單執行緒的 也就意味著你不需要通過介面實現 看程式碼

FaceDetect

public class FaceDetect {
    public static FaceDetectVo detect(String url,String imageUrl,String accessToken) {
        try {
            //通過圖片路徑 把圖片資料轉成位元組
            byte [] imageDate = FileUtil.readFileByBytes(imageUrl);
            //把位元組轉成base64格式
            String imageBase64 = Base64Util.encode(imageDate);
            Map<String, Object> map = new HashMap<>();
            /* image 引數 圖片的BASE64值 上面我通過工具類“Base64Util”轉好了
             *  官網給出的API中說image的引數還可以是其他兩種
             *  URL:圖片的 URL地址( 可能由於網路等原因導致下載圖片時間過長);
             *  FACE_TOKEN: 人臉圖片的唯一標識,呼叫人臉檢測介面時,
             *  會為每個人臉圖片賦予一個唯一的FACE_TOKEN,同一張圖片多次檢測得到的FACE_TOKEN是同一個。
             *  也就是說map集合中 “image”這個key的值 如果是圖片的base64值的話 你新增的“image_type”這個
             *  引數的值應該是“BASE64”。
             *  如果“iamge”的值是一個地址例如:你圖片存放的伺服器地址“http://xxx.com/xxx.jpg”
             *  那"image_type"的值就應該是“URL”
             *  如果“iamge”的值是一個FACE_TOKEN例如:“027d8308a2ec665acb1bdf63e513bcb9”
             *  那"image_type"的值就應該是“FACE_TOKEN”
             *  image_type這個引數的值是固定的寫法 只能三個選一個“BASE64”,“URL”,“FACE_TOKEN”
             **/
            map.put("image", imageBase64);
            map.put("image_type", "BASE64");
            /*
             *  第三個引數“face_field”,也就是返回值
             *  這個引數的值string型別 以逗號隔開
             *  可以選擇返回aga 年齡 beauty 顏值 等 具體返回引數
             *  可以參照官方API https://ai.baidu.com/docs#/Face-Detect-V3/top
             *
             **/
            map.put("face_field", "age,beauty,expression,gender,glasses,race,face_type");
            //GsonUtils map轉json 用於請求入參
            String param = GsonUtils.toJson(map);
            /*
              post請求 url官網控制檯自己建立應用關於人臉檢測的訪問連結地址
              accessToken 這個是官網給你的一個認證標識
              contentType 請求頭
              param 引數
            */

            String result = HttpUtil.post(url, accessToken, "application/json", param);
            //返回值“result”是String型別的,其實就是一個json串 我自己寫了一個vo 通過GsonUtils把json串轉成對映實體類
            FaceDetectVo faceDetectVo = new FaceDetectVo();
            faceDetectVo = GsonUtils.fromJson(result,faceDetectVo.getClass());
            return faceDetectVo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
  

 

 註釋很詳細 只說一塊程式碼 

faceDetectVo = GsonUtils.fromJson(result,faceDetectVo.getClass());

這個是我通過GsonUtil 把官網檢測的返回結果轉換成了實體類物件 所以我要寫一個實體類

FaceDetectVo

public class FaceDetectVo {


    private int error_code;
    private String error_msg;
    private ResultBean result;

    public int getError_code() {
        return error_code;
    }

    public void setError_code(int error_code) {
        this.error_code = error_code;
    }

    public String getError_msg() {
        return error_msg;
    }

    public void setError_msg(String error_msg) {
        this.error_msg = error_msg;
    }

    public ResultBean getResult() {
        return result;
    }

    public void setResult(ResultBean result) {
        this.result = result;
    }

    public FaceDetectVo() {
    }

    public FaceDetectVo(int error_code, String error_msg, ResultBean result) {
        this.error_code = error_code;
        this.error_msg = error_msg;
        this.result = result;
    }

    @Override
    public String toString() {
        return "FaceDetectVo{" +
                "error_code=" + error_code +
                ", error_msg='" + error_msg + '\'' +
                ", result=" + result +
                '}';
    }

    public static class ResultBean {

        private List<FaceListBean> face_list;

        public List<FaceListBean> getFace_list() {
            return face_list;
        }

        public void setFace_list(List<FaceListBean> face_list) {
            this.face_list = face_list;
        }

        public ResultBean() {
        }

        public static class FaceListBean {

            private int age;
            private double beauty;
            private ExpressionBean expression;
            private GenderBean gender;
            private GlassesBean glasses;
            private RaceBean race;
            private FaceTypeBean face_type;

            public int getAge() {
                return age;
            }

            public void setAge(int age) {
                this.age = age;
            }

            public double getBeauty() {
                return beauty;
            }

            public void setBeauty(double beauty) {
                this.beauty = beauty;
            }

            public ExpressionBean getExpression() {
                return expression;
            }

            public void setExpression(ExpressionBean expression) {
                this.expression = expression;
            }

            public GenderBean getGender() {
                return gender;
            }

            public void setGender(GenderBean gender) {
                this.gender = gender;
            }

            public GlassesBean getGlasses() {
                return glasses;
            }

            public void setGlasses(GlassesBean glasses) {
                this.glasses = glasses;
            }

            public RaceBean getRace() {
                return race;
            }

            public void setRace(RaceBean race) {
                this.race = race;
            }

            public FaceTypeBean getFace_type() {
                return face_type;
            }

            public void setFace_type(FaceTypeBean face_type) {
                this.face_type = face_type;
            }

            public FaceListBean() {
            }


            public static class ExpressionBean {

                private String type;
                private double probability;

                public String getType() {
                    return type;
                }

                public void setType(String type) {
                    this.type = type;
                }

                public double getProbability() {
                    return probability;
                }

                public void setProbability(double probability) {
                    this.probability = probability;
                }

                public ExpressionBean() {
                }
            }

            public static class GenderBean {

                private String type;
                private double probability;

                public String getType() {
                    return type;
                }

                public void setType(String type) {
                    this.type = type;
                }

                public double getProbability() {
                    return probability;
                }

                public void setProbability(double probability) {
                    this.probability = probability;
                }

                public GenderBean() {
                }
            }

            public static class GlassesBean {

                private String type;
                private double probability;

                public String getType() {
                    return type;
                }

                public void setType(String type) {
                    this.type = type;
                }

                public double getProbability() {
                    return probability;
                }

                public void setProbability(double probability) {
                    this.probability = probability;
                }

                public GlassesBean() {
                }
            }

            public static class RaceBean {

                private String type;
                private double probability;

                public String getType() {
                    return type;
                }

                public void setType(String type) {
                    this.type = type;
                }

                public double getProbability() {
                    return probability;
                }

                public void setProbability(double probability) {
                    this.probability = probability;
                }

                public RaceBean() {
                }
            }

            public static class FaceTypeBean {

                private String type;
                private double probability;

                public String getType() {
                    return type;
                }

                public void setType(String type) {
                    this.type = type;
                }

                public double getProbability() {
                    return probability;
                }

                public void setProbability(double probability) {
                    this.probability = probability;
                }

                public FaceTypeBean() {
                }
            }
        }
    }
}

這個vo有很多內部類 都應該有無參構造 和 封裝 看一下官網的返回值

result:{"error_code":0,"error_msg":"SUCCESS","log_id":3584051565053,
     "timestamp":1541095172,"cached":0,
     "result":{"face_num":1,
               "face_list":[{
               "face_token":"c7352123456456454c1971a66986fcc",
               "location":{"left":206.3209229,"top":280.6053467,
                            "width":279,"height":272,"rotation":-14},
                            "face_probability":0.9146046638,
                            "angle":{"yaw":6.934440613,
                                     "pitch":15.56725311,"roll":-14.03364563},
                                     "age":45,"beauty":48.68906021,
                                     "expression":{"type":"none",
                                    "probability":0.857055068},
                                    "gender":{"type":"male",
                                    "probability":0.9945344925},
                                    "glasses":{"type":"common",
                                    "probability":0.9993425012},
                                    "race":{"type":"black","probability":0.9982160926},
               "face_type":{"type":"human","probability":0.9997557402}}]}}

  

這是一個複雜的json串 也是好幾層 所以我的vo 裡面有好多內部類對映json串裡面的層次 通過GsonUtil可以把這個複雜的json串轉換賦值於我的vo 用於controller層返回給前端使用

下面看controller層

@RestController
@RequestMapping("api/recognition")
public class FaceDetectController {
    @Autowired
    UploadService uploadService;
    @RequestMapping("/faceDetect")
    public FaceDetectVo faceDetect(@RequestParam("file") MultipartFile file){
        FaceDetectVo faceDetectVo = new FaceDetectVo();
        try {
            System.out.println(file);
            //檔案上傳至伺服器
            UploadVo uploadVo = uploadService.upload(file);
            if(StringUtils.isNotBlank(uploadVo.getUploadUrl())){
                //呼叫service層的人臉檢測方法
              faceDetectVo =  FaceDetect.detect(Constant.POST_URL,uploadVo.getUploadUrl(),Constant.ACCESS_TOKEN);
            }
            return  faceDetectVo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  faceDetectVo;
    }
}

  很正常的controller寫法 裡面有一個方法要說一下

uoloadService.upload方法 這就是個上傳方法 我下面貼程式碼:

UploadService

public interface UploadService {
UploadVo upload(MultipartFile file) throws Exception;
}

UploadServiceImpl  

@Service
public class UploadServiceImpl implements UploadService {
    /*
     * @Author huyuqiang
     * @Description 檔案上傳
     * @Date 11:09
     * @Param file上傳檔案流
     * @return
     **/
    @Override
    public UploadVo upload(MultipartFile file) throws Exception {
        UploadVo uploadVo = new UploadVo();
        if (!file.isEmpty()) {
            String fileName = file.getOriginalFilename();
            String fileType = fileName.substring(fileName.lastIndexOf(".")+1);
            long fileSize = file.getSize();
            String Path = "D:/javaspace/tomcatPath";
            File packageFile = new File(Path);
            if (!packageFile.exists()) {
                packageFile.mkdir();
            }
            File targetFile = new File(Path + "/" + fileName);
            file.transferTo(targetFile);
            uploadVo.setBeginFileName(fileName);
            uploadVo.setLastFileName(fileName);
            uploadVo.setFileType(fileType);
            uploadVo.setFileSize(BytesUtils.getPrintSize(fileSize));
            uploadVo.setUploadUrl(targetFile.toString());
            uploadVo.setResult("上傳成功");
            return uploadVo;
        } else {
            uploadVo.setResult(String.valueOf(ErrorMessageConstant.ERROR_CODE_10004));
            return uploadVo;
        }
    }


}

UploadVo  

public class UploadVo {
    //上傳結果
    private String result;
    //後端獲得檔名
    private String beginFileName;
    //最終上傳檔名
    private String lastFileName;
    //檔案型別
    private String FileType;
    //檔案大小
    private String fileSize;
    //檔案上傳的地址
    private String uploadUrl;

    public UploadVo() {
    }

    public UploadVo(String result, String beginFileName, String lastFileName, String fileType, String fileSize, String uploadUrl) {
        this.result = result;
        this.beginFileName = beginFileName;
        this.lastFileName = lastFileName;
        FileType = fileType;
        this.fileSize = fileSize;
        this.uploadUrl = uploadUrl;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getBeginFileName() {
        return beginFileName;
    }

    public void setBeginFileName(String beginFileName) {
        this.beginFileName = beginFileName;
    }

    public String getLastFileName() {
        return lastFileName;
    }

    public void setLastFileName(String lastFileName) {
        this.lastFileName = lastFileName;
    }

    public String getFileType() {
        return FileType;
    }

    public void setFileType(String fileType) {
        FileType = fileType;
    }

    public String getFileSize() {
        return fileSize;
    }

    public void setFileSize(String fileSize) {
        this.fileSize = fileSize;
    }

    public String getUploadUrl() {
        return uploadUrl;
    }

    public void setUploadUrl(String uploadUrl) {
        this.uploadUrl = uploadUrl;
    }

    @Override
    public String toString() {
        return "UploadVo{" +
                "result='" + result + '\'' +
                ", beginFileName='" + beginFileName + '\'' +
                ", lastFileName='" + lastFileName + '\'' +
                ", FileType='" + FileType + '\'' +
                ", fileSize='" + fileSize + '\'' +
                ", uploadUrl='" + uploadUrl + '\'' +
                '}';
    }
}
下面是前端程式碼:vue寫的 一個是上傳圖片識別 一個是呼叫攝像頭識別 
<template>
    <div>
        <div class="crumbs">
            <el-breadcrumb separator="/">
                <el-breadcrumb-item><i class="el-icon-date"></i> 智慧識別</el-breadcrumb-item>
                <el-breadcrumb-item>照片識別</el-breadcrumb-item>
            </el-breadcrumb>
        </div>
        <div class="container">
            <div class="container-left">
                <el-upload
                class="avatar-uploader"
                action="http://localhost:8080/api/recognition/faceDetect"
                :show-file-list="false"
                :on-success="onSuccess"
                :before-upload="beforeAvatarUpload">
                <img v-if="imageUrl" :src="imageUrl" class="avatar">
                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
              </el-upload>
            </div>
            <div class="container-right">
                <el-form :model="resultForm" status-icon  ref="resultForm" label-width="100px" class="demo-ruleForm">
                    <el-form-item label="人物型別" prop="faceType">
                        <el-input type="text" v-if="resultForm.faceType=='human'" value="真實人物"></el-input>
                        <el-input type="text" v-if="resultForm.faceType=='cartoon'" value="卡通人物"></el-input>
                    </el-form-item>
                    <el-form-item label="年齡" prop="age">
                        <el-input type="text" v-if="resultForm.age!=''" v-model="resultForm.age"></el-input>
                    </el-form-item>
                    <el-form-item label="性別" prop="gender">
                        <el-input type="text" v-if="resultForm.gender=='male'" value="男"></el-input>
                        <el-input type="text" v-if="resultForm.gender=='female'" value="女"></el-input>
                    </el-form-item>
                    <el-form-item label="人種" prop="race">
                            <el-input type="text" v-if="resultForm.race=='yellow'" value="黃種人"></el-input>
                            <el-input type="text" v-if="resultForm.race=='white'" value="白種人"></el-input>
                            <el-input type="text" v-if="resultForm.race=='black'" value="黑種人"></el-input>
                            <el-input type="text" v-if="resultForm.race=='arabs'" value="阿拉伯人"></el-input>
                    </el-form-item>
                    <el-form-item label="戴眼鏡" prop="glasses">
                            <el-input type="text" v-if="resultForm.glasses=='none'" value="無眼鏡"></el-input>
                            <el-input type="text" v-if="resultForm.glasses=='common'" value="普通眼鏡"></el-input>
                            <el-input type="text" v-if="resultForm.glasses=='sun'" value="墨鏡"></el-input>
                    </el-form-item>
                    <el-form-item label="表情" prop="expression">
                        <el-input type="text" v-if="resultForm.expression=='none'" value="不笑"></el-input>
                        <el-input type="text" v-if="resultForm.expression=='smile'" value="微笑"></el-input>
                        <el-input type="text" v-if="resultForm.expression=='laugh'" value="大笑"></el-input>
                    </el-form-item>
                    <el-form-item label="顏值" prop="beauty">
                        <el-input type="text" v-if="resultForm.beauty<=20&&resultForm.beauty>0" value="奇醜無比"></el-input>
                        <el-input type="text" v-if="resultForm.beauty>20&&resultForm.beauty<=40" value="醜陋"></el-input>
                        <el-input type="text" v-if="resultForm.beauty>40&&resultForm.beauty<=70" value="俊美"></el-input>
                        <el-input type="text" v-if="resultForm.beauty>70" value="絕美無比"></el-input>
                    </el-form-item>
                </el-form>
            </div>
        </div>
    </div>
</template>

<script>
    import VueCropper  from 'vue-cropperjs';
    import axios from 'axios';
    export default {
        name: 'upload',
        data() {
            return {
                imageUrl: '',
                resultForm:{
                    //人物型別
                    faceType:'',
                    //年齡
                    age:'',
                    //性別
                    gender:'',
                    //人種
                    race:'',
                    //戴眼鏡
                    glasses:'',
                    //表情
                    expression:'',
                    //顏值
                    beauty:''
                }
            };
        },
        methods: {
            onSuccess(response, file) {
            this.imageUrl = URL.createObjectURL(file.raw);
            console.log(response);
            if(response.error_code==0){
                let faceDetect = response.result.face_list;
                if(faceDetect!=null){
                    for(let i =0;i<faceDetect.length;i++){
                        this.resultForm.faceType = faceDetect[i].face_type.type;
                        this.resultForm.age = faceDetect[i].age;
                        this.resultForm.gender = faceDetect[i].gender.type;
                        this.resultForm.race = faceDetect[i].race.type;
                        this.resultForm.glasses = faceDetect[i].glasses.type;
                        this.resultForm.expression = faceDetect[i].expression.type;
                        this.resultForm.beauty = faceDetect[i].beauty;    
                    }
                }
            }else{
                this.$message("圖片人物形象不明顯,無法分辨");
            }
          
            },
            beforeAvatarUpload(file) {
                const isJPG = file.type === 'image/jpeg';
                const isLt2M = file.size / 1024 / 1024 < 2;
                if (!isJPG) {
                    this.$message.error('上傳頭像圖片只能是 JPG 格式!');
                }
                if (!isLt2M) {
                    this.$message.error('上傳頭像圖片大小不能超過 2MB!');
                }
                return isJPG && isLt2M;
            }
        }
    }
</script>
<style>
        .avatar-uploader .el-upload {
          border: 1px dashed #d9d9d9;
          border-radius: 6px;
          width: 600px;
          height: 600px;
          cursor: pointer;
          position: relative;
          overflow: hidden;
        }
        .avatar-uploader .el-upload:hover {
          border-color: #409EFF;
        }
        .avatar-uploader-icon {
          font-size: 28px;
          color: #8c939d;
          width: 178px;
          height: 178px;
          line-height: 600px;
          text-align: center;
        }
        .avatar {
          width: 600px;
          height: 600px;
          display: block;
        }
</style>

  攝像頭開啟識別:

<template>
<div>  
    <div class="crumbs">
        <el-breadcrumb separator="/">
            <el-breadcrumb-item><i class="el-icon-date"></i> 智慧識別</el-breadcrumb-item>
            <el-breadcrumb-item>相機識別</el-breadcrumb-item>
        </el-breadcrumb>
    </div>
    <div class="container">
            <div class="container-left">
                <video ref="video" width="600" height="600" autoplay></video>       
                <button ref="capture" @click="faceDetect">智慧辨別</button>        
                <canvas ref="canvas" id="convas" width="320" height="320" style="visibility:hidden">
                </canvas> 
            </div>
            <div class="container-right">
                <el-form :model="resultForm" status-icon  ref="resultForm" label-width="100px" class="demo-ruleForm">
                    <el-form-item label="人物型別" prop="faceType">
                        <el-input type="text" v-if="resultForm.faceType=='human'" value="真實人物"></el-input>
                        <el-input type="text" v-if="resultForm.faceType=='cartoon'" value="卡通人物"></el-input>
                    </el-form-item>
                    <el-form-item label="年齡" prop="age">
                        <el-input type="text" v-if="resultForm.age!=''" v-model="resultForm.age"></el-input>
                    </el-form-item>
                    <el-form-item label="性別" prop="gender">
                        <el-input type="text" v-if="resultForm.gender=='male'" value="男"></el-input>
                        <el-input type="text" v-if="resultForm.gender=='female'" value="女"></el-input>
                    </el-form-item>
                    <el-form-item label="人種" prop="race">
                            <el-input type="text" v-if="resultForm.race=='yellow'" value="黃種人"></el-input>
                            <el-input type="text" v-if="resultForm.race=='white'" value="白種人"></el-input>
                            <el-input type="text" v-if="resultForm.race=='black'" value="黑種人"></el-input>
                            <el-input type="text" v-if="resultForm.race=='arabs'" value="阿拉伯人"></el-input>
                    </el-form-item>
                    <el-form-item label="戴眼鏡" prop="glasses">
                            <el-input type="text" v-if="resultForm.glasses=='none'" value="無眼鏡"></el-input>
                            <el-input type="text" v-if="resultForm.glasses=='common'" value="普通眼鏡"></el-input>
                            <el-input type="text" v-if="resultForm.glasses=='sun'" value="墨鏡"></el-input>
                    </el-form-item>
                    <el-form-item label="表情" prop="expression">
                        <el-input type="text" v-if="resultForm.expression=='none'" value="不笑"></el-input>
                        <el-input type="text" v-if="resultForm.expression=='smile'" value="微笑"></el-input>
                        <el-input type="text" v-if="resultForm.expression=='laugh'" value="大笑"></el-input>
                    </el-form-item>
                    <el-form-item label="顏值" prop="beauty">
                        <el-input type="text" v-if="resultForm.beauty<=20&&resultForm.beauty>0" value="奇醜無比"></el-input>
                        <el-input type="text" v-if="resultForm.beauty>20&&resultForm.beauty<=40" value="醜陋"></el-input>
                        <el-input type="text" v-if="resultForm.beauty>40&&resultForm.beauty<=70" value="俊美"></el-input>
                        <el-input type="text" v-if="resultForm.beauty>70" value="絕美無比"></el-input>
                    </el-form-item>
                </el-form>
            </div>
    </div>     
</div>
 </template>
<script>  
import axios from 'axios'
    export default{
        data(){
            return{
                resultForm:{
                    //人物型別
                    faceType:'',
                    //年齡
                    age:'',
                    //性別
                    gender:'',
                    //人種
                    race:'',
                    //戴眼鏡
                    glasses:'',
                    //表情
                    expression:'',
                    //顏值
                    beauty:''
                }
            }
        },mounted() {
            this.useCamera();
        },
        methods:{
            //訪問使用者媒體裝置的相容方法
            getUserMedia(constraints, success, error) {
                if (navigator.mediaDevices.getUserMedia) {
                    //最新的標準API
                    navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
                } else if (navigator.webkitGetUserMedia) {
                    //webkit核心瀏覽器
                    navigator.webkitGetUserMedia(constraints,success, error)
                } else if (navigator.mozGetUserMedia) {
                    //firfox瀏覽器
                    navigator.mozGetUserMedia(constraints, success, error);
                } else if (navigator.getUserMedia) {
                    //舊版API
                    navigator.getUserMedia(constraints, success, error);
                }
            },
            //攝像頭訪問成功
            success(stream) {
                //相容webkit核心瀏覽器
                let CompatibleURL = window.URL || window.webkitURL;
                //將視訊流設定為video元素的源
                console.log(stream);
                //video.src = CompatibleURL.createObjectURL(stream);
                let video = this.$refs.video;
                video.srcObject = stream;
                video.play();
            },
            //攝像頭訪問失敗
            error(error) {
                 console.log(`訪問使用者媒體裝置失敗${error.name}, ${error.message}`);
            },
            //呼叫攝像頭進行訪問
            useCamera(){
                let video = this.$refs.video;
                if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia 
                || navigator.mozGetUserMedia) {
                    //呼叫使用者媒體裝置, 訪問攝像頭
                    this.getUserMedia({video : {width: 600, height: 600}}, this.success, this.error);
                    } else {
                    alert('不支援訪問使用者媒體');
                    }
            },
            //獲取攝像頭圖片提交後臺驗證
            faceDetect(){
                let canvas = this.$refs.canvas;
                let context = canvas.getContext('2d');
                let video = this.$refs.video;
                context.drawImage(video, 0, 0, 480, 320);
                let base64Data = convas.toDataURL('image/jpeg');
                let blob = this.getDataURItoBlob(base64Data,'abcd.jpg');
                let params = new FormData();
                params.append('file',blob);
                axios.post('http://localhost:8080/api/recognition/faceDetect',params,
                    {
                        headers:{
                        'Content-Type':'multipart/form-data'
                        }
                    }
                    ).then((response)=>{
                        console.log(response);
                        if(response.data.error_code==0){
                            let faceDetect = response.data.result.face_list;
                            if(faceDetect!=null){
                                for(let i =0;i<faceDetect.length;i++){
                                    this.resultForm.faceType = faceDetect[i].face_type.type;
                                    this.resultForm.age = faceDetect[i].age;
                                    this.resultForm.gender = faceDetect[i].gender.type;
                                    this.resultForm.race = faceDetect[i].race.type;
                                    this.resultForm.glasses = faceDetect[i].glasses.type;
                                    this.resultForm.expression = faceDetect[i].expression.type;
                                    this.resultForm.beauty = faceDetect[i].beauty;    
                                }
                            }   
                        }else{
                             this.$message("圖片人物形象不明顯,無法分辨");
                        }    
                    }).catch((response)=>{
                            this.$message("圖片人物形象不明顯,無法分辨");
                    });
            },
            //把canvas標籤獲取的base64物件轉換成bolb物件 也就是file物件
            getDataURItoBlob (base64Data,fileName) {
                let arr = base64Data.split(','), mime = arr[0].match(/:(.*?);/)[1],
                    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
                while(n--){
                    u8arr[n] = bstr.charCodeAt(n);
                }
                return new File([u8arr], fileName, {type:mime});
            }
        }
    }
</script>

  執行結果:

 關於人臉檢測 就暫時說這麼多 後續我會做一些實物識別 同聲翻譯之類的 當然這都建立在百度AI的基礎上 感謝百度 !!!!