From 232389e8059d646aa3133db3db5e74f651154213 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Sat, 28 Aug 2021 02:51:46 +0800 Subject: [PATCH 01/18] :sparkles: Get number of labeled and unlabled image in project metadata --- .../main/java/ai/classifai/ClassifaiApp.java | 2 + .../bndbox/BoundingBoxVerticle.java | 6 + .../database/portfolio/PortfolioVerticle.java | 10 +- .../ai/classifai/loader/ProjectLoader.java | 4 + .../java/ai/classifai/util/ParamConfig.java | 3 + .../classifai/util/data/LabelListHandler.java | 148 ++++++++++++++++++ 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java diff --git a/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java b/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java index 71644e3e5..84f670c9b 100644 --- a/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java +++ b/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java @@ -16,6 +16,8 @@ package ai.classifai; import ai.classifai.config.CLIArgument; +import ai.classifai.database.annotation.bndbox.BoundingBoxVerticle; +import ai.classifai.util.data.LabelListHandler; import io.vertx.core.DeploymentOptions; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; diff --git a/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java b/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java index 69bde714e..4c9db9307 100644 --- a/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java @@ -29,6 +29,8 @@ import io.vertx.core.eventbus.Message; import io.vertx.core.json.JsonObject; import io.vertx.jdbcclient.JDBCPool; +import io.vertx.sqlclient.Row; +import io.vertx.sqlclient.RowSet; import lombok.extern.slf4j.Slf4j; /** @@ -80,6 +82,10 @@ else if(action.equals(AnnotationQuery.getRenameProjectData())) { this.renameProjectData(message); } + else if(action.equals(AnnotationQuery.getRetrieveAllProjects())) + { + this.renameProjectData(message); + } else { log.error("BoundingBox Verticle query error. Action did not have an assigned function for handling."); diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index a8ddf01b6..2f8cc8760 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -35,6 +35,7 @@ import ai.classifai.util.collection.ConversionHandler; import ai.classifai.util.collection.UuidGenerator; import ai.classifai.util.data.ImageHandler; +import ai.classifai.util.data.LabelListHandler; import ai.classifai.util.data.StringHandler; import ai.classifai.util.message.ErrorCodes; import ai.classifai.util.message.ReplyHandler; @@ -47,6 +48,7 @@ import io.vertx.core.Promise; import io.vertx.core.Vertx; import io.vertx.core.eventbus.Message; +import io.vertx.core.json.Json; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.jdbcclient.JDBCPool; @@ -491,6 +493,9 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin File projectPath = loader.getProjectPath(); + ArrayList> totalImage = LabelListHandler.getImageLabeledStatus(loader.getUuidAnnotationDict()); +// String labelPerClassPerImage = LabelListHandler.getImageLabel(loader.getUuidAnnotationDict()); + if (!projectPath.exists()) { log.info(String.format("Root path of project [%s] is missing! %s does not exist.", loader.getProjectName(), loader.getProjectPath())); @@ -510,7 +515,10 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin .put(ParamConfig.getLastModifiedDate(), currentVersion.getLastModifiedDate().toString()) .put(ParamConfig.getCurrentVersionParam(), currentVersion.getVersionUuid()) .put(ParamConfig.getTotalUuidParam(), existingDataInDir.size()) - .put(ParamConfig.getIsRootPathValidParam(), projectPath.exists())); + .put(ParamConfig.getIsRootPathValidParam(), projectPath.exists()) + .put(ParamConfig.getLabelledImageParam(), totalImage.get(0).size()) + .put(ParamConfig.getUnLabelledImageParam(), totalImage.get(1).size())); +// .put(ParamConfig.getLabelPerClassPerImage(), labelPerClassPerImage)); } /** diff --git a/classifai-core/src/main/java/ai/classifai/loader/ProjectLoader.java b/classifai-core/src/main/java/ai/classifai/loader/ProjectLoader.java index 75d3be75e..62c9ba378 100644 --- a/classifai-core/src/main/java/ai/classifai/loader/ProjectLoader.java +++ b/classifai-core/src/main/java/ai/classifai/loader/ProjectLoader.java @@ -102,6 +102,10 @@ public class ProjectLoader @Builder.Default private List unsupportedImageList = new ArrayList<>(); + // list of label and unlabelled image + @Builder.Default private List labelledImageList = new ArrayList<>(); + @Builder.Default private List unLabelledImageList = new ArrayList<>(); + public String getCurrentVersionUuid() { return projectVersion.getCurrentVersion().getVersionUuid(); diff --git a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java index b3fe440af..a268c3b1f 100644 --- a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java +++ b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java @@ -95,6 +95,9 @@ public class ParamConfig @Getter private static final String createdDateParam = "created_date"; @Getter private static final String lastModifiedDate = "last_modified_date"; @Getter private static final String isRootPathValidParam = "root_path_valid"; + @Getter private static final String labelledImageParam = "labelled_image"; + @Getter private static final String unLabelledImageParam = "unlabelled_image"; + @Getter private static final String labelPerClassPerImage = "labelPerClass_per_Image"; @Getter private static final String statusParam = "status"; diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java new file mode 100644 index 000000000..be12ec8bd --- /dev/null +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -0,0 +1,148 @@ +package ai.classifai.util.data; + +import ai.classifai.database.versioning.Annotation; +import ai.classifai.util.ParamConfig; +import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; + +/* +* Objective of this class: +* 1) retrieve information of the annotation from database +* 2) sort label according to class +* 3) send label and unlabeled information +* */ + +@Slf4j +public class LabelListHandler { + + // Handling the number of labeled and unlabeled image + public static ArrayList> getImageLabeledStatus(Map uuidAnnotationDict) { + + Set imageUUID = uuidAnnotationDict.keySet(); // key for each project + List annotationList = new ArrayList<>(); // a list of Image metadata + ArrayList labeledImageList= new ArrayList<>(); + ArrayList unlabeledImageList = new ArrayList<>(); + + // Getting image metadata : uuid, projectId, imgPath, annotationDict, imgDepth, imgOriW, imgOriH, fileSize + for (String s : imageUUID) { + annotationList.add(uuidAnnotationDict.get(s)); + } + + // Every annotation represent an image + for (Annotation annotation : annotationList) { + + LinkedHashMap annotationDict = getAnnotationDict(annotation.getAnnotationDictDbFormat()); + JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDict.values())); + + if (getAnnotatedImage(labelPointData) != null) { + labeledImageList.add(labelPointData); + } else { + unlabeledImageList.add(labelPointData); + } + + } + + ArrayList> totalImage = new ArrayList<>(); + totalImage.add(labeledImageList); + totalImage.add(unlabeledImageList); + + return totalImage; + + } + + + public static LinkedHashMap getAnnotationDict(String annotationDict) { + + String s = StringUtils.removeStart(StringUtils.removeEnd(annotationDict, "]"), "["); + + JsonObject annotationDictJsonObject = new JsonObject(s); + String versionUuid = annotationDictJsonObject.getString(ParamConfig.getVersionUuidParam()); + JsonObject annotationData= annotationDictJsonObject.getJsonObject(ParamConfig.getAnnotationDataParam()); + + LinkedHashMap annotationDataMap = new LinkedHashMap<>(); + + annotationDataMap.put(versionUuid, annotationData); + + return annotationDataMap; + + } + + public static JsonArray getAnnotationStatus(String annotationDictValue){ + + String s = StringUtils.removeStart(StringUtils.removeEnd(annotationDictValue, "]"), "["); + JsonObject annotationDataJsonObject = new JsonObject(s); //annotation, img_x, img_y, img_w, img_h + + // To get annotation data + return annotationDataJsonObject.getJsonArray(ParamConfig.getAnnotationParam());// x1, y1, x2, y2, color, distToImg, label ,id + + } + + public static Number getAnnotatedImage(JsonArray labelPointData) { + + if(!labelPointData.isEmpty()) { + return labelPointData.size(); + } else { + return null; + } + + } + + public static String getImageLabel(Map uuidAnnotationDict) { + + Set imageUUID = uuidAnnotationDict.keySet(); // key for each project + List annotationList = new ArrayList<>(); // a list of Image metadata + Map labelByClass = new HashMap<>(); + ArrayList labels = new ArrayList<>(); + + for (String s : imageUUID) { + annotationList.add(uuidAnnotationDict.get(s)); + } + + JsonObject jsonObject = new JsonObject(); + for (Annotation annotation : annotationList) { + + LinkedHashMap annotationDict = getAnnotationDict(annotation.getAnnotationDictDbFormat()); + JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDict.values())); + + for (int i = 0; i < labelPointData.size(); i++) { + JsonObject jsonArray = labelPointData.getJsonObject(i); + String label = jsonArray.getString("label"); + labels.add(label); + } + + for (String label : labels) { + Integer count = labelByClass.get(label); + if (count == null) { + count = 0; + } + if (label == null) { + label = "null"; + } + labelByClass.put(label, count + 1); + } + + String versionUUID = getVerssionUUID(annotationDict); + JsonArray jsonArray = new JsonArray(Collections.singletonList(labelByClass)); + jsonObject.put(versionUUID, jsonArray); + } + + return Objects.requireNonNull(jsonObject).toString(); + + } + + public static String getVerssionUUID(LinkedHashMap annotationDict) { + + String s = StringUtils.removeStart(StringUtils.removeEnd(String.valueOf(annotationDict), "]"), "["); + JsonObject annotationDataJsonObject = new JsonObject(s); //annotation, img_x, img_y, img_w, img_h + + // To get annotation data + return annotationDataJsonObject.getString(ParamConfig.getVersionUuidParam()); + + } + + +} From df049b1960d170f3be100cf7b17cf1613657fe4b Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Sat, 28 Aug 2021 12:30:19 +0800 Subject: [PATCH 02/18] :sparkles: Get number of label per Image --- .../database/portfolio/PortfolioVerticle.java | 7 +- .../classifai/util/data/LabelListHandler.java | 95 ++++++++++--------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index 2f8cc8760..4f0bbbb1a 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -48,7 +48,6 @@ import io.vertx.core.Promise; import io.vertx.core.Vertx; import io.vertx.core.eventbus.Message; -import io.vertx.core.json.Json; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.jdbcclient.JDBCPool; @@ -494,7 +493,7 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin File projectPath = loader.getProjectPath(); ArrayList> totalImage = LabelListHandler.getImageLabeledStatus(loader.getUuidAnnotationDict()); -// String labelPerClassPerImage = LabelListHandler.getImageLabel(loader.getUuidAnnotationDict()); + String labelPerClassPerImage = LabelListHandler.getLabelPerClassPerImage(loader.getUuidAnnotationDict()); if (!projectPath.exists()) { @@ -517,8 +516,8 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin .put(ParamConfig.getTotalUuidParam(), existingDataInDir.size()) .put(ParamConfig.getIsRootPathValidParam(), projectPath.exists()) .put(ParamConfig.getLabelledImageParam(), totalImage.get(0).size()) - .put(ParamConfig.getUnLabelledImageParam(), totalImage.get(1).size())); -// .put(ParamConfig.getLabelPerClassPerImage(), labelPerClassPerImage)); + .put(ParamConfig.getUnLabelledImageParam(), totalImage.get(1).size()) + .put(ParamConfig.getLabelPerClassPerImage(), labelPerClassPerImage)); } /** diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index be12ec8bd..550523eb8 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -1,6 +1,7 @@ package ai.classifai.util.data; import ai.classifai.database.versioning.Annotation; +import ai.classifai.database.versioning.AnnotationVersion; import ai.classifai.util.ParamConfig; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; @@ -23,20 +24,15 @@ public class LabelListHandler { public static ArrayList> getImageLabeledStatus(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); // key for each project - List annotationList = new ArrayList<>(); // a list of Image metadata + List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict);// a list of Image metadata ArrayList labeledImageList= new ArrayList<>(); ArrayList unlabeledImageList = new ArrayList<>(); - // Getting image metadata : uuid, projectId, imgPath, annotationDict, imgDepth, imgOriW, imgOriH, fileSize - for (String s : imageUUID) { - annotationList.add(uuidAnnotationDict.get(s)); - } - // Every annotation represent an image for (Annotation annotation : annotationList) { - LinkedHashMap annotationDict = getAnnotationDict(annotation.getAnnotationDictDbFormat()); - JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDict.values())); + LinkedHashMap annotationDataMap = getAnnotationData(annotation.getAnnotationDictDbFormat()); // version uuid, annotation data + JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDataMap.values())); if (getAnnotatedImage(labelPointData) != null) { labeledImageList.add(labelPointData); @@ -55,33 +51,32 @@ public static ArrayList> getImageLabeledStatus(Map getAnnotationDict(String annotationDict) { + private static LinkedHashMap getAnnotationData(String annotationDict) { + LinkedHashMap annotationDataMap = new LinkedHashMap<>(); String s = StringUtils.removeStart(StringUtils.removeEnd(annotationDict, "]"), "["); JsonObject annotationDictJsonObject = new JsonObject(s); String versionUuid = annotationDictJsonObject.getString(ParamConfig.getVersionUuidParam()); JsonObject annotationData= annotationDictJsonObject.getJsonObject(ParamConfig.getAnnotationDataParam()); - LinkedHashMap annotationDataMap = new LinkedHashMap<>(); - annotationDataMap.put(versionUuid, annotationData); return annotationDataMap; } - public static JsonArray getAnnotationStatus(String annotationDictValue){ + private static JsonArray getAnnotationStatus(String annotationDictValue){ String s = StringUtils.removeStart(StringUtils.removeEnd(annotationDictValue, "]"), "["); JsonObject annotationDataJsonObject = new JsonObject(s); //annotation, img_x, img_y, img_w, img_h - // To get annotation data + // To get annotation parameters return annotationDataJsonObject.getJsonArray(ParamConfig.getAnnotationParam());// x1, y1, x2, y2, color, distToImg, label ,id } - public static Number getAnnotatedImage(JsonArray labelPointData) { + private static Number getAnnotatedImage(JsonArray labelPointData) { if(!labelPointData.isEmpty()) { return labelPointData.size(); @@ -91,57 +86,63 @@ public static Number getAnnotatedImage(JsonArray labelPointData) { } - public static String getImageLabel(Map uuidAnnotationDict) { + public static String getLabelPerClassPerImage(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); // key for each project - List annotationList = new ArrayList<>(); // a list of Image metadata + List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); // a list of Image metadata + Map labelByClass; + + JsonArray jsonArray = new JsonArray(); + JsonObject jsonObject = new JsonObject(); + + for (Annotation annotation : annotationList) { + + LinkedHashMap annotationDataMap = getAnnotationData(annotation.getAnnotationDictDbFormat()); + JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDataMap.values())); + labelByClass = getLabelByClass(labelPointData); + + jsonObject.put(annotation.getUuid(), labelByClass); + jsonArray.add(jsonObject); + } + + return jsonArray.encode(); + + } + + private static Map getLabelByClass(JsonArray labelPointData){ + Map labelByClass = new HashMap<>(); ArrayList labels = new ArrayList<>(); - for (String s : imageUUID) { - annotationList.add(uuidAnnotationDict.get(s)); + for (int i = 0; i < labelPointData.size(); i++) { + JsonObject jsonArray = labelPointData.getJsonObject(i); + String label = jsonArray.getString("label"); + labels.add(label); } - JsonObject jsonObject = new JsonObject(); - for (Annotation annotation : annotationList) { + for (String label : labels) { - LinkedHashMap annotationDict = getAnnotationDict(annotation.getAnnotationDictDbFormat()); - JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDict.values())); + Integer count = labelByClass.get(label); - for (int i = 0; i < labelPointData.size(); i++) { - JsonObject jsonArray = labelPointData.getJsonObject(i); - String label = jsonArray.getString("label"); - labels.add(label); + if (count == null) { + count = 0; } - for (String label : labels) { - Integer count = labelByClass.get(label); - if (count == null) { - count = 0; - } - if (label == null) { - label = "null"; - } - labelByClass.put(label, count + 1); - } - - String versionUUID = getVerssionUUID(annotationDict); - JsonArray jsonArray = new JsonArray(Collections.singletonList(labelByClass)); - jsonObject.put(versionUUID, jsonArray); + labelByClass.put(label, count + 1); } - return Objects.requireNonNull(jsonObject).toString(); - + return labelByClass; } - public static String getVerssionUUID(LinkedHashMap annotationDict) { + private static List getAnnotationList(Set imageUUID, Map uuidAnnotationDict){ - String s = StringUtils.removeStart(StringUtils.removeEnd(String.valueOf(annotationDict), "]"), "["); - JsonObject annotationDataJsonObject = new JsonObject(s); //annotation, img_x, img_y, img_w, img_h + List annotationList = new ArrayList<>(); - // To get annotation data - return annotationDataJsonObject.getString(ParamConfig.getVersionUuidParam()); + for (String s : imageUUID) { + annotationList.add(uuidAnnotationDict.get(s)); + } + return annotationList; } From 0e9f927c930b939d33ff85b6eaa1b8014786826e Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Sat, 28 Aug 2021 15:25:04 +0800 Subject: [PATCH 03/18] :bug: Fix bug --- .../java/ai/classifai/util/data/LabelListHandler.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index 550523eb8..d93afb92a 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -1,7 +1,6 @@ package ai.classifai.util.data; import ai.classifai.database.versioning.Annotation; -import ai.classifai.database.versioning.AnnotationVersion; import ai.classifai.util.ParamConfig; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; @@ -24,7 +23,7 @@ public class LabelListHandler { public static ArrayList> getImageLabeledStatus(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); // key for each project - List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict);// a list of Image metadata + List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict);// a list of annotation ArrayList labeledImageList= new ArrayList<>(); ArrayList unlabeledImageList = new ArrayList<>(); @@ -88,11 +87,10 @@ private static Number getAnnotatedImage(JsonArray labelPointData) { public static String getLabelPerClassPerImage(Map uuidAnnotationDict) { - Set imageUUID = uuidAnnotationDict.keySet(); // key for each project - List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); // a list of Image metadata + Set imageUUID = uuidAnnotationDict.keySet(); + List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); Map labelByClass; - JsonArray jsonArray = new JsonArray(); JsonObject jsonObject = new JsonObject(); for (Annotation annotation : annotationList) { @@ -102,10 +100,9 @@ public static String getLabelPerClassPerImage(Map uuidAnnota labelByClass = getLabelByClass(labelPointData); jsonObject.put(annotation.getUuid(), labelByClass); - jsonArray.add(jsonObject); } - return jsonArray.encode(); + return jsonObject.encode(); } From ffc2be111a3e5f7c860904ce918d571e8f91702b Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Sat, 28 Aug 2021 16:15:02 +0800 Subject: [PATCH 04/18] :recycle: Correct output format --- .../database/portfolio/PortfolioVerticle.java | 2 +- .../ai/classifai/util/data/LabelListHandler.java | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index 4f0bbbb1a..84c6c93a9 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -493,7 +493,7 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin File projectPath = loader.getProjectPath(); ArrayList> totalImage = LabelListHandler.getImageLabeledStatus(loader.getUuidAnnotationDict()); - String labelPerClassPerImage = LabelListHandler.getLabelPerClassPerImage(loader.getUuidAnnotationDict()); + JsonObject labelPerClassPerImage = LabelListHandler.getLabelPerClassPerImage(loader.getUuidAnnotationDict()); if (!projectPath.exists()) { diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index d93afb92a..c93c6bf44 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -9,12 +9,11 @@ import java.util.*; -/* -* Objective of this class: -* 1) retrieve information of the annotation from database -* 2) sort label according to class -* 3) send label and unlabeled information -* */ +/** + * Getting information of labeled and unlabeled image + * + * @author ken479 + */ @Slf4j public class LabelListHandler { @@ -85,7 +84,7 @@ private static Number getAnnotatedImage(JsonArray labelPointData) { } - public static String getLabelPerClassPerImage(Map uuidAnnotationDict) { + public static JsonObject getLabelPerClassPerImage(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); @@ -102,7 +101,7 @@ public static String getLabelPerClassPerImage(Map uuidAnnota jsonObject.put(annotation.getUuid(), labelByClass); } - return jsonObject.encode(); + return jsonObject; } From c5ae56f0abdfd2d79e748d95e1c7d64e90803527 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Mon, 30 Aug 2021 03:45:58 +0800 Subject: [PATCH 05/18] :recycle: Refactor code to remove complexity and make sorted array --- .../database/portfolio/PortfolioVerticle.java | 8 ++--- .../classifai/util/data/LabelListHandler.java | 31 ++++++++++++++----- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index 84c6c93a9..7a925f9be 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -492,8 +492,8 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin File projectPath = loader.getProjectPath(); - ArrayList> totalImage = LabelListHandler.getImageLabeledStatus(loader.getUuidAnnotationDict()); - JsonObject labelPerClassPerImage = LabelListHandler.getLabelPerClassPerImage(loader.getUuidAnnotationDict()); + LabelListHandler.getImageLabeledStatus(loader.getUuidAnnotationDict()); + JsonArray labelPerClassPerImage = LabelListHandler.getLabelPerClassPerImage(loader.getUuidAnnotationDict()); if (!projectPath.exists()) { @@ -515,8 +515,8 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin .put(ParamConfig.getCurrentVersionParam(), currentVersion.getVersionUuid()) .put(ParamConfig.getTotalUuidParam(), existingDataInDir.size()) .put(ParamConfig.getIsRootPathValidParam(), projectPath.exists()) - .put(ParamConfig.getLabelledImageParam(), totalImage.get(0).size()) - .put(ParamConfig.getUnLabelledImageParam(), totalImage.get(1).size()) + .put(ParamConfig.getLabelledImageParam(), LabelListHandler.getNumberOfLabeledImage()) + .put(ParamConfig.getUnLabelledImageParam(), LabelListHandler.getNumberOfUnLabeledImage()) .put(ParamConfig.getLabelPerClassPerImage(), labelPerClassPerImage)); } diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index c93c6bf44..72792ada6 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -18,8 +18,10 @@ @Slf4j public class LabelListHandler { + private static final ArrayList> totalImage = new ArrayList<>(); + // Handling the number of labeled and unlabeled image - public static ArrayList> getImageLabeledStatus(Map uuidAnnotationDict) { + public static void getImageLabeledStatus(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); // key for each project List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict);// a list of annotation @@ -40,14 +42,17 @@ public static ArrayList> getImageLabeledStatus(Map> totalImage = new ArrayList<>(); - totalImage.add(labeledImageList); - totalImage.add(unlabeledImageList); - - return totalImage; + totalImage.add(0, labeledImageList); + totalImage.add(1, unlabeledImageList); + } + public static Integer getNumberOfLabeledImage(){ + return totalImage.get(0).size(); } + public static Integer getNumberOfUnLabeledImage(){ + return totalImage.get(1).size(); + } private static LinkedHashMap getAnnotationData(String annotationDict) { @@ -84,13 +89,15 @@ private static Number getAnnotatedImage(JsonArray labelPointData) { } - public static JsonObject getLabelPerClassPerImage(Map uuidAnnotationDict) { + public static JsonArray getLabelPerClassPerImage(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); Map labelByClass; JsonObject jsonObject = new JsonObject(); + JsonObject sortedJsonObject = new JsonObject(); + JsonArray labelPerClassPerImageJsonArray = new JsonArray(); for (Annotation annotation : annotationList) { @@ -101,7 +108,15 @@ public static JsonObject getLabelPerClassPerImage(Map uuidAn jsonObject.put(annotation.getUuid(), labelByClass); } - return jsonObject; + Collections.reverse(annotationList); + + for(Annotation annotation : annotationList) { + sortedJsonObject.put(annotation.getUuid(), jsonObject.getJsonObject(annotation.getUuid())); + } + + labelPerClassPerImageJsonArray.add(sortedJsonObject); + + return labelPerClassPerImageJsonArray; } From f6a8c0c346e169f834fd71720e4cb49569fdbd4a Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Mon, 30 Aug 2021 13:04:31 +0800 Subject: [PATCH 06/18] :sparkles: New API for project statistic --- .../database/portfolio/PortfolioDbQuery.java | 3 ++ .../database/portfolio/PortfolioVerticle.java | 41 ++++++++++++--- .../ai/classifai/router/EndpointRouter.java | 2 + .../java/ai/classifai/router/V2Endpoint.java | 51 +++++++++++++++++++ .../java/ai/classifai/util/ParamConfig.java | 6 +-- .../classifai/util/data/LabelListHandler.java | 27 ++++------ 6 files changed, 104 insertions(+), 26 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java index 9adfa76c4..5687d2599 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java @@ -58,4 +58,7 @@ public class PortfolioDbQuery @Getter private static final String reloadProject = "SELECT project_path FROM Portfolio WHERE project_id = ?"; @Getter private static final String updateLastModifiedDate = "UPDATE Portfolio SET current_version = ? WHERE project_id = ?"; + + @Getter private static final String retrieveProjectStatistic = "retrieveProjectStatistic"; + } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index 7a925f9be..dde2439aa 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -128,6 +128,10 @@ else if(action.equals(PortfolioDbQuery.getUpdateLastModifiedDate())) { this.updateLastModifiedDate(message); } + else if(action.equals(PortfolioDbQuery.getRetrieveProjectStatistic())) + { + this.getProjectStatistic(message); + } else { log.error("Portfolio query error. Action did not have an assigned function for handling."); @@ -492,9 +496,6 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin File projectPath = loader.getProjectPath(); - LabelListHandler.getImageLabeledStatus(loader.getUuidAnnotationDict()); - JsonArray labelPerClassPerImage = LabelListHandler.getLabelPerClassPerImage(loader.getUuidAnnotationDict()); - if (!projectPath.exists()) { log.info(String.format("Root path of project [%s] is missing! %s does not exist.", loader.getProjectName(), loader.getProjectPath())); @@ -514,10 +515,7 @@ private void getProjectMetadata(@NonNull List result, @NonNull Strin .put(ParamConfig.getLastModifiedDate(), currentVersion.getLastModifiedDate().toString()) .put(ParamConfig.getCurrentVersionParam(), currentVersion.getVersionUuid()) .put(ParamConfig.getTotalUuidParam(), existingDataInDir.size()) - .put(ParamConfig.getIsRootPathValidParam(), projectPath.exists()) - .put(ParamConfig.getLabelledImageParam(), LabelListHandler.getNumberOfLabeledImage()) - .put(ParamConfig.getUnLabelledImageParam(), LabelListHandler.getNumberOfUnLabeledImage()) - .put(ParamConfig.getLabelPerClassPerImage(), labelPerClassPerImage)); + .put(ParamConfig.getIsRootPathValidParam(), projectPath.exists())); } /** @@ -662,6 +660,35 @@ public void reloadProject(Message message) ImageHandler.loadProjectRootPath(loader); } + public void getProjectStatistic(Message message) + { + String projectId = message.body().getString(ParamConfig.getProjectIdParam()); + + ProjectLoader loader = Objects.requireNonNull(ProjectHandler.getProjectLoader(projectId)); + + File projectPath = loader.getProjectPath(); + + LabelListHandler.getImageLabeledStatus(loader.getUuidAnnotationDict()); + JsonArray labelPerClassInProject = LabelListHandler.getLabelPerClassInProject(loader.getUuidAnnotationDict()); + + List result = new ArrayList<>(); + + if (!projectPath.exists()) + { + log.info(String.format("Root path of project [%s] is missing! %s does not exist.", loader.getProjectName(), loader.getProjectPath())); + } + + result.add(new JsonObject() + .put(ParamConfig.getLabeledImageParam(), LabelListHandler.getNumberOfLabeledImage()) + .put(ParamConfig.getUnLabeledImageParam(), LabelListHandler.getNumberOfUnLabeledImage()) + .put(ParamConfig.getLabelPerClassInProject(), labelPerClassInProject)); + + JsonObject response = ReplyHandler.getOkReply(); + response.put(loader.getProjectName(), result); + + message.replyAndRequest(response); + } + @Override public void stop(Promise promise) { diff --git a/classifai-core/src/main/java/ai/classifai/router/EndpointRouter.java b/classifai-core/src/main/java/ai/classifai/router/EndpointRouter.java index 7d6480cd2..964eaf1cc 100644 --- a/classifai-core/src/main/java/ai/classifai/router/EndpointRouter.java +++ b/classifai-core/src/main/java/ai/classifai/router/EndpointRouter.java @@ -161,6 +161,8 @@ public void start(Promise promise) router.put("/v2/close").handler(v2::closeClassifai); + router.get("/v2/:annotation_type/projects/:project_name/statistic").handler(v2::getProjectStatistic); + //*******************************Cloud******************************* router.put("/v2/:annotation_type/wasabi/projects/:project_name").handler(cloud::createWasabiCloudProject); diff --git a/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java b/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java index 3959a587b..2af3cbdd1 100644 --- a/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java +++ b/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java @@ -698,4 +698,55 @@ public void renameData(RoutingContext context) }); } + + + /** + * Retrieve number of labeled Image, unlabeled Image and total number of labels per class in a project + * + * GET http://localhost:{port}/v2/:annotation_type/projects/:project_name/statistic + * + * Example: + * GET http://localhost:{port}/v2/bndbox/projects/demo/statistic + * + */ + public void getProjectStatistic (RoutingContext context){ + + AnnotationType type = AnnotationHandler.getTypeFromEndpoint(context.request().getParam(ParamConfig.getAnnotationTypeParam())); + + String projectName = context.request().getParam(ParamConfig.getProjectNameParam()); + + log.debug("Get project statistic : " + projectName + " of annotation type: " + type.name()); + + ProjectLoader loader = ProjectHandler.getProjectLoader(projectName, type); + + if(helper.checkIfProjectNull(context, loader, projectName)) return; + + if(loader == null) + { + HTTPResponseHandler.configureOK(context, ReplyHandler.reportUserDefinedError("Failure in retrieving statistic of project: " + projectName)); + } + + JsonObject jsonObject = new JsonObject().put(ParamConfig.getProjectIdParam(), Objects.requireNonNull(loader).getProjectId()); + + //load label list + DeliveryOptions statisticDataOptions = new DeliveryOptions().addHeader(ParamConfig.getActionKeyword(), PortfolioDbQuery.getRetrieveProjectStatistic()); + + vertx.eventBus().request(PortfolioDbQuery.getQueue(), jsonObject, statisticDataOptions, statisticReply -> + { + if (statisticReply.succeeded()) { + + JsonObject statisticResponse = (JsonObject) statisticReply.result().body(); + + if (ReplyHandler.isReplyOk(statisticResponse)) + { + HTTPResponseHandler.configureOK(context, statisticResponse); + } + else + { + HTTPResponseHandler.configureOK(context, ReplyHandler.reportUserDefinedError("Failed to retrieve statistic for project " + projectName)); + } + } + }); + + } } diff --git a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java index a268c3b1f..ef3ea2eb9 100644 --- a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java +++ b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java @@ -95,9 +95,9 @@ public class ParamConfig @Getter private static final String createdDateParam = "created_date"; @Getter private static final String lastModifiedDate = "last_modified_date"; @Getter private static final String isRootPathValidParam = "root_path_valid"; - @Getter private static final String labelledImageParam = "labelled_image"; - @Getter private static final String unLabelledImageParam = "unlabelled_image"; - @Getter private static final String labelPerClassPerImage = "labelPerClass_per_Image"; + @Getter private static final String labeledImageParam = "labeled_image"; + @Getter private static final String unLabeledImageParam = "unlabeled_image"; + @Getter private static final String labelPerClassInProject = "labelPerClassInProject"; @Getter private static final String statusParam = "status"; diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index 72792ada6..413ecf70f 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -6,8 +6,8 @@ import io.vertx.core.json.JsonObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; - import java.util.*; +import java.util.stream.Collectors; /** * Getting information of labeled and unlabeled image @@ -89,34 +89,29 @@ private static Number getAnnotatedImage(JsonArray labelPointData) { } - public static JsonArray getLabelPerClassPerImage(Map uuidAnnotationDict) { + public static JsonArray getLabelPerClassInProject(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); - Map labelByClass; - - JsonObject jsonObject = new JsonObject(); - JsonObject sortedJsonObject = new JsonObject(); - JsonArray labelPerClassPerImageJsonArray = new JsonArray(); + Map labelByClass = new HashMap<>(); + List> labelByClassList = new ArrayList<>(); + JsonArray labelPerClassInProjectJsonArray = new JsonArray(); for (Annotation annotation : annotationList) { LinkedHashMap annotationDataMap = getAnnotationData(annotation.getAnnotationDictDbFormat()); JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDataMap.values())); labelByClass = getLabelByClass(labelPointData); - - jsonObject.put(annotation.getUuid(), labelByClass); + labelByClassList.add(labelByClass); } - Collections.reverse(annotationList); - - for(Annotation annotation : annotationList) { - sortedJsonObject.put(annotation.getUuid(), jsonObject.getJsonObject(annotation.getUuid())); - } + Map sumLabelByClass = labelByClassList.stream() + .flatMap(m -> m.entrySet().stream()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum)); - labelPerClassPerImageJsonArray.add(sortedJsonObject); + labelPerClassInProjectJsonArray.add(sumLabelByClass); - return labelPerClassPerImageJsonArray; + return labelPerClassInProjectJsonArray; } From 2fd6d488686c51873bdeb0cfc1f3eaeed60ca650 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Mon, 30 Aug 2021 17:13:51 +0800 Subject: [PATCH 07/18] :pencil2: Update satistic output format --- .../database/portfolio/PortfolioVerticle.java | 3 ++- .../java/ai/classifai/util/ParamConfig.java | 5 ++++- .../classifai/util/data/LabelListHandler.java | 17 +++++++++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index dde2439aa..9e9df425f 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -679,12 +679,13 @@ public void getProjectStatistic(Message message) } result.add(new JsonObject() + .put(ParamConfig.getProjectNameParam(), loader.getProjectName()) .put(ParamConfig.getLabeledImageParam(), LabelListHandler.getNumberOfLabeledImage()) .put(ParamConfig.getUnLabeledImageParam(), LabelListHandler.getNumberOfUnLabeledImage()) .put(ParamConfig.getLabelPerClassInProject(), labelPerClassInProject)); JsonObject response = ReplyHandler.getOkReply(); - response.put(loader.getProjectName(), result); + response.put(ParamConfig.getStatisticDataParam(), result); message.replyAndRequest(response); } diff --git a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java index ef3ea2eb9..c25bd784c 100644 --- a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java +++ b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java @@ -97,7 +97,10 @@ public class ParamConfig @Getter private static final String isRootPathValidParam = "root_path_valid"; @Getter private static final String labeledImageParam = "labeled_image"; @Getter private static final String unLabeledImageParam = "unlabeled_image"; - @Getter private static final String labelPerClassInProject = "labelPerClassInProject"; + @Getter private static final String labelPerClassInProject = "label_Per_Class_In_Project"; + @Getter private static final String labelParam = "label"; + @Getter private static final String labelCountParam = "count"; + @Getter private static final String statisticDataParam = "statistic_data"; @Getter private static final String statusParam = "status"; diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index 413ecf70f..b29e1ab85 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -93,8 +93,9 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn Set imageUUID = uuidAnnotationDict.keySet(); List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); - Map labelByClass = new HashMap<>(); + Map labelByClass; List> labelByClassList = new ArrayList<>(); + JsonObject labelCountJsonObject; JsonArray labelPerClassInProjectJsonArray = new JsonArray(); for (Annotation annotation : annotationList) { @@ -109,12 +110,24 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn .flatMap(m -> m.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum)); - labelPerClassInProjectJsonArray.add(sumLabelByClass); + for(Map.Entry m : sumLabelByClass.entrySet()) { + labelCountJsonObject = getJsonObject(m.getKey(), m.getValue()); + labelPerClassInProjectJsonArray.add(labelCountJsonObject); + } return labelPerClassInProjectJsonArray; } + private static JsonObject getJsonObject(String key, Integer value){ + + JsonObject jsonObject = new JsonObject(); + jsonObject.put(ParamConfig.getLabelParam(), key); + jsonObject.put(ParamConfig.getLabelCountParam(), value); + + return jsonObject; + } + private static Map getLabelByClass(JsonArray labelPointData){ Map labelByClass = new HashMap<>(); From 691a5779069747402996a0b1e150a16cdb18644f Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Wed, 1 Sep 2021 13:42:43 +0800 Subject: [PATCH 08/18] :memo: Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33396731e..d8a5e3ce8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The detailed rules and walkthrough of writing a changelog is located [here](http - Project versioning [WIP] - Project import image from cloud storage [WIP] - Database migration [WIP] +- Project statistic ## [2.0.0-alpha2] - 2021-08-12 ### Added From 4a49b7581acfadf7ca9d693aa06563de7f962ae1 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Wed, 1 Sep 2021 14:15:46 +0800 Subject: [PATCH 09/18] :recycle: Remove code smell and tidy up coding --- .../main/java/ai/classifai/ClassifaiApp.java | 2 - .../database/portfolio/PortfolioVerticle.java | 8 +- .../java/ai/classifai/util/ParamConfig.java | 12 +-- .../classifai/util/data/LabelListHandler.java | 85 +++++++++++-------- 4 files changed, 61 insertions(+), 46 deletions(-) diff --git a/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java b/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java index 84f670c9b..71644e3e5 100644 --- a/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java +++ b/classifai-api/src/main/java/ai/classifai/ClassifaiApp.java @@ -16,8 +16,6 @@ package ai.classifai; import ai.classifai.config.CLIArgument; -import ai.classifai.database.annotation.bndbox.BoundingBoxVerticle; -import ai.classifai.util.data.LabelListHandler; import io.vertx.core.DeploymentOptions; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index 9e9df425f..4e340d128 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -680,12 +680,12 @@ public void getProjectStatistic(Message message) result.add(new JsonObject() .put(ParamConfig.getProjectNameParam(), loader.getProjectName()) - .put(ParamConfig.getLabeledImageParam(), LabelListHandler.getNumberOfLabeledImage()) - .put(ParamConfig.getUnLabeledImageParam(), LabelListHandler.getNumberOfUnLabeledImage()) - .put(ParamConfig.getLabelPerClassInProject(), labelPerClassInProject)); + .put(ParamConfig.getLABELEDIMAGEPARAM(), LabelListHandler.getNumberOfLabeledImage()) + .put(ParamConfig.getUNLABELEDIMAGEPARAM(), LabelListHandler.getNumberOfUnLabeledImage()) + .put(ParamConfig.getLABELPERCLASSINPROJECTPARAM(), labelPerClassInProject)); JsonObject response = ReplyHandler.getOkReply(); - response.put(ParamConfig.getStatisticDataParam(), result); + response.put(ParamConfig.getSTATISTICDATAPARAM(), result); message.replyAndRequest(response); } diff --git a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java index c25bd784c..84fe1597c 100644 --- a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java +++ b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java @@ -95,12 +95,12 @@ public class ParamConfig @Getter private static final String createdDateParam = "created_date"; @Getter private static final String lastModifiedDate = "last_modified_date"; @Getter private static final String isRootPathValidParam = "root_path_valid"; - @Getter private static final String labeledImageParam = "labeled_image"; - @Getter private static final String unLabeledImageParam = "unlabeled_image"; - @Getter private static final String labelPerClassInProject = "label_Per_Class_In_Project"; - @Getter private static final String labelParam = "label"; - @Getter private static final String labelCountParam = "count"; - @Getter private static final String statisticDataParam = "statistic_data"; + @Getter private static final String LABELEDIMAGEPARAM = "labeled_image"; + @Getter private static final String UNLABELEDIMAGEPARAM = "unlabeled_image"; + @Getter private static final String LABELPERCLASSINPROJECTPARAM = "label_Per_Class_In_Project"; + @Getter private static final String LABELPARAM = "label"; + @Getter private static final String LABELCOUNTPARAM = "count"; + @Getter private static final String STATISTICDATAPARAM = "statistic_data"; @Getter private static final String statusParam = "status"; diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index b29e1ab85..86b34c08f 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -18,25 +18,33 @@ @Slf4j public class LabelListHandler { + private LabelListHandler() + { + throw new IllegalStateException("Utility class"); + } + private static final ArrayList> totalImage = new ArrayList<>(); // Handling the number of labeled and unlabeled image - public static void getImageLabeledStatus(Map uuidAnnotationDict) { - + public static void getImageLabeledStatus(Map uuidAnnotationDict) + { Set imageUUID = uuidAnnotationDict.keySet(); // key for each project List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict);// a list of annotation ArrayList labeledImageList= new ArrayList<>(); ArrayList unlabeledImageList = new ArrayList<>(); // Every annotation represent an image - for (Annotation annotation : annotationList) { - + for (Annotation annotation : annotationList) + { LinkedHashMap annotationDataMap = getAnnotationData(annotation.getAnnotationDictDbFormat()); // version uuid, annotation data JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDataMap.values())); - if (getAnnotatedImage(labelPointData) != null) { + if (getAnnotatedImage(labelPointData) != null) + { labeledImageList.add(labelPointData); - } else { + } + else + { unlabeledImageList.add(labelPointData); } @@ -46,16 +54,18 @@ public static void getImageLabeledStatus(Map uuidAnnotationD totalImage.add(1, unlabeledImageList); } - public static Integer getNumberOfLabeledImage(){ + public static Integer getNumberOfLabeledImage() + { return totalImage.get(0).size(); } - public static Integer getNumberOfUnLabeledImage(){ + public static Integer getNumberOfUnLabeledImage() + { return totalImage.get(1).size(); } - private static LinkedHashMap getAnnotationData(String annotationDict) { - + private static LinkedHashMap getAnnotationData(String annotationDict) + { LinkedHashMap annotationDataMap = new LinkedHashMap<>(); String s = StringUtils.removeStart(StringUtils.removeEnd(annotationDict, "]"), "["); @@ -69,8 +79,8 @@ private static LinkedHashMap getAnnotationData(String annota } - private static JsonArray getAnnotationStatus(String annotationDictValue){ - + private static JsonArray getAnnotationStatus(String annotationDictValue) + { String s = StringUtils.removeStart(StringUtils.removeEnd(annotationDictValue, "]"), "["); JsonObject annotationDataJsonObject = new JsonObject(s); //annotation, img_x, img_y, img_w, img_h @@ -79,18 +89,21 @@ private static JsonArray getAnnotationStatus(String annotationDictValue){ } - private static Number getAnnotatedImage(JsonArray labelPointData) { - - if(!labelPointData.isEmpty()) { + private static Number getAnnotatedImage(JsonArray labelPointData) + { + if(!labelPointData.isEmpty()) + { return labelPointData.size(); - } else { + } + else + { return null; } } - public static JsonArray getLabelPerClassInProject(Map uuidAnnotationDict) { - + public static JsonArray getLabelPerClassInProject(Map uuidAnnotationDict) + { Set imageUUID = uuidAnnotationDict.keySet(); List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); Map labelByClass; @@ -98,8 +111,8 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn JsonObject labelCountJsonObject; JsonArray labelPerClassInProjectJsonArray = new JsonArray(); - for (Annotation annotation : annotationList) { - + for (Annotation annotation : annotationList) + { LinkedHashMap annotationDataMap = getAnnotationData(annotation.getAnnotationDictDbFormat()); JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDataMap.values())); labelByClass = getLabelByClass(labelPointData); @@ -110,7 +123,8 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn .flatMap(m -> m.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum)); - for(Map.Entry m : sumLabelByClass.entrySet()) { + for(Map.Entry m : sumLabelByClass.entrySet()) + { labelCountJsonObject = getJsonObject(m.getKey(), m.getValue()); labelPerClassInProjectJsonArray.add(labelCountJsonObject); } @@ -119,31 +133,33 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn } - private static JsonObject getJsonObject(String key, Integer value){ - + private static JsonObject getJsonObject(String key, Integer value) + { JsonObject jsonObject = new JsonObject(); - jsonObject.put(ParamConfig.getLabelParam(), key); - jsonObject.put(ParamConfig.getLabelCountParam(), value); + jsonObject.put(ParamConfig.getLABELPARAM(), key); + jsonObject.put(ParamConfig.getLABELCOUNTPARAM(), value); return jsonObject; } - private static Map getLabelByClass(JsonArray labelPointData){ - + private static Map getLabelByClass(JsonArray labelPointData) + { Map labelByClass = new HashMap<>(); ArrayList labels = new ArrayList<>(); - for (int i = 0; i < labelPointData.size(); i++) { + for (int i = 0; i < labelPointData.size(); i++) + { JsonObject jsonArray = labelPointData.getJsonObject(i); String label = jsonArray.getString("label"); labels.add(label); } - for (String label : labels) { - + for (String label : labels) + { Integer count = labelByClass.get(label); - if (count == null) { + if (count == null) + { count = 0; } @@ -153,11 +169,12 @@ private static Map getLabelByClass(JsonArray labelPointData){ return labelByClass; } - private static List getAnnotationList(Set imageUUID, Map uuidAnnotationDict){ - + private static List getAnnotationList(Set imageUUID, Map uuidAnnotationDict) + { List annotationList = new ArrayList<>(); - for (String s : imageUUID) { + for (String s : imageUUID) + { annotationList.add(uuidAnnotationDict.get(s)); } From 5ab64c3d83217809f594aad507093d76a4a2340b Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Wed, 1 Sep 2021 14:49:15 +0800 Subject: [PATCH 10/18] :pencil2: Fix typo --- .../java/ai/classifai/database/portfolio/PortfolioDbQuery.java | 2 +- .../java/ai/classifai/database/portfolio/PortfolioVerticle.java | 2 +- .../src/main/java/ai/classifai/router/V2Endpoint.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java index 5687d2599..e34d12daf 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java @@ -59,6 +59,6 @@ public class PortfolioDbQuery @Getter private static final String updateLastModifiedDate = "UPDATE Portfolio SET current_version = ? WHERE project_id = ?"; - @Getter private static final String retrieveProjectStatistic = "retrieveProjectStatistic"; + @Getter private static final String RETRIEVEPROJECTSTATISTIC = "retrieveProjectStatistic"; } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index 4e340d128..bcb4be11e 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -128,7 +128,7 @@ else if(action.equals(PortfolioDbQuery.getUpdateLastModifiedDate())) { this.updateLastModifiedDate(message); } - else if(action.equals(PortfolioDbQuery.getRetrieveProjectStatistic())) + else if(action.equals(PortfolioDbQuery.getRETRIEVEPROJECTSTATISTIC())) { this.getProjectStatistic(message); } diff --git a/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java b/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java index 2af3cbdd1..b090d6062 100644 --- a/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java +++ b/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java @@ -729,7 +729,7 @@ public void getProjectStatistic (RoutingContext context){ JsonObject jsonObject = new JsonObject().put(ParamConfig.getProjectIdParam(), Objects.requireNonNull(loader).getProjectId()); //load label list - DeliveryOptions statisticDataOptions = new DeliveryOptions().addHeader(ParamConfig.getActionKeyword(), PortfolioDbQuery.getRetrieveProjectStatistic()); + DeliveryOptions statisticDataOptions = new DeliveryOptions().addHeader(ParamConfig.getActionKeyword(), PortfolioDbQuery.getRETRIEVEPROJECTSTATISTIC()); vertx.eventBus().request(PortfolioDbQuery.getQueue(), jsonObject, statisticDataOptions, statisticReply -> { From 5ca3bd16eba46cbf16e84b5a00d511871b742a7a Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Thu, 2 Sep 2021 09:48:18 +0800 Subject: [PATCH 11/18] :memo: Add license --- .../ai/classifai/util/data/LabelListHandler.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index 86b34c08f..9e21f5ce3 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2021 CertifAI Sdn. Bhd. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ package ai.classifai.util.data; import ai.classifai.database.versioning.Annotation; From 9be5b1986b9acfa552fa6c269b391cc7eb3c5513 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Fri, 3 Sep 2021 09:19:20 +0800 Subject: [PATCH 12/18] :recycle: Refactor code to optimize performance and update param follow back code base format --- .../database/portfolio/PortfolioDbQuery.java | 2 +- .../database/portfolio/PortfolioVerticle.java | 10 +- .../java/ai/classifai/router/V2Endpoint.java | 2 +- .../java/ai/classifai/util/ParamConfig.java | 12 +- .../classifai/util/data/LabelListHandler.java | 123 +++++++----------- 5 files changed, 63 insertions(+), 86 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java index e34d12daf..5687d2599 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioDbQuery.java @@ -59,6 +59,6 @@ public class PortfolioDbQuery @Getter private static final String updateLastModifiedDate = "UPDATE Portfolio SET current_version = ? WHERE project_id = ?"; - @Getter private static final String RETRIEVEPROJECTSTATISTIC = "retrieveProjectStatistic"; + @Getter private static final String retrieveProjectStatistic = "retrieveProjectStatistic"; } \ No newline at end of file diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index bcb4be11e..6a9b72a14 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -128,7 +128,7 @@ else if(action.equals(PortfolioDbQuery.getUpdateLastModifiedDate())) { this.updateLastModifiedDate(message); } - else if(action.equals(PortfolioDbQuery.getRETRIEVEPROJECTSTATISTIC())) + else if(action.equals(PortfolioDbQuery.getRetrieveProjectStatistic())) { this.getProjectStatistic(message); } @@ -680,12 +680,12 @@ public void getProjectStatistic(Message message) result.add(new JsonObject() .put(ParamConfig.getProjectNameParam(), loader.getProjectName()) - .put(ParamConfig.getLABELEDIMAGEPARAM(), LabelListHandler.getNumberOfLabeledImage()) - .put(ParamConfig.getUNLABELEDIMAGEPARAM(), LabelListHandler.getNumberOfUnLabeledImage()) - .put(ParamConfig.getLABELPERCLASSINPROJECTPARAM(), labelPerClassInProject)); + .put(ParamConfig.getLabeledImageParam(), LabelListHandler.getNumberOfLabeledImage()) + .put(ParamConfig.getUnlabeledImageParam(), LabelListHandler.getNumberOfUnLabeledImage()) + .put(ParamConfig.getLabelPerClassInProject(), labelPerClassInProject)); JsonObject response = ReplyHandler.getOkReply(); - response.put(ParamConfig.getSTATISTICDATAPARAM(), result); + response.put(ParamConfig.getStatisticData(), result); message.replyAndRequest(response); } diff --git a/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java b/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java index b090d6062..2af3cbdd1 100644 --- a/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java +++ b/classifai-core/src/main/java/ai/classifai/router/V2Endpoint.java @@ -729,7 +729,7 @@ public void getProjectStatistic (RoutingContext context){ JsonObject jsonObject = new JsonObject().put(ParamConfig.getProjectIdParam(), Objects.requireNonNull(loader).getProjectId()); //load label list - DeliveryOptions statisticDataOptions = new DeliveryOptions().addHeader(ParamConfig.getActionKeyword(), PortfolioDbQuery.getRETRIEVEPROJECTSTATISTIC()); + DeliveryOptions statisticDataOptions = new DeliveryOptions().addHeader(ParamConfig.getActionKeyword(), PortfolioDbQuery.getRetrieveProjectStatistic()); vertx.eventBus().request(PortfolioDbQuery.getQueue(), jsonObject, statisticDataOptions, statisticReply -> { diff --git a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java index 84fe1597c..8e54d58c6 100644 --- a/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java +++ b/classifai-core/src/main/java/ai/classifai/util/ParamConfig.java @@ -95,12 +95,12 @@ public class ParamConfig @Getter private static final String createdDateParam = "created_date"; @Getter private static final String lastModifiedDate = "last_modified_date"; @Getter private static final String isRootPathValidParam = "root_path_valid"; - @Getter private static final String LABELEDIMAGEPARAM = "labeled_image"; - @Getter private static final String UNLABELEDIMAGEPARAM = "unlabeled_image"; - @Getter private static final String LABELPERCLASSINPROJECTPARAM = "label_Per_Class_In_Project"; - @Getter private static final String LABELPARAM = "label"; - @Getter private static final String LABELCOUNTPARAM = "count"; - @Getter private static final String STATISTICDATAPARAM = "statistic_data"; + @Getter private static final String labeledImageParam = "labeled_image"; + @Getter private static final String unlabeledImageParam = "unlabeled_image"; + @Getter private static final String labelPerClassInProject = "label_per_class_in_project"; + @Getter private static final String labelParam = "label"; + @Getter private static final String labelCountParam = "count"; + @Getter private static final String statisticData = "statistic_data"; @Getter private static final String statusParam = "status"; diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index 9e21f5ce3..9296eb7d3 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -22,7 +22,10 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.util.*; +import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * Getting information of labeled and unlabeled image @@ -38,35 +41,36 @@ private LabelListHandler() throw new IllegalStateException("Utility class"); } - private static final ArrayList> totalImage = new ArrayList<>(); + private static final List> totalImage = new ArrayList<>(); // Handling the number of labeled and unlabeled image public static void getImageLabeledStatus(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); // key for each project List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict);// a list of annotation - ArrayList labeledImageList= new ArrayList<>(); - ArrayList unlabeledImageList = new ArrayList<>(); - // Every annotation represent an image - for (Annotation annotation : annotationList) - { - LinkedHashMap annotationDataMap = getAnnotationData(annotation.getAnnotationDictDbFormat()); // version uuid, annotation data - JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDataMap.values())); + List labelPointData = annotationList.stream() + .map(Annotation::getAnnotationDictDbFormat) + .map(LabelListHandler::getAnnotationData) + .map(Map::values) + .map(String::valueOf) + .map(LabelListHandler::getAnnotationStatus) + .collect(Collectors.toList()); - if (getAnnotatedImage(labelPointData) != null) - { - labeledImageList.add(labelPointData); - } - else - { - unlabeledImageList.add(labelPointData); - } + Predicate isEmpty = JsonArray::isEmpty; + Predicate notEmpty = isEmpty.negate(); - } + List labeledImageList = labelPointData.stream() + .filter(notEmpty) + .collect(Collectors.toList()); + + List unlabeledImageList = labelPointData.stream() + .filter(isEmpty) + .collect(Collectors.toList()); totalImage.add(0, labeledImageList); totalImage.add(1, unlabeledImageList); + } public static Integer getNumberOfLabeledImage() @@ -79,14 +83,14 @@ public static Integer getNumberOfUnLabeledImage() return totalImage.get(1).size(); } - private static LinkedHashMap getAnnotationData(String annotationDict) + private static LinkedHashMap getAnnotationData(String annotationDict) { LinkedHashMap annotationDataMap = new LinkedHashMap<>(); String s = StringUtils.removeStart(StringUtils.removeEnd(annotationDict, "]"), "["); JsonObject annotationDictJsonObject = new JsonObject(s); String versionUuid = annotationDictJsonObject.getString(ParamConfig.getVersionUuidParam()); - JsonObject annotationData= annotationDictJsonObject.getJsonObject(ParamConfig.getAnnotationDataParam()); + JsonObject annotationData = annotationDictJsonObject.getJsonObject(ParamConfig.getAnnotationDataParam()); annotationDataMap.put(versionUuid, annotationData); @@ -104,45 +108,28 @@ private static JsonArray getAnnotationStatus(String annotationDictValue) } - private static Number getAnnotatedImage(JsonArray labelPointData) - { - if(!labelPointData.isEmpty()) - { - return labelPointData.size(); - } - else - { - return null; - } - - } - public static JsonArray getLabelPerClassInProject(Map uuidAnnotationDict) { Set imageUUID = uuidAnnotationDict.keySet(); List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); - Map labelByClass; - List> labelByClassList = new ArrayList<>(); - JsonObject labelCountJsonObject; JsonArray labelPerClassInProjectJsonArray = new JsonArray(); - for (Annotation annotation : annotationList) - { - LinkedHashMap annotationDataMap = getAnnotationData(annotation.getAnnotationDictDbFormat()); - JsonArray labelPointData = getAnnotationStatus(String.valueOf(annotationDataMap.values())); - labelByClass = getLabelByClass(labelPointData); - labelByClassList.add(labelByClass); - } + List> labelByClassList = annotationList.stream() + .map(Annotation::getAnnotationDictDbFormat) + .map(LabelListHandler::getAnnotationData) + .map(Map::values) + .map(String::valueOf) + .map(LabelListHandler::getAnnotationStatus) + .map(LabelListHandler::getLabelByClass) + .collect(Collectors.toList()); - Map sumLabelByClass = labelByClassList.stream() + Map sumLabelByClass = labelByClassList.stream() .flatMap(m -> m.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum)); - for(Map.Entry m : sumLabelByClass.entrySet()) - { - labelCountJsonObject = getJsonObject(m.getKey(), m.getValue()); - labelPerClassInProjectJsonArray.add(labelCountJsonObject); - } + sumLabelByClass.entrySet().stream() + .map(m -> getJsonObject(m.getKey(), m.getValue())) + .forEach(labelPerClassInProjectJsonArray::add); return labelPerClassInProjectJsonArray; @@ -151,49 +138,39 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn private static JsonObject getJsonObject(String key, Integer value) { JsonObject jsonObject = new JsonObject(); - jsonObject.put(ParamConfig.getLABELPARAM(), key); - jsonObject.put(ParamConfig.getLABELCOUNTPARAM(), value); + jsonObject.put(ParamConfig.getLabelParam(), key); + jsonObject.put(ParamConfig.getLabelCountParam(), value); return jsonObject; } - private static Map getLabelByClass(JsonArray labelPointData) + private static Map getLabelByClass(JsonArray labelPointData) { - Map labelByClass = new HashMap<>(); - ArrayList labels = new ArrayList<>(); - - for (int i = 0; i < labelPointData.size(); i++) - { - JsonObject jsonArray = labelPointData.getJsonObject(i); - String label = jsonArray.getString("label"); - labels.add(label); - } + Map labelByClass = new HashMap<>(); - for (String label : labels) - { - Integer count = labelByClass.get(label); + List labels = IntStream.range(0, labelPointData.size()) + .mapToObj(labelPointData::getJsonObject) + .map(m -> m.getString("label")) + .collect(Collectors.toList()); + Consumer action = s -> { + Integer count = labelByClass.get(s); if (count == null) { count = 0; } + labelByClass.put(s, count + 1); + }; - labelByClass.put(label, count + 1); - } + labels.forEach(action); return labelByClass; + } private static List getAnnotationList(Set imageUUID, Map uuidAnnotationDict) { - List annotationList = new ArrayList<>(); - - for (String s : imageUUID) - { - annotationList.add(uuidAnnotationDict.get(s)); - } - - return annotationList; + return imageUUID.stream().map(uuidAnnotationDict::get).collect(Collectors.toList()); } From a9a4a12c690ce6045e4642063bfdd8725f1e07c5 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Fri, 3 Sep 2021 10:42:53 +0800 Subject: [PATCH 13/18] :pencil2: Remove wrongly inserted action --- .../database/annotation/bndbox/BoundingBoxVerticle.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java b/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java index 4c9db9307..6ba579b58 100644 --- a/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java @@ -82,10 +82,6 @@ else if(action.equals(AnnotationQuery.getRenameProjectData())) { this.renameProjectData(message); } - else if(action.equals(AnnotationQuery.getRetrieveAllProjects())) - { - this.renameProjectData(message); - } else { log.error("BoundingBox Verticle query error. Action did not have an assigned function for handling."); From 760a5d71db2d36f966830f6f3d4611e608355386 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Fri, 3 Sep 2021 17:07:26 +0800 Subject: [PATCH 14/18] :recycle: Add on unused label info --- .../database/portfolio/PortfolioVerticle.java | 2 +- .../classifai/util/data/LabelListHandler.java | 40 +++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java index 6a9b72a14..02612e862 100644 --- a/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/portfolio/PortfolioVerticle.java @@ -669,7 +669,7 @@ public void getProjectStatistic(Message message) File projectPath = loader.getProjectPath(); LabelListHandler.getImageLabeledStatus(loader.getUuidAnnotationDict()); - JsonArray labelPerClassInProject = LabelListHandler.getLabelPerClassInProject(loader.getUuidAnnotationDict()); + JsonArray labelPerClassInProject = LabelListHandler.getLabelPerClassInProject(loader.getUuidAnnotationDict(), projectId); List result = new ArrayList<>(); diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index 9296eb7d3..4ab28ca0c 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -16,7 +16,9 @@ package ai.classifai.util.data; import ai.classifai.database.versioning.Annotation; +import ai.classifai.loader.ProjectLoader; import ai.classifai.util.ParamConfig; +import ai.classifai.util.project.ProjectHandler; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import lombok.extern.slf4j.Slf4j; @@ -108,7 +110,7 @@ private static JsonArray getAnnotationStatus(String annotationDictValue) } - public static JsonArray getLabelPerClassInProject(Map uuidAnnotationDict) + public static JsonArray getLabelPerClassInProject(Map uuidAnnotationDict, String projectId) { Set imageUUID = uuidAnnotationDict.keySet(); List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); @@ -123,6 +125,10 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn .map(LabelListHandler::getLabelByClass) .collect(Collectors.toList()); + List> unUsedLabelList = getUnUsedLabelList(projectId, labelByClassList); + + labelByClassList.addAll(unUsedLabelList); + Map sumLabelByClass = labelByClassList.stream() .flatMap(m -> m.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum)); @@ -154,12 +160,7 @@ private static Map getLabelByClass(JsonArray labelPointData) .collect(Collectors.toList()); Consumer action = s -> { - Integer count = labelByClass.get(s); - if (count == null) - { - count = 0; - } - labelByClass.put(s, count + 1); + labelByClass.put(s, Collections.frequency(labels, s)); }; labels.forEach(action); @@ -173,5 +174,30 @@ private static List getAnnotationList(Set imageUUID, Map> getUnUsedLabelList (String projectId, List> labelByClassList) + { + ProjectLoader loader = Objects.requireNonNull(ProjectHandler.getProjectLoader(projectId)); + List oriLabelList = loader.getLabelList(); + + List usedLabel = labelByClassList.stream() + .flatMap(m -> m.entrySet().stream()) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + List filterList = oriLabelList.stream() + .filter(s -> !usedLabel.contains(s)) + .collect(Collectors.toList()); + + Map unUsedLabels = new HashMap<>(); + List> unUsedLabelList = new ArrayList<>(); + + for(String label : filterList){ + unUsedLabels.put(label, 0); + unUsedLabelList.add(unUsedLabels); + } + + return unUsedLabelList; + } + } From 179f7f6c6bc15278a6501ff98530b79039aff88f Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Fri, 3 Sep 2021 17:34:51 +0800 Subject: [PATCH 15/18] :recycle: Remove code smell --- .../java/ai/classifai/util/data/LabelListHandler.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index 4ab28ca0c..f075ca0f4 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -159,9 +159,7 @@ private static Map getLabelByClass(JsonArray labelPointData) .map(m -> m.getString("label")) .collect(Collectors.toList()); - Consumer action = s -> { - labelByClass.put(s, Collections.frequency(labels, s)); - }; + Consumer action = s -> labelByClass.put(s, Collections.frequency(labels, s)); labels.forEach(action); @@ -178,6 +176,8 @@ private static List> getUnUsedLabelList (String projectId, { ProjectLoader loader = Objects.requireNonNull(ProjectHandler.getProjectLoader(projectId)); List oriLabelList = loader.getLabelList(); + Map unUsedLabels = new HashMap<>(); + List> unUsedLabelList = new ArrayList<>(); List usedLabel = labelByClassList.stream() .flatMap(m -> m.entrySet().stream()) @@ -188,9 +188,6 @@ private static List> getUnUsedLabelList (String projectId, .filter(s -> !usedLabel.contains(s)) .collect(Collectors.toList()); - Map unUsedLabels = new HashMap<>(); - List> unUsedLabelList = new ArrayList<>(); - for(String label : filterList){ unUsedLabels.put(label, 0); unUsedLabelList.add(unUsedLabels); From 93439346228b247a8ce4cbfa368bae7b82414679 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Mon, 6 Sep 2021 12:10:26 +0800 Subject: [PATCH 16/18] :speech_balloon: Add comment on unclear functions --- .../classifai/util/data/LabelListHandler.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index f075ca0f4..c0f371217 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -51,6 +51,7 @@ public static void getImageLabeledStatus(Map uuidAnnotationD Set imageUUID = uuidAnnotationDict.keySet(); // key for each project List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict);// a list of annotation + // To get a list of JsonArray, whereby each JsonArray contain annotation parameters of an image List labelPointData = annotationList.stream() .map(Annotation::getAnnotationDictDbFormat) .map(LabelListHandler::getAnnotationData) @@ -62,10 +63,12 @@ public static void getImageLabeledStatus(Map uuidAnnotationD Predicate isEmpty = JsonArray::isEmpty; Predicate notEmpty = isEmpty.negate(); + // Checking If a JsonArray is not empty, annotation was performed on an image List labeledImageList = labelPointData.stream() .filter(notEmpty) .collect(Collectors.toList()); + // Checking if a JsonArray is empty, annotation was not performed on an image List unlabeledImageList = labelPointData.stream() .filter(isEmpty) .collect(Collectors.toList()); @@ -85,6 +88,7 @@ public static Integer getNumberOfUnLabeledImage() return totalImage.get(1).size(); } + // To extract the annotation data and version uuid of an Image private static LinkedHashMap getAnnotationData(String annotationDict) { LinkedHashMap annotationDataMap = new LinkedHashMap<>(); @@ -103,10 +107,12 @@ private static LinkedHashMap getAnnotationData(String annotat private static JsonArray getAnnotationStatus(String annotationDictValue) { String s = StringUtils.removeStart(StringUtils.removeEnd(annotationDictValue, "]"), "["); - JsonObject annotationDataJsonObject = new JsonObject(s); //annotation, img_x, img_y, img_w, img_h - // To get annotation parameters - return annotationDataJsonObject.getJsonArray(ParamConfig.getAnnotationParam());// x1, y1, x2, y2, color, distToImg, label ,id + // To get the data : annotation, img_x, img_y, img_w, img_h + JsonObject annotationDataJsonObject = new JsonObject(s); + + // To get annotation parameters : x1, y1, x2, y2, color, distToImg, label ,id + return annotationDataJsonObject.getJsonArray(ParamConfig.getAnnotationParam()); } @@ -116,6 +122,7 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn List annotationList = getAnnotationList(imageUUID, uuidAnnotationDict); JsonArray labelPerClassInProjectJsonArray = new JsonArray(); + // To get list of map whereby each map represent a label and its number of occurrence on an Image List> labelByClassList = annotationList.stream() .map(Annotation::getAnnotationDictDbFormat) .map(LabelListHandler::getAnnotationData) @@ -125,10 +132,12 @@ public static JsonArray getLabelPerClassInProject(Map uuidAn .map(LabelListHandler::getLabelByClass) .collect(Collectors.toList()); + // Collect all the labels that not used in annotation List> unUsedLabelList = getUnUsedLabelList(projectId, labelByClassList); labelByClassList.addAll(unUsedLabelList); + // To sum all occurrences of each label of respective class in the project Map sumLabelByClass = labelByClassList.stream() .flatMap(m -> m.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::sum)); @@ -154,11 +163,13 @@ private static Map getLabelByClass(JsonArray labelPointData) { Map labelByClass = new HashMap<>(); + // To get a list label on an Image List labels = IntStream.range(0, labelPointData.size()) .mapToObj(labelPointData::getJsonObject) .map(m -> m.getString("label")) .collect(Collectors.toList()); + // To get each label with its occurrence into a map Consumer action = s -> labelByClass.put(s, Collections.frequency(labels, s)); labels.forEach(action); @@ -179,11 +190,13 @@ private static List> getUnUsedLabelList (String projectId, Map unUsedLabels = new HashMap<>(); List> unUsedLabelList = new ArrayList<>(); + // To get a list of label that used in annotation List usedLabel = labelByClassList.stream() .flatMap(m -> m.entrySet().stream()) .map(Map.Entry::getKey) .collect(Collectors.toList()); + // To filter out the unused label from original label list List filterList = oriLabelList.stream() .filter(s -> !usedLabel.contains(s)) .collect(Collectors.toList()); From 539cdb53c4b225288772853faa1c2329b1ef3290 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Mon, 6 Sep 2021 12:48:08 +0800 Subject: [PATCH 17/18] :pencil2: Fix typo --- .../main/java/ai/classifai/util/data/LabelListHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java index c0f371217..b72794ecb 100644 --- a/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java +++ b/classifai-core/src/main/java/ai/classifai/util/data/LabelListHandler.java @@ -186,7 +186,7 @@ private static List getAnnotationList(Set imageUUID, Map> getUnUsedLabelList (String projectId, List> labelByClassList) { ProjectLoader loader = Objects.requireNonNull(ProjectHandler.getProjectLoader(projectId)); - List oriLabelList = loader.getLabelList(); + List originalLabelList = loader.getLabelList(); Map unUsedLabels = new HashMap<>(); List> unUsedLabelList = new ArrayList<>(); @@ -197,7 +197,7 @@ private static List> getUnUsedLabelList (String projectId, .collect(Collectors.toList()); // To filter out the unused label from original label list - List filterList = oriLabelList.stream() + List filterList = originalLabelList.stream() .filter(s -> !usedLabel.contains(s)) .collect(Collectors.toList()); From 242b0513f13a39839456be5c77e7e0fb1b835001 Mon Sep 17 00:00:00 2001 From: Lai Yip Khen Date: Mon, 6 Sep 2021 13:04:30 +0800 Subject: [PATCH 18/18] :hammer: Optimize import --- .../bndbox/BoundingBoxVerticle.java | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java b/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java index 6ba579b58..deff46fca 100644 --- a/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java +++ b/classifai-core/src/main/java/ai/classifai/database/annotation/bndbox/BoundingBoxVerticle.java @@ -15,25 +15,23 @@ */ package ai.classifai.database.annotation.bndbox; -import ai.classifai.database.DbConfig; -import ai.classifai.database.annotation.AnnotationQuery; -import ai.classifai.database.annotation.AnnotationVerticle; -import ai.classifai.util.ParamConfig; -import ai.classifai.util.message.ErrorCodes; -import ai.classifai.util.type.AnnotationHandler; -import ai.classifai.util.type.AnnotationType; -import ai.classifai.util.type.database.H2; -import ai.classifai.util.type.database.RelationalDb; -import io.vertx.core.Promise; -import io.vertx.core.Vertx; -import io.vertx.core.eventbus.Message; -import io.vertx.core.json.JsonObject; -import io.vertx.jdbcclient.JDBCPool; -import io.vertx.sqlclient.Row; -import io.vertx.sqlclient.RowSet; -import lombok.extern.slf4j.Slf4j; + import ai.classifai.database.DbConfig; + import ai.classifai.database.annotation.AnnotationQuery; + import ai.classifai.database.annotation.AnnotationVerticle; + import ai.classifai.util.ParamConfig; + import ai.classifai.util.message.ErrorCodes; + import ai.classifai.util.type.AnnotationHandler; + import ai.classifai.util.type.AnnotationType; + import ai.classifai.util.type.database.H2; + import ai.classifai.util.type.database.RelationalDb; + import io.vertx.core.Promise; + import io.vertx.core.Vertx; + import io.vertx.core.eventbus.Message; + import io.vertx.core.json.JsonObject; + import io.vertx.jdbcclient.JDBCPool; + import lombok.extern.slf4j.Slf4j; -/** + /** * Bounding Box Verticle * * @author codenamewei