Skip to content

Commit

Permalink
Feature: add Java implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Riccardo Gallina committed Mar 30, 2022
1 parent a41b025 commit da1d099
Show file tree
Hide file tree
Showing 12 changed files with 428 additions and 19 deletions.
20 changes: 18 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 47,29 @@ stages:

#-------------- Base CI --------------

.base_ci: # Base CI
rules:
- if: '$CI_COMMIT_BRANCH == "master" || $CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- when: on_success

.base_docker: # Base CI for docker stage
stage: docker-base
image: docker:19.03.11-git
variables:
DOCKER_DRIVER: overlay2
DOCKER_FILES: docker/Dockerfile
rules:
- if: '$CI_COMMIT_BRANCH == "master" || $CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- changes:
- docker/Dockerfile
tags:
- build
needs: ["mirror-pull"]

.base_env_check: # Base CI env-check stage
extends: .base_ci
stage: env-check
image: docker:19.03.11
variables:
Expand All @@ -75,6 84,7 @@ stages:
- build

.base_build: # Base CI for build stage
extends: .base_ci
stage: build
image: $BUILD_IMAGE
tags:
Expand All @@ -95,6 105,7 @@ stages:
# - if the hash is the same, then do nothing
# - if the hash is different, then we pull the github develop branch into gitlab's and push it
mirror-pull:
extends: .base_ci
stage: setup
script:
- *git_auth
Expand Down Expand Up @@ -136,6 147,8 @@ docker-build-cpu:
DOCKER_DRIVER: overlay2
DOCKER_FILES: docker/Dockerfile.cpu,docker/Dockerfile
rules:
- if: '$CI_COMMIT_BRANCH == "master" || $CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- changes:
- docker/Dockerfile.cpu
- docker/Dockerfile
Expand All @@ -154,6 167,8 @@ docker-build-gpu:
DOCKER_DRIVER: overlay2
DOCKER_FILES: docker/Dockerfile.gpu,docker/Dockerfile
rules:
- if: '$CI_COMMIT_BRANCH == "master" || $CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- changes:
- docker/Dockerfile.gpu
- docker/Dockerfile
Expand All @@ -172,6 187,8 @@ docker-build-android:
DOCKER_DRIVER: overlay2
DOCKER_FILES: docker/Dockerfile.android,docker/Dockerfile
rules:
- if: '$CI_COMMIT_BRANCH == "master" || $CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- changes:
- docker/Dockerfile.android
- docker/Dockerfile
Expand Down Expand Up @@ -237,8 254,7 @@ build-python:
build-java:
extends: .base_build
script:
- echo "Implement me!"
# - ./build.sh -t x86_64 -jni --clean
- ./build.sh -t x86_64 -jni --clean

build-golang:
extends: .base_build
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 87,11 @@ To build `Python` apps for `aarch64-linux-gnu` target:
./build.sh -t aarch64-linux-gnu -py --clean
```

To build `Java` apps for `x86_64` target:
```bash
./build.sh -t x86_64 -jni --clean
```

If `--clean` is not specified, the existing `oneML` artifacts will be used and
the old build files will not be deleted.

Expand Down Expand Up @@ -132,6 137,11 @@ To build `Python` apps for `msvc-x64` target:
build.bat -t msvc-x64 -py --clean
```

To build `Java` apps for `msvc-x64` target:
```batch
build.bat -t msvc-x64 -jni --clean
```

If `--clean` is not specified, the existing `oneML` artifacts will be used and
the old build files will not be deleted.

Expand Down
43 changes: 43 additions & 0 deletions apps/java/FaceDetectorApp.java
Original file line number Diff line number Diff line change
@@ -0,0 1,43 @@
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.sertiscorp.oneml.face.*;

public class FaceDetectorApp {

public static void main(String[] args) throws IOException {
Path basePath = Paths.get("", "../../assets/images");
String path = basePath "/face-detect-set/face/0.jpg";

LicenseManager manager = new LicenseManager();
manager.activateTrial();
FaceDetector detector = new FaceDetector(manager);
Utils utils = new Utils(manager);

Image img = utils.readImageCV(path);
FaceDetectorResult result = detector.detect(img);
System.out.println("Faces: " result.getSize());

BBoxList boxes = result.getBBoxes();
Landmark5List landmarks = result.getLandmarks();
ScoreList scores = result.getScores();
FacePoseList poses = result.getPoses();

for (int i = 0; i < result.getSize(); i ) {
System.out.println("Face " i);
System.out.println(String.format("Score: %.6f", scores.get(i)));
System.out.println("Pose: " poses.get(i));

BBox box = boxes.get(i);
String out = String.format("BBox: [(%.6f, %.6f), (%.6f, %.6f)]", box.getTop(), box.getLeft(), box.getBottom(), box.getRight());
System.out.println(out);

int n_landmarks = Face.getLandmarkSize();
Landmark5 landmark = landmarks.get(i);
for (int j = 0; j < n_landmarks; j ) {
System.out.println(String.format("Landmark %d: (%.6f, %.6f)", j, landmark.getX().get(j), landmark.getY().get(j)));
}
}
}
}
47 changes: 47 additions & 0 deletions apps/java/FaceEmbedderApp.java
Original file line number Diff line number Diff line change
@@ -0,0 1,47 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;

import java.util.List;
import java.util.StringJoiner;

import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.Collectors;
import java.util.function.Supplier;

import org.sertiscorp.oneml.face.*;

public class FaceEmbedderApp {

static String joinAsString(Iterable<Double> it) {
StringJoiner joiner = new StringJoiner(", ", "[", "]");
for (Double i: it) {
joiner.add(String.format("%.6f", i));
}

return joiner.toString();
}

public static void main(String[] args) throws IOException {
Path basePath = Paths.get("", "../../assets/images");
String path = basePath "/register-set/Colin_Powell/colin_powell_0074.jpg";

LicenseManager manager = new LicenseManager();
manager.activateTrial();
FaceEmbedder embedder = new FaceEmbedder(manager);
Utils utils = new Utils(manager);

Image img = utils.readImageCV(path);
FaceEmbedderResult result = embedder.embed(img);

System.out.println("Embedding size: " Face.getEmbeddingSize());

float[] embedding = result.getEmbedding();
Supplier<DoubleStream> supplier = () -> IntStream.range(0, embedding.length).mapToDouble(i -> embedding[i]);
List<Double> sample = supplier.get().limit(5).boxed().collect(Collectors.toList());

System.out.println("Embedding sample: " joinAsString(sample));
System.out.println(String.format("Embedding sum: %.5f", supplier.get().sum()));
}
}
106 changes: 106 additions & 0 deletions apps/java/FaceIdApp.java
Original file line number Diff line number Diff line change
@@ -0,0 1,106 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;

import java.util.List;
import java.util.StringJoiner;

import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.Collectors;
import java.util.function.Supplier;

import org.sertiscorp.oneml.face.*;

public class FaceIdApp {

static String joinAsString(Iterable<Double> it) {
StringJoiner joiner = new StringJoiner(", ", "[", "]");
for (Double i: it) {
joiner.add(String.format("%.6f", i));
}

return joiner.toString();
}

static void print(FaceIdResult result) {
System.out.println("Is identifiable: " booleanToInt(result.isIdentifiable()));
System.out.println("Id: " result.getId());
System.out.println(String.format("Nearest node distance: %.6f", result.getNearestNodeDistance()));
System.out.println(String.format("Combined distance: %.6f", result.getCombinedDistance()));
}

static void print(FaceIdResultList results) {
for (FaceIdResult result: results) {
print(result);
}
}

static int booleanToInt(boolean val) {
return val ? 1 : 0;
}

public static void main(String[] args) throws IOException {
Path basePath = Paths.get("", "../../assets/images");

LicenseManager manager = new LicenseManager();
manager.activateTrial();
Utils utils = new Utils(manager);

String path1 = basePath "/register-set/Colin_Powell/colin_powell_0074.jpg";
Image img1 = utils.readImageCV(path1);

String path2 = basePath "/register-set/Colin_Powell/colin_powell_0078.jpg";
Image img2 = utils.readImageCV(path2);

String path3 = basePath "/register-set/George_Robertson/george_robertson_0000.jpg";
Image img3 = utils.readImageCV(path3);

String path4 = basePath "/register-set/George_Robertson/george_robertson_0002.jpg";
Image img4 = utils.readImageCV(path4);

FaceEmbedder embedder = new FaceEmbedder(manager);
FaceId faceId = new FaceId(embedder, manager);

// isTheSamePerson
boolean same1 = faceId.isTheSamePerson(img1, img2);
System.out.println("Is the same person: " booleanToInt(same1));

FaceEmbedderResult result = embedder.embed(img1);
SamePersonResult sameResult = faceId.isTheSamePerson(result.getEmbedding(), img2);
System.out.println("Is the same person: " booleanToInt(sameResult.getSame()));

// registerId
int size1 = faceId.registerId("Colin_Powell", result.getEmbedding());
System.out.println("Registered size is: " size1);

Embedding emb_ = faceId.registerId("George_Robertson", img3);
float[] emb = emb_.toArray();
Supplier<DoubleStream> supplier = () -> IntStream.range(0, emb.length).mapToDouble(i -> emb[i]);
List<Double> sample = supplier.get().limit(5).boxed().collect(Collectors.toList());
System.out.println("Registered emb is: " joinAsString(sample));

// predict
print(faceId.predict(img2));

// updateEmbeddingDynamically
faceId.updateEmbeddingDynamically("George_Robertson", img3, emb);
print(faceId.predict(img4));

faceId.updateEmbeddingDynamically("Colin_Powell", sameResult.getEmbedding(), result.getEmbedding());

print(faceId.predict(img1));

// updateEmbedding
faceId.updateEmbedding("George_Robertson", emb);
print(faceId.predict(img3));

// removeId
faceId.removeId("George_Robertson");
faceId.removeId("Colin_Powell");

// getIds
IdList idList = faceId.getIds();
System.out.println("Gallery size: " idList.size());
}
}
72 changes: 72 additions & 0 deletions apps/java/FaceVerificationApp.java
Original file line number Diff line number Diff line change
@@ -0,0 1,72 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.sertiscorp.oneml.face.*;

public class FaceVerificationApp {

static int booleanToInt(boolean val) {
return val ? 1 : 0;
}

public static void main(String[] args) throws IOException {
LicenseManager manager = new LicenseManager();
manager.activateTrial();

Path basePath = Paths.get("", "../../assets/images");
File file1 = new File(basePath "/register-set/Colin_Powell/colin_powell_0074.jpg");
File file2 = new File(basePath "/evaluate-set/Colin_Powell/colin_powell_0097.jpg");
File file3 = new File(basePath "/register-set/George_Robertson/george_robertson_0000.jpg");
File file4 = new File(basePath "/evaluate-set/George_Robertson/george_robertson_0009.jpg");

FaceEmbedder embedder = new FaceEmbedder(manager);
FaceId faceId = new FaceId(embedder, manager);
FaceDetector detector = new FaceDetector(manager);
Utils utils = new Utils(manager);

Image img1 = utils.readImageCV(file1.getAbsolutePath());
Image img2 = utils.readImageCV(file2.getAbsolutePath());
Image img3 = utils.readImageCV(file3.getAbsolutePath());
Image img4 = utils.readImageCV(file4.getAbsolutePath());

ImageBatch register_batch = new ImageBatch();
register_batch.add(img1);
register_batch.add(img3);

ImageBatch eval_batch = new ImageBatch();
eval_batch.add(img2);
eval_batch.add(img4);

FaceDetectorResultList register_results = detector.detect(register_batch);
FaceDetectorResultList eval_results = detector.detect(eval_batch);

Image align_img1 = utils.cropAlignFaceLandmark(img1, register_results.get(0).getLandmarks().get(0));
Image align_img3 = utils.cropAlignFaceLandmark(img3, register_results.get(1).getLandmarks().get(0));
Image align_img2 = utils.cropAlignFaceLandmark(img2, eval_results.get(0).getLandmarks().get(0));
Image align_img4 = utils.cropAlignFaceLandmark(img4, eval_results.get(1).getLandmarks().get(0));

faceId.registerId("colin_powell", align_img1);
faceId.registerId("george_robertson", align_img3);

ImageBatch predict_batch = new ImageBatch();
predict_batch.add(align_img2);
predict_batch.add(align_img4);
FaceIdResultList results = faceId.predict(predict_batch);

// Run with registration & predict style to print scores for validating with other language applications
// since isTheSamePerson API doesn't provide any score.
System.out.println("First person nearest node distance: " String.format("%.8f", results.get(0).getNearestNodeDistance()));
System.out.println("Second person nearest node distance: " String.format("%.8f", results.get(1).getNearestNodeDistance()));
System.out.println("First person: " results.get(0).getId());
System.out.println("Second person: " results.get(1).getId());

// Also test the actual face verification API (IsTheSamePerson)
boolean same1 = faceId.isTheSamePerson(img1, img2);
System.out.println("Is the same person (colin_powell): " booleanToInt(same1));

boolean same2 = faceId.isTheSamePerson(img3, img4);
System.out.println("Is the same person (george_robertson): " booleanToInt(same2));
}
}
Loading

0 comments on commit da1d099

Please sign in to comment.