เกี่ยวกับ Codelab นี้
1 ข้อควรทราบก่อนที่จะเริ่มต้น
ใน Codelab นี้ คุณดูวิธีเรียกใช้การอนุมานการตรวจหาออบเจ็กต์จากแอป Android โดยใช้ TensorFlow Serving กับ REST และ gRPC
สิ่งที่ต้องมีก่อน
- ความรู้เบื้องต้นเกี่ยวกับการพัฒนา Android ด้วย Java
- ความรู้เบื้องต้นเกี่ยวกับแมชชีนเลิร์นนิงด้วย TensorFlow เช่น การฝึกอบรมและการทําให้ใช้งานได้
- ความรู้เบื้องต้นเกี่ยวกับเทอร์มินัลและ Docker
สิ่งที่คุณจะได้เรียนรู้
- วิธีค้นหาโมเดลการตรวจจับออบเจ็กต์ที่ฝึกไว้แล้วล่วงหน้าใน TensorFlow Hub
- วิธีสร้างแอป Android แบบง่ายๆ และการคาดคะเนด้วยโมเดลการตรวจจับออบเจ็กต์ที่ดาวน์โหลดผ่าน TensorFlow Serving (REST และ gRPC)
- วิธีแสดงผลการตรวจจับใน UI
สิ่งที่ต้องมี
- Android Studio เวอร์ชันล่าสุด
- Docker
- Bash
2 ตั้งค่า
วิธีดาวน์โหลดโค้ดสําหรับ Codelab นี้
- ไปที่ที่เก็บ GitHub สําหรับ Codelab นี้
- คลิก Code > Download ZIP เพื่อดาวน์โหลดโค้ดทั้งหมดสําหรับ Codelab นี้
- แตกไฟล์ ZIP ที่ดาวน์โหลดเพื่อคลายโฟลเดอร์รูท
codelabs
ด้วยทรัพยากรทั้งหมดที่ต้องการ
Codelab นี้ต้องการเฉพาะไฟล์ในไดเรกทอรีย่อย TFServing/ObjectDetectionAndroid
ในที่เก็บ ซึ่งมี 2 โฟลเดอร์ดังนี้
- โฟลเดอร์
starter
มีโค้ดเริ่มต้นที่คุณสร้างสําหรับ Codelab นี้ - โฟลเดอร์
finished
มีโค้ดที่สมบูรณ์สําหรับแอปตัวอย่างที่สมบูรณ์
3 เพิ่มทรัพยากร Dependency ลงในโปรเจ็กต์
นําเข้าแอปเริ่มต้นไปยัง Android Studio
- ใน Android Studio ให้คลิก File > New > Import project แล้วเลือกโฟลเดอร์
starter
จากซอร์สโค้ดที่คุณดาวน์โหลดไว้ก่อนหน้านี้
เพิ่มทรัพยากร Dependency สําหรับ OkHttp และ gRPC
- ในไฟล์
app/build.gradle
ของโปรเจ็กต์ ให้ยืนยันว่ามีทรัพยากร Dependency อยู่
dependencies {
// ...
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'javax.annotation:javax.annotation-api:1.3.2'
implementation 'io.grpc:grpc-okhttp:1.29.0'
implementation 'io.grpc:grpc-protobuf-lite:1.29.0'
implementation 'io.grpc:grpc-stub:1.29.0'
}
ซิงค์โปรเจ็กต์ด้วยไฟล์ Gradle
- เลือก
ซิงค์โปรเจ็กต์ด้วย Gradle Files จากเมนูการนําทาง
4 เรียกใช้แอปเริ่มต้น
- เริ่มโปรแกรมจําลอง Android จากนั้นคลิก
เรียกใช้ ‘app' ในเมนูการนําทาง
เรียกใช้และสํารวจแอป
แอปควรเปิดตัวในอุปกรณ์ Android UI มีความเรียบง่าย: จะมีรูปภาพแมวที่คุณต้องการตรวจหาออบเจ็กต์และผู้ใช้เลือกวิธีส่งข้อมูลไปยังแบ็กเอนด์ได้ด้วย REST หรือ gRPC แบ็กเอนด์จะตรวจจับออบเจ็กต์ในรูปภาพและส่งผลลัพธ์ของการตรวจจับไปยังแอปไคลเอ็นต์ ซึ่งจะแสดงผล UI อีกครั้ง
ขณะนี้หากคุณคลิกเรียกใช้การอนุมาน ก็จะไม่มีอะไรเกิดขึ้น เนื่องจากยังไม่สามารถสื่อสารกับแบ็กเอนด์
5 ทําให้โมเดลการตรวจจับออบเจ็กต์ใช้งานได้ด้วยการแสดงผล TensorFlow
การตรวจหาออบเจ็กต์เป็นงาน ML ที่พบบ่อยที่สุดและเป้าหมายของออบเจ็กต์นี้คือ การตรวจหาออบเจ็กต์ภายในรูปภาพ ซึ่งก็คือการคาดการณ์หมวดหมู่ที่เป็นไปได้ของออบเจ็กต์และกรอบล้อมรอบ ด้านล่างนี้เป็นตัวอย่างของผลการตรวจหา
Google ได้เผยแพร่โมเดลที่ฝึกล่วงหน้าแล้วจํานวนหนึ่งใน TensorFlow Hub หากต้องการดูรายการทั้งหมด ให้ไปที่หน้า Object_detection คุณใช้โมเดล SSD MobileNet V2 FPNLite 320x320 ที่ค่อนข้างหนักสําหรับ Codelab นี้เพื่อที่จะได้ไม่ต้องใช้ GPU ในการเรียกใช้
หากต้องการทําให้โมเดลการตรวจจับออบเจ็กต์ใช้งานได้ด้วยการแสดงผล TensorFlow ให้ทําดังนี้
- ดาวน์โหลดไฟล์โมเดล
- ยกเลิกการบีบอัดไฟล์
.tar.gz
โดยใช้เครื่องมือขยายข้อมูลที่บีบอัด เช่น 7-Zip - สร้างโฟลเดอร์
ssd_mobilenet_v2_2_320
แล้วสร้างโฟลเดอร์ย่อย123
ในโฟลเดอร์นั้น - วางโฟลเดอร์
variables
และไฟล์saved_model.pb
ที่แยกไว้ในโฟลเดอร์ย่อย123
คุณจะอ้างอิงโฟลเดอร์ ssd_mobilenet_v2_2_320
ว่าเป็นโฟลเดอร์ SavedModel
ก็ได้ 123
เป็นหมายเลขเวอร์ชันตัวอย่าง คุณเลือกหมายเลขอื่นได้หากต้องการ
โครงสร้างโฟลเดอร์ควรมีลักษณะเช่นนี้
เริ่มแสดงโฆษณา TensorFlow
- ในเทอร์มินัล ให้เริ่มแสดงโฆษณา TensorFlow ด้วย Docker แต่แทนที่ตัวยึดตําแหน่ง
PATH/TO/SAVEDMODEL
ด้วยเส้นทางสัมบูรณ์ของโฟลเดอร์ssd_mobilenet_v2_2_320
ในคอมพิวเตอร์
docker pull tensorflow/serving docker run -it --rm -p 8500:8500 -p 8501:8501 -v "PATH/TO/SAVEDMODEL:/models/ssd_mobilenet_v2_2" -e MODEL_NAME=ssd_mobilenet_v2_2 tensorflow/serving
Docker จะดาวน์โหลดอิมเมจการแสดงผล TensorFlow โดยอัตโนมัติก่อน ซึ่งจะใช้เวลา 1 นาที หลังจากนั้น TensorFlow Serving ควรจะเริ่มแสดง บันทึกควรมีลักษณะเหมือนข้อมูลโค้ดนี้
2022-02-25 06:01:12.513231: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle. 2022-02-25 06:01:12.585012: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 3000000000 Hz 2022-02-25 06:01:13.395083: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/ssd_mobilenet_v2_2/123 2022-02-25 06:01:13.837562: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 1928700 microseconds. 2022-02-25 06:01:13.877848: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/ssd_mobilenet_v2_2/123/assets.extra/tf_serving_warmup_requests 2022-02-25 06:01:13.929844: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: ssd_mobilenet_v2_2 version: 123} 2022-02-25 06:01:13.985848: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models 2022-02-25 06:01:13.985987: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled 2022-02-25 06:01:13.988994: I tensorflow_serving/model_servers/server.cc:393] Running gRPC ModelServer at 0.0.0.0:8500 ... [warn] getaddrinfo: address family for nodename not supported 2022-02-25 06:01:14.033872: I tensorflow_serving/model_servers/server.cc:414] Exporting HTTP/REST API at:localhost:8501 ... [evhttp_server.cc : 245] NET_LOG: Entering the event loop ...
6 เชื่อมต่อแอป Android กับ TensorFlow Serving ผ่าน REST
แบ็กเอนด์พร้อมใช้งานแล้ว คุณจึงส่งคําขอของไคลเอ็นต์ไปยังการแสดงของ TensorFlow เพื่อตรวจหาออบเจ็กต์ภายในรูปภาพได้ คุณส่งคําขอไปยังการแสดง TensorFlow ได้ 2 วิธีดังนี้
- REST
- gRPC
ส่งคําขอและรับการตอบกลับผ่าน REST
มี 3 ขั้นตอนง่ายๆ ดังนี้
- สร้างคําขอ REST
- ส่งคําขอ REST ไปยังการแสดงผล TensorFlow
- ดึงผลลัพธ์ที่คาดการณ์ไว้จากการตอบกลับของ REST และแสดง UI
คุณจะบรรลุเป้าหมายเหล่านี้ใน MainActivity.java.
สร้างคําขอ REST
ขณะนี้มีฟังก์ชัน createRESTRequest()
ที่ว่างเปล่าในไฟล์ MainActivity.java
คุณใช้ฟังก์ชันนี้เพื่อสร้างคําขอ REST ได้
private Request createRESTRequest() {
}
การแสดงผล TensorFlow ต้องการคําขอ POST ที่มี Tensor รูปภาพสําหรับโมเดล SSD MobileNet ที่คุณใช้ คุณจึงต้องดึงค่า RGB จากแต่ละพิกเซลของรูปภาพเป็นอาร์เรย์ แล้วรวมอาร์เรย์ไว้ใน JSON ซึ่งเป็นเพย์โหลดของคําขอ
- เพิ่มโค้ดนี้ลงในฟังก์ชัน
createRESTRequest()
//Create the REST request.
int[] inputImg = new int[INPUT_IMG_HEIGHT * INPUT_IMG_WIDTH];
int[][][][] inputImgRGB = new int[1][INPUT_IMG_HEIGHT][INPUT_IMG_WIDTH][3];
inputImgBitmap.getPixels(inputImg, 0, INPUT_IMG_WIDTH, 0, 0, INPUT_IMG_WIDTH, INPUT_IMG_HEIGHT);
int pixel;
for (int i = 0; i < INPUT_IMG_HEIGHT; i++) {
for (int j = 0; j < INPUT_IMG_WIDTH; j++) {
// Extract RBG values from each pixel; alpha is ignored
pixel = inputImg[i * INPUT_IMG_WIDTH + j];
inputImgRGB[0][i][j][0] = ((pixel >> 16) & 0xff);
inputImgRGB[0][i][j][1] = ((pixel >> 8) & 0xff);
inputImgRGB[0][i][j][2] = ((pixel) & 0xff);
}
}
RequestBody requestBody =
RequestBody.create("{\"instances\": " + Arrays.deepToString(inputImgRGB) + "}", JSON);
Request request =
new Request.Builder()
.url("http://" + SERVER + ":" + REST_PORT + "/v1/models/" + MODEL_NAME + ":predict")
.post(requestBody)
.build();
return request;
ส่งคําขอ REST ไปยังการแสดงโฆษณา TensorFlow
แอปช่วยให้ผู้ใช้เลือก REST หรือ gRPC เพื่อสื่อสารกับ TensorFlow Serving จึงมี 2 สาขาใน Listener onClick(View view)
predictButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
if (requestRadioGroup.getCheckedRadioButtonId() == R.id.rest) {
// TODO: REST request
}
else {
}
}
}
)
- เพิ่มโค้ดนี้ลงในสาขา REST ของ Listener
onClick(View view)
เพื่อใช้ OkHttp เพื่อส่งคําขอไปยัง TensorFlow Serving ดังต่อไปนี้
// Send the REST request.
Request request = createRESTRequest();
try {
client =
new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.callTimeout(20, TimeUnit.SECONDS)
.build();
Response response = client.newCall(request).execute();
JSONObject responseObject = new JSONObject(response.body().string());
postprocessRESTResponse(responseObject);
} catch (IOException | JSONException e) {
Log.e(TAG, e.getMessage());
responseTextView.setText(e.getMessage());
return;
}
ประมวลผลการตอบกลับ REST จาก TensorFlow Serving
โมเดล SDD MobileNet จะแสดงผลลัพธ์จํานวนหนึ่ง ซึ่งรวมถึง
num_detections
: จํานวนการตรวจจับdetection_scores
: คะแนนการตรวจจับdetection_classes
: ดัชนีคลาสการตรวจจับdetection_boxes
: พิกัดกล่องขอบเขต
คุณใช้ฟังก์ชัน postprocessRESTResponse()
ในการจัดการคําตอบ
private void postprocessRESTResponse(Predict.PredictResponse response) {
}
- เพิ่มโค้ดนี้ลงในฟังก์ชัน
postprocessRESTResponse()
// Process the REST response.
JSONArray predictionsArray = responseObject.getJSONArray("predictions");
//You only send one image, so you directly extract the first element.
JSONObject predictions = predictionsArray.getJSONObject(0);
// Argmax
int maxIndex = 0;
JSONArray detectionScores = predictions.getJSONArray("detection_scores");
for (int j = 0; j < predictions.getInt("num_detections"); j++) {
maxIndex =
detectionScores.getDouble(j) > detectionScores.getDouble(maxIndex + 1) ? j : maxIndex;
}
int detectionClass = predictions.getJSONArray("detection_classes").getInt(maxIndex);
JSONArray boundingBox = predictions.getJSONArray("detection_boxes").getJSONArray(maxIndex);
double ymin = boundingBox.getDouble(0);
double xmin = boundingBox.getDouble(1);
double ymax = boundingBox.getDouble(2);
double xmax = boundingBox.getDouble(3);
displayResult(detectionClass, (float) ymin, (float) xmin, (float) ymax, (float) xmax);
ตอนนี้ฟังก์ชันหลังการประมวลผลจะดึงค่าที่คาดการณ์ไว้จากการตอบกลับ ระบุหมวดหมู่ที่น่าจะเป็นมากที่สุดของวัตถุ และพิกัดของจุดยอดกล่องล้อมรอบ และแสดงผลกรอบล้อมรอบการตรวจจับบน UI ครั้งล่าสุด
เรียกใช้
- คลิก
เรียกใช้ ‘app' ในเมนูการนําทางแล้วรอให้แอปโหลด
- เลือก REST > Run inference
ระบบจะใช้เวลา 2-3 วินาทีก่อนที่แอปจะแสดงผลกรอบล้อมรอบของแมวและแสดง 17
เป็นหมวดหมู่ของออบเจ็กต์ที่แมปกับออบเจ็กต์ cat
ในชุดข้อมูล COCO
7 เชื่อมต่อแอป Android กับ TensorFlow Serving ผ่าน gRPC
นอกจาก REST แล้ว TensorFlow Serving ยังรองรับ gRPC อีกด้วย
gRPC เป็นเฟรมเวิร์ก Call Procedure Call (RPC) แบบโอเพนซอร์สที่มีประสิทธิภาพสูงและใช้งานได้กับทุกสภาพแวดล้อม เครื่องมือนี้จะเชื่อมบริการอย่างมีประสิทธิภาพทั่วทั้งศูนย์ข้อมูลต่างๆ ที่รองรับความสามารถในการจัดสรรภาระงาน การติดตาม การตรวจสอบประสิทธิภาพการทํางาน และการตรวจสอบสิทธิ์แบบเสียบปลั๊กได้ พบว่า gRPC มีประสิทธิภาพมากกว่า REST ในทางปฏิบัติ
ส่งคําขอและรับการตอบกลับด้วย gRPC
มี 4 ขั้นตอนง่ายๆ ดังนี้
- [ไม่บังคับ] สร้างโค้ดไคลเอ็นต์ gRPC
- สร้างคําขอ gRPC
- ส่งคําขอ gRPC ไปยัง TensorFlow Serving
- ดึงผลลัพธ์ที่คาดการณ์ไว้จากการตอบกลับของ gRPC และแสดง UI
คุณจะบรรลุเป้าหมายเหล่านี้ใน MainActivity.java.
ไม่บังคับ: สร้างโค้ดไคลเอ็นต์ gRPC
หากต้องการใช้ gRPC กับการให้บริการ TensorFlow คุณต้องทําตามเวิร์กโฟลว์ gRPC ดูข้อมูลเพิ่มเติมเกี่ยวกับรายละเอียดได้ที่เอกสารประกอบ gRPC
TensorFlow Serving และ TensorFlow จะกําหนดไฟล์ .proto
ให้คุณ เมื่อคํานึงถึง TensorFlow และ TensorFlow Serving 2.8 จึงต้องมีไฟล์ .proto
รายการต่อไปนี้
tensorflow/core/example/example.proto
tensorflow/core/example/feature.proto
tensorflow/core/protobuf/struct.proto
tensorflow/core/protobuf/saved_object_graph.proto
tensorflow/core/protobuf/saver.proto
tensorflow/core/protobuf/trackable_object_graph.proto
tensorflow/core/protobuf/meta_graph.proto
tensorflow/core/framework/node_def.proto
tensorflow/core/framework/attr_value.proto
tensorflow/core/framework/function.proto
tensorflow/core/framework/types.proto
tensorflow/core/framework/tensor_shape.proto
tensorflow/core/framework/full_type.proto
tensorflow/core/framework/versions.proto
tensorflow/core/framework/op_def.proto
tensorflow/core/framework/graph.proto
tensorflow/core/framework/tensor.proto
tensorflow/core/framework/resource_handle.proto
tensorflow/core/framework/variable.proto
tensorflow_serving/apis/inference.proto
tensorflow_serving/apis/classification.proto
tensorflow_serving/apis/predict.proto
tensorflow_serving/apis/regression.proto
tensorflow_serving/apis/get_model_metadata.proto
tensorflow_serving/apis/input.proto
tensorflow_serving/apis/prediction_service.proto
tensorflow_serving/apis/model.proto
- หากต้องการสร้างโค้ดนี้ ให้เพิ่มโค้ดนี้ลงในไฟล์
app/build.gradle
apply plugin: 'com.google.protobuf'
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.11.0' }
plugins {
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.29.0'
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
java { option 'lite' }
}
task.plugins {
grpc { option 'lite' }
}
}
}
}
สร้างคําขอ gRPC
คุณสร้างคําขอ gRPC ในฟังก์ชัน createGRPCRequest()
เช่นเดียวกับคําขอ REST
private Request createGRPCRequest() {
}
- เพิ่มโค้ดนี้ลงในฟังก์ชัน
createGRPCRequest()
:
if (stub == null) {
channel = ManagedChannelBuilder.forAddress(SERVER, GRPC_PORT).usePlaintext().build();
stub = PredictionServiceGrpc.newBlockingStub(channel);
}
Model.ModelSpec.Builder modelSpecBuilder = Model.ModelSpec.newBuilder();
modelSpecBuilder.setName(MODEL_NAME);
modelSpecBuilder.setVersion(Int64Value.of(MODEL_VERSION));
modelSpecBuilder.setSignatureName(SIGNATURE_NAME);
Predict.PredictRequest.Builder builder = Predict.PredictRequest.newBuilder();
builder.setModelSpec(modelSpecBuilder);
TensorProto.Builder tensorProtoBuilder = TensorProto.newBuilder();
tensorProtoBuilder.setDtype(DataType.DT_UINT8);
TensorShapeProto.Builder tensorShapeBuilder = TensorShapeProto.newBuilder();
tensorShapeBuilder.addDim(TensorShapeProto.Dim.newBuilder().setSize(1));
tensorShapeBuilder.addDim(TensorShapeProto.Dim.newBuilder().setSize(INPUT_IMG_HEIGHT));
tensorShapeBuilder.addDim(TensorShapeProto.Dim.newBuilder().setSize(INPUT_IMG_WIDTH));
tensorShapeBuilder.addDim(TensorShapeProto.Dim.newBuilder().setSize(3));
tensorProtoBuilder.setTensorShape(tensorShapeBuilder.build());
int[] inputImg = new int[INPUT_IMG_HEIGHT * INPUT_IMG_WIDTH];
inputImgBitmap.getPixels(inputImg, 0, INPUT_IMG_WIDTH, 0, 0, INPUT_IMG_WIDTH, INPUT_IMG_HEIGHT);
int pixel;
for (int i = 0; i < INPUT_IMG_HEIGHT; i++) {
for (int j = 0; j < INPUT_IMG_WIDTH; j++) {
// Extract RBG values from each pixel; alpha is ignored.
pixel = inputImg[i * INPUT_IMG_WIDTH + j];
tensorProtoBuilder.addIntVal((pixel >> 16) & 0xff);
tensorProtoBuilder.addIntVal((pixel >> 8) & 0xff);
tensorProtoBuilder.addIntVal((pixel) & 0xff);
}
}
TensorProto tensorProto = tensorProtoBuilder.build();
builder.putInputs("input_tensor", tensorProto);
builder.addOutputFilter("num_detections");
builder.addOutputFilter("detection_boxes");
builder.addOutputFilter("detection_classes");
builder.addOutputFilter("detection_scores");
return builder.build();
ส่งคําขอ gRPC ไปยังการแสดงผล TensorFlow
คุณฟัง onClick(View view)
Listener ได้แล้ว
predictButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
if (requestRadioGroup.getCheckedRadioButtonId() == R.id.rest) {
}
else {
// TODO: gRPC request
}
}
}
)
- เพิ่มโค้ดนี้ลงในสาขา gRPC
try {
Predict.PredictRequest request = createGRPCRequest();
Predict.PredictResponse response = stub.predict(request);
postprocessGRPCResponse(response);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
responseTextView.setText(e.getMessage());
return;
}
ประมวลผลการตอบสนอง gRPC จาก TensorFlow Serving
คุณใช้ฟังก์ชัน postprocessGRPCResponse()
เพื่อจัดการการตอบกลับได้เช่นเดียวกับ gRPC
private void postprocessGRPCResponse(Predict.PredictResponse response) {
}
- เพิ่มโค้ดนี้ลงในฟังก์ชัน
postprocessGRPCResponse()
// Process the response.
float numDetections = response.getOutputsMap().get("num_detections").getFloatValList().get(0);
List<Float> detectionScores = response.getOutputsMap().get("detection_scores").getFloatValList();
int maxIndex = 0;
for (int j = 0; j < numDetections; j++) {
maxIndex = detectionScores.get(j) > detectionScores.get(maxIndex + 1) ? j : maxIndex;
}
Float detectionClass = response.getOutputsMap().get("detection_classes").getFloatValList().get(maxIndex);
List<Float> boundingBoxValues = response.getOutputsMap().get("detection_boxes").getFloatValList();
float ymin = boundingBoxValues.get(maxIndex * 4);
float xmin = boundingBoxValues.get(maxIndex * 4 + 1);
float ymax = boundingBoxValues.get(maxIndex * 4 + 2);
float xmax = boundingBoxValues.get(maxIndex * 4 + 3);
displayResult(detectionClass.intValue(), ymin, xmin, ymax, xmax);
ตอนนี้ฟังก์ชันหลังการประมวลผลสามารถแยกค่าที่คาดการณ์ไว้จากการตอบกลับ และแสดงผลกล่องขอบเขตการตรวจจับใน UI ได้
เรียกใช้
- คลิก
เรียกใช้ ‘app' ในเมนูการนําทางแล้วรอให้แอปโหลด
- เลือก gRPC > Run inference
โปรดรอ 2-3 วินาทีก่อนที่แอปจะแสดงผลกรอบล้อมรอบของแมวและแสดง 17
เป็นหมวดหมู่ของออบเจ็กต์ที่แมปกับหมวดหมู่ cat
ในชุดข้อมูล COCO
8 ยินดีด้วย
คุณใช้ TensorFlow Serving เพื่อเพิ่มความสามารถในการตรวจหาออบเจ็กต์ในแอปแล้ว