1. 程式人生 > 其它 >百度AI人臉檢測——解析JSON 資料格式

百度AI人臉檢測——解析JSON 資料格式

1.瞭解一下

通常情況下,每個需要訪問網路的應用程式都會有一個自己的伺服器,我們可以向伺服器提交資料,也可以從伺服器上獲取資料。不過這個時候就出現了一個問題,這些資料到底要以什麼樣的格式在網路上傳輸呢?

隨便傳遞一段文字肯定是不行的,因為另一方根本就不會知道這段文字的用途是什麼。因此,一般都會在網路上傳輸一些格式化後的資料,這種資料會有一定的結構規格和語義,當另一方收到資料訊息之後就可以按照相同的結構規格進行解析,從而取出他想要的那部分內容。

在網路上傳輸資料時最常用的格式有兩種:XML JSON。相比 XML,JSON的主要優勢在於它的體積更小,在網路上傳輸的時候可以更省流量。因此,本節重點講解JSON格式資料的解析。

JSON(JavaScript Object Notation)是一種輕量級的資料交換格式,它可以將JavaScript物件中表示的一組資料轉換為字串,然後就可以在網路或者程式之間輕鬆地傳遞這個字串,並在需要的時候將它還原為各程式語言所支援的資料格式。··········JSON的建構主要有以下兩種結構在;

(1)“名稱/值"對的集合。不同的語言中,它被理解為對像(object).記錄(record)、結構(struct)、字典(dictionary)、雜湊表(hash table),有飢列表(keyed list)或者關聯陣列(association array)。

  物件是一個無序的“名稱/值"對的集合。一個物件以|“{”開始,以“}”結束。每個“名稱”後跟一個“:”,多個“名稱/值"之間使用“,”來分隔。例:

{" id":1,"name” : "zhangsan", "sex”:"M"","age":19}

 

(2)值的有序列表。在大部分語言中,它被理解為陣列(array).

陣列是值(value)的有序集會。一個數組以“[”開始,以“]”結束。值之間使用“,”分隔。例加,

[ { "id":1,"name" :"zhangsan", "sex":"M","age":19},

  {"id":2,"nane": "lisi" , "sex" :"F" , "age":18},

  {"id":3,"name" : "wangwu" , "sex": "M", "age":20} ]

2.如何解析

解析JSON格式的資料有很多種方法,可以使用官方提供的JSONObject,也可以使用Google的開源庫GSON,還有一些第三方的開源庫Jackson,FastJSON。

這裡用FastJSON來解析百度AI返回的JSON格式資料。

   首先在build.gradle下引入依賴:

 

implementation 'com.alibaba:fastjson:1.2.32'

現在我們看看什麼是fastjson?
fastjson 是一個性能極好的用 Java 語言實現的 JSON 解析器和生成器,來自阿里巴巴的工程師開發。

主要特點:

  • 快速FAST (比其它任何基於Java的解析器和生成器更快,包括jackson)
  • 強大(支援普通JDK類包括任意Java Bean Class、Collection、Map、Date或enum)
  • 零依賴(沒有依賴其它任何類庫除了JDK)

  (1).生成Json

JavaBean,List<JavaBean>,List<String>,List<Map<String,Object>>

String jsonString = JSON.toJSONString(obj); 

(2).解析Json
1.JavaBean
Class class= JSON.parseObject(jsonString, Class.class); 

2.List<JavaBean>
List<Class> class="JSON".parseArray((jsonString, Class.class); 

3.List<String>
List<String> listString = JSON.parseArray(jsonString, String.class); 

4.List<Map<String,Object>>
List<Map<String, Object>> listMap = JSON.parseObject(jsonString, new TypeReference<List<Map<String,Object>>>(){}); 
這裡我們選擇JavaBean的方式解析。

先來看看百度AI返回的資料

 

 

 注意我這裡的map.put("face_field", "age,beauty,landmark");因為我不需要其他的,就只需要這三個。

將上面的資料排版一下:

 

 現在可以清晰地看見這段資料的結構了,那我們怎麼解析呢?

首先我們需要定義一個FaceDetectBean,用於將返回的JSON字串轉換為一個Java類物件。

 

public class FaceDetectBean {
public FaceDetectBean(){

}

public FaceDetectBean(int error_code, String error_msg, int log_id, int timestamp, int cached, ResultClass result) {
this.error_code = error_code;
this.error_msg = error_msg;
this.log_id = log_id;
this.timestamp = timestamp;
this.cached = cached;
this.result = result;
}

/**
"error_code":0,
"error_msg":"SUCCESS",
"log_id":2473751407,
"timestamp":1646563273,
"cached":0,
"result":{
*/
private int error_code;
private String error_msg;
private int log_id;
private int timestamp;
private int cached;
private ResultClass 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 int getLog_id() {
return log_id;
}

public void setLog_id(int log_id) {
this.log_id = log_id;
}

public int getTimestamp() {
return timestamp;
}

public void setTimestamp(int timestamp) {
this.timestamp = timestamp;
}

public int getCached() {
return cached;
}

public void setCached(int cached) {
this.cached = cached;
}

public ResultClass getResult() {
return result;
}

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

}

 

對比一下:

 

 是按照返回的內容寫的FaceDetectBean的屬性。

而最後的private ResultClass result; 是什麼?

public class ResultClass {
/*
"face_num":1,
"face_list":[]
*/
private int face_num;
private List<face_list_bean> face_list;

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

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

public int getFace_num() {
return face_num;
}

public void setFace_num(int face_num) {
this.face_num = face_num;
}

}

對照一下:

 

 那 List<face_list_bean>是什麼呢?

 

public class face_list_bean{
/*
"face_token":"8ad51d2c97a022efa8ffb5f789fc9658",
"location":{
"left":99.57,
"top":112.13,
"width":258,
"height":230,
"rotation":-4 },
"face_probability":1,
"angle":{
"yaw":-4.94,
"pitch":22.63,
"roll":-6.86 },
"age":22,
"beauty":78.24,
"landmark":[
{"x":172.24,"y":148.64},
{"x":280.38,"y":140.28},
{"x":229.78,"y":222.21},
{"x":235.31,"y":264.27} ],
"landmark72":[{....}]
*/
private String face_token;
private locationbean location;
private int face_probability;
private anglebean angle;
private int age;
private double beauty;
private List<landmarkbean> landmark;
private List<landmark72bean> landmark72;

public String getFace_token() {
return face_token;
}

public void setFace_token(String face_token) {
this.face_token = face_token;
}

public locationbean getLocation() {
return location;
}

public void setLocation(locationbean location) {
this.location = location;
}

public int getFace_probability() {
return face_probability;
}

public void setFace_probability(int face_probability) {
this.face_probability = face_probability;
}

public anglebean getAngle() {
return angle;
}

public void setAngle(anglebean angle) {
this.angle = angle;
}

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 List<landmarkbean> getLandmark() {
return landmark;
}

public void setLandmark(List<landmarkbean> landmark) {
this.landmark = landmark;
}

public List<landmark72bean> getLandmark72() {
return landmark72;
}

public void setLandmark72(List<landmark72bean> landmark72) {
this.landmark72 = landmark72;
}

}

 

 

 接著,我們對照一下:

 

 OK,locationbean,anglebean,List<landmarkbean>,List<landmark72bean>這些都是什麼?

應該不用一一解釋了吧,我把程式碼放上來。

 

public class locationbean {
/*
"location":{
"left":99.57,
"top":112.13,
"width":258,
"height":230,
"rotation":-4 },

*/
private double left;
private double top;
private double width;
private double height;
private double rotation;

public double getLeft() {
return left;
}

public void setLeft(double left) {
this.left = left;
}

public double getTop() {
return top;
}

public void setTop(double top) {
this.top = top;
}

public double getWidth() {
return width;
}

public void setWidth(double width) {
this.width = width;
}

public double getHeight() {
return height;
}

public void setHeight(double height) {
this.height = height;
}

public double getRotation() {
return rotation;
}

public void setRotation(double rotation) {
this.rotation = rotation;
}

}

public class anglebean {
/*
"angle":{
"yaw":-4.94,
"pitch":22.63,
"roll":-6.86 },
*/
private double yaw;
private double pitch;
private double roll;

public double getYaw() {
return yaw;
}

public void setYaw(double yaw) {
this.yaw = yaw;
}

public double getPitch() {
return pitch;
}

public void setPitch(double pitch) {
this.pitch = pitch;
}

public double getRoll() {
return roll;
}

public void setRoll(double roll) {
this.roll = roll;
}

}

public class landmarkbean{
/*
"landmark":[
{"x":172.24,"y":148.64},
{"x":280.38,"y":140.28},
{"x":229.78,"y":222.21},
{"x":235.31,"y":264.27} ],
*/
private double x;
private double y;
public double getX() {
return x;
}

public void setX(double x) {
this.x = x;
}

public double getY() {
return y;
}

public void setY(double y) {
this.y = y;
}

}
List<landmarkbean>和List<landmark72bean>內容一致。
至此,FaceDetectBean才算寫完,這樣我們的資料轉為Java物件時,才能一一對應。

回到正題,我們開始對JSON格式的資料進行解析。
//解析JSON格式資料
JSON json = JSON.parseObject(result); //result為百度AI返回的JSON格式資料
FaceDetectBean faceDetectBean = JSON.toJavaObject(json,FaceDetectBean.class); //將result轉為FaceDetectBean的物件,這樣我們就可以對資料進行操作了。
ResultClass resultClass =faceDetectBean.getResult(); //通過getResult()獲取到ResultClass的物件
List<face_list_bean> face_list = resultClass.getFace_list(); //通過getFace_list()獲取到List<face_list_bean>的物件,我們需要的東西都放在這裡面。
for(int i=0;i<face_list.size();i++){ //從圖片上的第一張人臉開始
face_list_bean myface = face_list.get(i); //得到該人臉的face_list_bean物件
List<landmark72bean> landmark72beanList = myface.getLandmark72();
landmark72bean landmark72_left = landmark72beanList.get(17);
landmark72bean landmark72_right = landmark72beanList.get(30);
System.out.println("x="+landmark72_left.getX()+", y="+landmark72_left.getY());
System.out.println("x="+landmark72_right.getX()+", y="+landmark72_right.getY());
left_x = landmark72_left.getX();
left_y = landmark72_left.getY();
right_x = landmark72_right.getX();
right_y = landmark72_right.getY();
double dx = (left_x - right_x);
double dy = (left_y - right_y);
distance = Math.sqrt(dx*dx + dy*dy );
System.out.println("distance===>"+distance);
}
因為我需要的是landmark里人臉關鍵點的座標,所以一直獲取到 landmark的物件才可以。
如果只需要age,beauty則得到face_list_bean的物件就可以了。通過 物件.getAge()方法就能得到年齡。
總之,需要什麼資訊,就看看該資訊是哪個類的屬性。通過建立該類的物件,物件的get,set方法對資料進行操作。
----------------------
原始碼:https://github.com/Xiang-MY/BDALdemo