From fac49bed793bfdc153ad55f11cb46d1872ccf7f5 Mon Sep 17 00:00:00 2001 From: Calvin <179209347@qq.com> Date: Mon, 29 Nov 2021 00:06:04 +0800 Subject: [PATCH] no message --- .../camera_face_sdk/camera-face-sdk.iml | 216 +++++++++++++++++ .../lib/aias-face-lib-0.1.0.jar | Bin 6492 -> 0 bytes 4_video_sdks/camera_face_sdk/pom.xml | 11 +- .../example/CameraFaceDetectionExample.java | 2 +- .../calvin/example/utils/FaceDetection.java | 104 ++++++++ .../camera-facemask-sdk.iml | 216 +++++++++++++++++ .../lib/aias-mask-lib-0.1.0.jar | Bin 9200 -> 0 bytes 4_video_sdks/camera_facemask_sdk/pom.xml | 12 +- .../CameraFaceMaskDetectionExample.java | 6 +- .../me/aias/example/utils/FaceDetection.java | 104 ++++++++ .../me/aias/example/utils/FaceMaskDetect.java | 98 ++++++++ .../mp4_face_sdk/lib/aias-face-lib-0.1.0.jar | Bin 6492 -> 0 bytes 4_video_sdks/mp4_face_sdk/mp4-face-sdk.iml | 225 ++++++++++++++++++ 4_video_sdks/mp4_face_sdk/pom.xml | 12 +- .../aias/example/MP4FaceDetectionExample.java | 2 +- .../me/aias/example/utils/FaceDetection.java | 104 ++++++++ .../lib/aias-mask-lib-0.1.0.jar | Bin 9200 -> 0 bytes .../mp4_facemask_sdk/mp4-facemask-sdk.iml | 216 +++++++++++++++++ 4_video_sdks/mp4_facemask_sdk/pom.xml | 12 +- .../example/MP4FaceMaskDetectionExample.java | 6 +- .../me/aias/example/utils/FaceDetection.java | 104 ++++++++ .../me/aias/example/utils/FaceMaskDetect.java | 98 ++++++++ .../rtsp_face_sdk/lib/aias-face-lib-0.1.0.jar | Bin 6492 -> 0 bytes 4_video_sdks/rtsp_face_sdk/pom.xml | 12 +- 4_video_sdks/rtsp_face_sdk/rtsp-face-sdk.iml | 216 +++++++++++++++++ .../example/RtspFaceDetectionExample.java | 2 +- .../me/aias/example/utils/FaceDetection.java | 104 ++++++++ .../lib/aias-mask-lib-0.1.0.jar | Bin 9200 -> 0 bytes 4_video_sdks/rtsp_facemask_sdk/pom.xml | 12 +- .../rtsp_facemask_sdk/rtsp-facemask-sdk.iml | 216 +++++++++++++++++ .../example/RtspFaceMaskDetectionExample.java | 6 +- .../me/aias/example/utils/FaceDetection.java | 104 ++++++++ .../me/aias/example/utils/FaceMaskDetect.java | 98 ++++++++ 33 files changed, 2247 insertions(+), 71 deletions(-) create mode 100644 4_video_sdks/camera_face_sdk/camera-face-sdk.iml delete mode 100644 4_video_sdks/camera_face_sdk/lib/aias-face-lib-0.1.0.jar create mode 100644 4_video_sdks/camera_face_sdk/src/main/java/me/calvin/example/utils/FaceDetection.java create mode 100644 4_video_sdks/camera_facemask_sdk/camera-facemask-sdk.iml delete mode 100644 4_video_sdks/camera_facemask_sdk/lib/aias-mask-lib-0.1.0.jar create mode 100644 4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java create mode 100644 4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java delete mode 100644 4_video_sdks/mp4_face_sdk/lib/aias-face-lib-0.1.0.jar create mode 100644 4_video_sdks/mp4_face_sdk/mp4-face-sdk.iml create mode 100644 4_video_sdks/mp4_face_sdk/src/main/java/me/aias/example/utils/FaceDetection.java delete mode 100644 4_video_sdks/mp4_facemask_sdk/lib/aias-mask-lib-0.1.0.jar create mode 100644 4_video_sdks/mp4_facemask_sdk/mp4-facemask-sdk.iml create mode 100644 4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java create mode 100644 4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java delete mode 100644 4_video_sdks/rtsp_face_sdk/lib/aias-face-lib-0.1.0.jar create mode 100644 4_video_sdks/rtsp_face_sdk/rtsp-face-sdk.iml create mode 100644 4_video_sdks/rtsp_face_sdk/src/main/java/me/aias/example/utils/FaceDetection.java delete mode 100644 4_video_sdks/rtsp_facemask_sdk/lib/aias-mask-lib-0.1.0.jar create mode 100644 4_video_sdks/rtsp_facemask_sdk/rtsp-facemask-sdk.iml create mode 100644 4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java create mode 100644 4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java diff --git a/4_video_sdks/camera_face_sdk/camera-face-sdk.iml b/4_video_sdks/camera_face_sdk/camera-face-sdk.iml new file mode 100644 index 00000000..9959c3f3 --- /dev/null +++ b/4_video_sdks/camera_face_sdk/camera-face-sdk.iml @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/4_video_sdks/camera_face_sdk/lib/aias-face-lib-0.1.0.jar b/4_video_sdks/camera_face_sdk/lib/aias-face-lib-0.1.0.jar deleted file mode 100644 index 65a056bbc60fcdff616590094e226707c0204be3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6492 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 Cv2C{i diff --git a/4_video_sdks/camera_face_sdk/pom.xml b/4_video_sdks/camera_face_sdk/pom.xml index f49d999e..138b8a96 100644 --- a/4_video_sdks/camera_face_sdk/pom.xml +++ b/4_video_sdks/camera_face_sdk/pom.xml @@ -31,7 +31,7 @@ UTF-8 1.8 1.8 - 0.13.0 + 0.14.0 @@ -94,7 +94,7 @@ ai.djl.pytorch pytorch-native-auto - 1.9.0 + 1.9.1 @@ -113,13 +113,6 @@ paddlepaddle-model-zoo ${djl.version} - - aias - face-lib - 0.1.0 - system - ${project.basedir}/lib/aias-face-lib-0.1.0.jar - org.bytedeco javacv-platform diff --git a/4_video_sdks/camera_face_sdk/src/main/java/me/calvin/example/CameraFaceDetectionExample.java b/4_video_sdks/camera_face_sdk/src/main/java/me/calvin/example/CameraFaceDetectionExample.java index 2e02416a..6660ce21 100644 --- a/4_video_sdks/camera_face_sdk/src/main/java/me/calvin/example/CameraFaceDetectionExample.java +++ b/4_video_sdks/camera_face_sdk/src/main/java/me/calvin/example/CameraFaceDetectionExample.java @@ -11,7 +11,7 @@ import ai.djl.repository.zoo.Criteria; import ai.djl.repository.zoo.ModelZoo; import ai.djl.repository.zoo.ZooModel; import ai.djl.translate.TranslateException; -import me.aias.FaceDetection; +import me.calvin.example.utils.FaceDetection; import me.calvin.example.utils.OpenCVImageUtil; import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.Frame; diff --git a/4_video_sdks/camera_face_sdk/src/main/java/me/calvin/example/utils/FaceDetection.java b/4_video_sdks/camera_face_sdk/src/main/java/me/calvin/example/utils/FaceDetection.java new file mode 100644 index 00000000..cee49203 --- /dev/null +++ b/4_video_sdks/camera_face_sdk/src/main/java/me/calvin/example/utils/FaceDetection.java @@ -0,0 +1,104 @@ +package me.calvin.example.utils; + +import ai.djl.Device; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.util.NDImageUtils; +import ai.djl.ndarray.NDArray; +import ai.djl.ndarray.NDList; +import ai.djl.ndarray.NDManager; +import ai.djl.ndarray.types.Shape; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.Batchifier; +import ai.djl.translate.Translator; +import ai.djl.translate.TranslatorContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class FaceDetection { + + private static final Logger logger = LoggerFactory.getLogger(FaceDetection.class); + + public FaceDetection() {} + + public Criteria criteria(float shrink, float threshold) { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, DetectedObjects.class) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_detection.zip") + // .optModelUrls("/Users/calvin/model/face_mask/pyramidbox_lite/") + // .optModelName("inference") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .optTranslator(new FaceTranslator(shrink, threshold)) + .build(); + + return criteria; + } + + private final class FaceTranslator implements Translator { + + private float shrink; + private float threshold; + private List className; + + FaceTranslator(float shrink, float threshold) { + this.shrink = shrink; + this.threshold = threshold; + className = Arrays.asList("Not Face", "Face"); + } + + @Override + public DetectedObjects processOutput(TranslatorContext ctx, NDList list) { + return processImageOutput(list, className, threshold); + } + + @Override + public NDList processInput(TranslatorContext ctx, Image input) { + return processImageInput(ctx.getNDManager(), input, shrink); + } + + @Override + public Batchifier getBatchifier() { + return null; + } + + NDList processImageInput(NDManager manager, Image input, float shrink) { + NDArray array = input.toNDArray(manager); + Shape shape = array.getShape(); + array = + NDImageUtils.resize(array, (int) (shape.get(1) * shrink), (int) (shape.get(0) * shrink)); + array = array.transpose(2, 0, 1).flip(0); // HWC -> CHW BGR -> RGB + NDArray mean = manager.create(new float[] {104f, 117f, 123f}, new Shape(3, 1, 1)); + array = array.sub(mean).mul(0.007843f); // normalization + array = array.expandDims(0); // make batch dimension + return new NDList(array); + } + + DetectedObjects processImageOutput(NDList list, List className, float threshold) { + NDArray result = list.singletonOrThrow(); + float[] probabilities = result.get(":,1").toFloatArray(); + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List boxes = new ArrayList<>(); + for (int i = 0; i < probabilities.length; i++) { + if (probabilities[i] >= threshold) { + float[] array = result.get(i).toFloatArray(); + names.add(className.get((int) array[0])); + prob.add((double) probabilities[i]); + boxes.add(new Rectangle(array[2], array[3], array[4] - array[2], array[5] - array[3])); + } + } + return new DetectedObjects(names, prob, boxes); + } + } +} diff --git a/4_video_sdks/camera_facemask_sdk/camera-facemask-sdk.iml b/4_video_sdks/camera_facemask_sdk/camera-facemask-sdk.iml new file mode 100644 index 00000000..6278679a --- /dev/null +++ b/4_video_sdks/camera_facemask_sdk/camera-facemask-sdk.iml @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/4_video_sdks/camera_facemask_sdk/lib/aias-mask-lib-0.1.0.jar b/4_video_sdks/camera_facemask_sdk/lib/aias-mask-lib-0.1.0.jar deleted file mode 100644 index 071e0e430d6fbeefcb7ac3b5488f406c00ebbdd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9200 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 U2VNEycXxMYz`q_do7mg_AH%Ahh5!Hn diff --git a/4_video_sdks/camera_facemask_sdk/pom.xml b/4_video_sdks/camera_facemask_sdk/pom.xml index f2714cf9..afcaa435 100644 --- a/4_video_sdks/camera_facemask_sdk/pom.xml +++ b/4_video_sdks/camera_facemask_sdk/pom.xml @@ -31,7 +31,7 @@ UTF-8 1.8 1.8 - 0.13.0 + 0.14.0 @@ -94,14 +94,13 @@ ai.djl.pytorch pytorch-native-auto - 1.9.0 + 1.9.1 ai.djl.paddlepaddle paddlepaddle-engine ${djl.version} - runtime ai.djl.paddlepaddle @@ -113,13 +112,6 @@ paddlepaddle-model-zoo ${djl.version} - - aias - mask-lib - 0.1.0 - system - ${project.basedir}/lib/aias-mask-lib-0.1.0.jar - org.bytedeco javacv-platform diff --git a/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/CameraFaceMaskDetectionExample.java b/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/CameraFaceMaskDetectionExample.java index c25e6056..d89734d4 100644 --- a/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/CameraFaceMaskDetectionExample.java +++ b/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/CameraFaceMaskDetectionExample.java @@ -12,8 +12,8 @@ import ai.djl.repository.zoo.Criteria; import ai.djl.repository.zoo.ModelZoo; import ai.djl.repository.zoo.ZooModel; import ai.djl.translate.TranslateException; -import me.aias.FaceDetection; -import me.aias.FaceMaskDetect; +import me.aias.example.utils.FaceDetection; +import me.aias.example.utils.FaceMaskDetect; import me.aias.example.utils.OpenCVImageUtil; import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.Frame; @@ -151,7 +151,7 @@ public class CameraFaceMaskDetectionExample { if (squareBox[1] > height) squareBox[1] = height; if ((squareBox[0] + squareBox[2]) > width) squareBox[2] = width - squareBox[0]; if ((squareBox[1] + squareBox[2]) > height) squareBox[2] = height - squareBox[1]; - return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); + return img.getSubImage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); // return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[3]); } } diff --git a/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java b/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java new file mode 100644 index 00000000..f5cfdd48 --- /dev/null +++ b/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java @@ -0,0 +1,104 @@ +package me.aias.example.utils; + +import ai.djl.Device; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.util.NDImageUtils; +import ai.djl.ndarray.NDArray; +import ai.djl.ndarray.NDList; +import ai.djl.ndarray.NDManager; +import ai.djl.ndarray.types.Shape; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.Batchifier; +import ai.djl.translate.Translator; +import ai.djl.translate.TranslatorContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class FaceDetection { + + private static final Logger logger = LoggerFactory.getLogger(FaceDetection.class); + + public FaceDetection() {} + + public Criteria criteria(float shrink, float threshold) { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, DetectedObjects.class) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_detection.zip") + // .optModelUrls("/Users/calvin/model/face_mask/pyramidbox_lite/") + // .optModelName("inference") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .optTranslator(new FaceTranslator(shrink, threshold)) + .build(); + + return criteria; + } + + private final class FaceTranslator implements Translator { + + private float shrink; + private float threshold; + private List className; + + FaceTranslator(float shrink, float threshold) { + this.shrink = shrink; + this.threshold = threshold; + className = Arrays.asList("Not Face", "Face"); + } + + @Override + public DetectedObjects processOutput(TranslatorContext ctx, NDList list) { + return processImageOutput(list, className, threshold); + } + + @Override + public NDList processInput(TranslatorContext ctx, Image input) { + return processImageInput(ctx.getNDManager(), input, shrink); + } + + @Override + public Batchifier getBatchifier() { + return null; + } + + NDList processImageInput(NDManager manager, Image input, float shrink) { + NDArray array = input.toNDArray(manager); + Shape shape = array.getShape(); + array = + NDImageUtils.resize(array, (int) (shape.get(1) * shrink), (int) (shape.get(0) * shrink)); + array = array.transpose(2, 0, 1).flip(0); // HWC -> CHW BGR -> RGB + NDArray mean = manager.create(new float[] {104f, 117f, 123f}, new Shape(3, 1, 1)); + array = array.sub(mean).mul(0.007843f); // normalization + array = array.expandDims(0); // make batch dimension + return new NDList(array); + } + + DetectedObjects processImageOutput(NDList list, List className, float threshold) { + NDArray result = list.singletonOrThrow(); + float[] probabilities = result.get(":,1").toFloatArray(); + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List boxes = new ArrayList<>(); + for (int i = 0; i < probabilities.length; i++) { + if (probabilities[i] >= threshold) { + float[] array = result.get(i).toFloatArray(); + names.add(className.get((int) array[0])); + prob.add((double) probabilities[i]); + boxes.add(new Rectangle(array[2], array[3], array[4] - array[2], array[5] - array[3])); + } + } + return new DetectedObjects(names, prob, boxes); + } + } +} diff --git a/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java b/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java new file mode 100644 index 00000000..bf6f9d92 --- /dev/null +++ b/4_video_sdks/camera_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java @@ -0,0 +1,98 @@ +package me.aias.example.utils; + +import ai.djl.Device; +import ai.djl.inference.Predictor; +import ai.djl.modality.Classifications; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.transform.Normalize; +import ai.djl.modality.cv.transform.Resize; +import ai.djl.modality.cv.transform.ToTensor; +import ai.djl.modality.cv.translator.ImageClassificationTranslator; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.TranslateException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public final class FaceMaskDetect { + + private static final Logger logger = LoggerFactory.getLogger(FaceMaskDetect.class); + + public FaceMaskDetect() {} + + public DetectedObjects predict( + Predictor faceDetector, + Predictor classifier, + Image image) + throws TranslateException { + + DetectedObjects detections = faceDetector.predict(image); + List faces = detections.items(); + + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List rect = new ArrayList<>(); + for (DetectedObjects.DetectedObject face : faces) { + Image subImg = getSubImage(image, face.getBoundingBox()); + Classifications classifications = classifier.predict(subImg); + names.add(classifications.best().getClassName()); + prob.add(face.getProbability()); + rect.add(face.getBoundingBox()); + } + + return new DetectedObjects(names, prob, rect); + } + + public Criteria criteria() { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, Classifications.class) + .optTranslator( + ImageClassificationTranslator.builder() + .addTransform(new Resize(128, 128)) + .addTransform(new ToTensor()) // HWC -> CHW div(255) + .addTransform( + new Normalize( + new float[] {0.5f, 0.5f, 0.5f}, new float[] {1.0f, 1.0f, 1.0f})) + .addTransform(nd -> nd.flip(0)) // RGB -> GBR + .build()) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_mask.zip") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .build(); + + return criteria; + } + + private int[] extendSquare( + double xmin, double ymin, double width, double height, double percentage) { + double centerx = xmin + width / 2; + double centery = ymin + height / 2; + double maxDist = Math.max(width / 2, height / 2) * (1 + percentage); + return new int[] {(int) (centerx - maxDist), (int) (centery - maxDist), (int) (2 * maxDist)}; + // return new int[] {(int) xmin, (int) ymin, (int) width, (int) height}; + } + + private Image getSubImage(Image img, BoundingBox box) { + Rectangle rect = box.getBounds(); + int width = img.getWidth(); + int height = img.getHeight(); + int[] squareBox = + extendSquare( + rect.getX() * width, + rect.getY() * height, + rect.getWidth() * width, + rect.getHeight() * height, + 0); // 0.18 + return img.getSubImage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); + // return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[3]); + } +} diff --git a/4_video_sdks/mp4_face_sdk/lib/aias-face-lib-0.1.0.jar b/4_video_sdks/mp4_face_sdk/lib/aias-face-lib-0.1.0.jar deleted file mode 100644 index 65a056bbc60fcdff616590094e226707c0204be3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6492 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 Cv2C{i diff --git a/4_video_sdks/mp4_face_sdk/mp4-face-sdk.iml b/4_video_sdks/mp4_face_sdk/mp4-face-sdk.iml new file mode 100644 index 00000000..aade2256 --- /dev/null +++ b/4_video_sdks/mp4_face_sdk/mp4-face-sdk.iml @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/4_video_sdks/mp4_face_sdk/pom.xml b/4_video_sdks/mp4_face_sdk/pom.xml index 6fc1fd77..662995ef 100644 --- a/4_video_sdks/mp4_face_sdk/pom.xml +++ b/4_video_sdks/mp4_face_sdk/pom.xml @@ -31,7 +31,7 @@ UTF-8 1.8 1.8 - 0.13.0 + 0.14.0 @@ -94,14 +94,13 @@ ai.djl.pytorch pytorch-native-auto - 1.9.0 + 1.9.1 ai.djl.paddlepaddle paddlepaddle-engine ${djl.version} - runtime ai.djl.paddlepaddle @@ -113,13 +112,6 @@ paddlepaddle-model-zoo ${djl.version} - - aias - face-lib - 0.1.0 - system - ${project.basedir}/lib/aias-face-lib-0.1.0.jar - org.bytedeco javacv-platform diff --git a/4_video_sdks/mp4_face_sdk/src/main/java/me/aias/example/MP4FaceDetectionExample.java b/4_video_sdks/mp4_face_sdk/src/main/java/me/aias/example/MP4FaceDetectionExample.java index 5246fd57..d4465385 100644 --- a/4_video_sdks/mp4_face_sdk/src/main/java/me/aias/example/MP4FaceDetectionExample.java +++ b/4_video_sdks/mp4_face_sdk/src/main/java/me/aias/example/MP4FaceDetectionExample.java @@ -11,7 +11,7 @@ import ai.djl.repository.zoo.Criteria; import ai.djl.repository.zoo.ModelZoo; import ai.djl.repository.zoo.ZooModel; import ai.djl.translate.TranslateException; -import me.aias.FaceDetection; +import me.aias.example.utils.FaceDetection; import me.aias.example.utils.OpenCVImageUtil; import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.FFmpegFrameGrabber; diff --git a/4_video_sdks/mp4_face_sdk/src/main/java/me/aias/example/utils/FaceDetection.java b/4_video_sdks/mp4_face_sdk/src/main/java/me/aias/example/utils/FaceDetection.java new file mode 100644 index 00000000..f5cfdd48 --- /dev/null +++ b/4_video_sdks/mp4_face_sdk/src/main/java/me/aias/example/utils/FaceDetection.java @@ -0,0 +1,104 @@ +package me.aias.example.utils; + +import ai.djl.Device; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.util.NDImageUtils; +import ai.djl.ndarray.NDArray; +import ai.djl.ndarray.NDList; +import ai.djl.ndarray.NDManager; +import ai.djl.ndarray.types.Shape; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.Batchifier; +import ai.djl.translate.Translator; +import ai.djl.translate.TranslatorContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class FaceDetection { + + private static final Logger logger = LoggerFactory.getLogger(FaceDetection.class); + + public FaceDetection() {} + + public Criteria criteria(float shrink, float threshold) { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, DetectedObjects.class) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_detection.zip") + // .optModelUrls("/Users/calvin/model/face_mask/pyramidbox_lite/") + // .optModelName("inference") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .optTranslator(new FaceTranslator(shrink, threshold)) + .build(); + + return criteria; + } + + private final class FaceTranslator implements Translator { + + private float shrink; + private float threshold; + private List className; + + FaceTranslator(float shrink, float threshold) { + this.shrink = shrink; + this.threshold = threshold; + className = Arrays.asList("Not Face", "Face"); + } + + @Override + public DetectedObjects processOutput(TranslatorContext ctx, NDList list) { + return processImageOutput(list, className, threshold); + } + + @Override + public NDList processInput(TranslatorContext ctx, Image input) { + return processImageInput(ctx.getNDManager(), input, shrink); + } + + @Override + public Batchifier getBatchifier() { + return null; + } + + NDList processImageInput(NDManager manager, Image input, float shrink) { + NDArray array = input.toNDArray(manager); + Shape shape = array.getShape(); + array = + NDImageUtils.resize(array, (int) (shape.get(1) * shrink), (int) (shape.get(0) * shrink)); + array = array.transpose(2, 0, 1).flip(0); // HWC -> CHW BGR -> RGB + NDArray mean = manager.create(new float[] {104f, 117f, 123f}, new Shape(3, 1, 1)); + array = array.sub(mean).mul(0.007843f); // normalization + array = array.expandDims(0); // make batch dimension + return new NDList(array); + } + + DetectedObjects processImageOutput(NDList list, List className, float threshold) { + NDArray result = list.singletonOrThrow(); + float[] probabilities = result.get(":,1").toFloatArray(); + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List boxes = new ArrayList<>(); + for (int i = 0; i < probabilities.length; i++) { + if (probabilities[i] >= threshold) { + float[] array = result.get(i).toFloatArray(); + names.add(className.get((int) array[0])); + prob.add((double) probabilities[i]); + boxes.add(new Rectangle(array[2], array[3], array[4] - array[2], array[5] - array[3])); + } + } + return new DetectedObjects(names, prob, boxes); + } + } +} diff --git a/4_video_sdks/mp4_facemask_sdk/lib/aias-mask-lib-0.1.0.jar b/4_video_sdks/mp4_facemask_sdk/lib/aias-mask-lib-0.1.0.jar deleted file mode 100644 index 071e0e430d6fbeefcb7ac3b5488f406c00ebbdd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9200 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 U2VNEycXxMYz`q_do7mg_AH%Ahh5!Hn diff --git a/4_video_sdks/mp4_facemask_sdk/mp4-facemask-sdk.iml b/4_video_sdks/mp4_facemask_sdk/mp4-facemask-sdk.iml new file mode 100644 index 00000000..6278679a --- /dev/null +++ b/4_video_sdks/mp4_facemask_sdk/mp4-facemask-sdk.iml @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/4_video_sdks/mp4_facemask_sdk/pom.xml b/4_video_sdks/mp4_facemask_sdk/pom.xml index 8b06f691..80ac3bce 100644 --- a/4_video_sdks/mp4_facemask_sdk/pom.xml +++ b/4_video_sdks/mp4_facemask_sdk/pom.xml @@ -31,7 +31,7 @@ UTF-8 1.8 1.8 - 0.13.0 + 0.14.0 @@ -94,14 +94,13 @@ ai.djl.pytorch pytorch-native-auto - 1.9.0 + 1.9.1 ai.djl.paddlepaddle paddlepaddle-engine ${djl.version} - runtime ai.djl.paddlepaddle @@ -118,13 +117,6 @@ javacv-platform 1.5.4 - - aias - mask-lib - 0.1.0 - system - ${project.basedir}/lib/aias-mask-lib-0.1.0.jar - org.testng testng diff --git a/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/MP4FaceMaskDetectionExample.java b/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/MP4FaceMaskDetectionExample.java index e8aec865..9c9e0f18 100644 --- a/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/MP4FaceMaskDetectionExample.java +++ b/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/MP4FaceMaskDetectionExample.java @@ -12,8 +12,8 @@ import ai.djl.repository.zoo.Criteria; import ai.djl.repository.zoo.ModelZoo; import ai.djl.repository.zoo.ZooModel; import ai.djl.translate.TranslateException; -import me.aias.FaceDetection; -import me.aias.FaceMaskDetect; +import me.aias.example.utils.FaceDetection; +import me.aias.example.utils.FaceMaskDetect; import me.aias.example.utils.OpenCVImageUtil; import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.FFmpegFrameGrabber; @@ -156,7 +156,7 @@ public class MP4FaceMaskDetectionExample { if (squareBox[1] > height) squareBox[1] = height; if ((squareBox[0] + squareBox[2]) > width) squareBox[2] = width - squareBox[0]; if ((squareBox[1] + squareBox[2]) > height) squareBox[2] = height - squareBox[1]; - return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); + return img.getSubImage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); // return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[3]); } } diff --git a/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java b/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java new file mode 100644 index 00000000..f5cfdd48 --- /dev/null +++ b/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java @@ -0,0 +1,104 @@ +package me.aias.example.utils; + +import ai.djl.Device; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.util.NDImageUtils; +import ai.djl.ndarray.NDArray; +import ai.djl.ndarray.NDList; +import ai.djl.ndarray.NDManager; +import ai.djl.ndarray.types.Shape; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.Batchifier; +import ai.djl.translate.Translator; +import ai.djl.translate.TranslatorContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class FaceDetection { + + private static final Logger logger = LoggerFactory.getLogger(FaceDetection.class); + + public FaceDetection() {} + + public Criteria criteria(float shrink, float threshold) { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, DetectedObjects.class) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_detection.zip") + // .optModelUrls("/Users/calvin/model/face_mask/pyramidbox_lite/") + // .optModelName("inference") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .optTranslator(new FaceTranslator(shrink, threshold)) + .build(); + + return criteria; + } + + private final class FaceTranslator implements Translator { + + private float shrink; + private float threshold; + private List className; + + FaceTranslator(float shrink, float threshold) { + this.shrink = shrink; + this.threshold = threshold; + className = Arrays.asList("Not Face", "Face"); + } + + @Override + public DetectedObjects processOutput(TranslatorContext ctx, NDList list) { + return processImageOutput(list, className, threshold); + } + + @Override + public NDList processInput(TranslatorContext ctx, Image input) { + return processImageInput(ctx.getNDManager(), input, shrink); + } + + @Override + public Batchifier getBatchifier() { + return null; + } + + NDList processImageInput(NDManager manager, Image input, float shrink) { + NDArray array = input.toNDArray(manager); + Shape shape = array.getShape(); + array = + NDImageUtils.resize(array, (int) (shape.get(1) * shrink), (int) (shape.get(0) * shrink)); + array = array.transpose(2, 0, 1).flip(0); // HWC -> CHW BGR -> RGB + NDArray mean = manager.create(new float[] {104f, 117f, 123f}, new Shape(3, 1, 1)); + array = array.sub(mean).mul(0.007843f); // normalization + array = array.expandDims(0); // make batch dimension + return new NDList(array); + } + + DetectedObjects processImageOutput(NDList list, List className, float threshold) { + NDArray result = list.singletonOrThrow(); + float[] probabilities = result.get(":,1").toFloatArray(); + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List boxes = new ArrayList<>(); + for (int i = 0; i < probabilities.length; i++) { + if (probabilities[i] >= threshold) { + float[] array = result.get(i).toFloatArray(); + names.add(className.get((int) array[0])); + prob.add((double) probabilities[i]); + boxes.add(new Rectangle(array[2], array[3], array[4] - array[2], array[5] - array[3])); + } + } + return new DetectedObjects(names, prob, boxes); + } + } +} diff --git a/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java b/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java new file mode 100644 index 00000000..bf6f9d92 --- /dev/null +++ b/4_video_sdks/mp4_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java @@ -0,0 +1,98 @@ +package me.aias.example.utils; + +import ai.djl.Device; +import ai.djl.inference.Predictor; +import ai.djl.modality.Classifications; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.transform.Normalize; +import ai.djl.modality.cv.transform.Resize; +import ai.djl.modality.cv.transform.ToTensor; +import ai.djl.modality.cv.translator.ImageClassificationTranslator; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.TranslateException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public final class FaceMaskDetect { + + private static final Logger logger = LoggerFactory.getLogger(FaceMaskDetect.class); + + public FaceMaskDetect() {} + + public DetectedObjects predict( + Predictor faceDetector, + Predictor classifier, + Image image) + throws TranslateException { + + DetectedObjects detections = faceDetector.predict(image); + List faces = detections.items(); + + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List rect = new ArrayList<>(); + for (DetectedObjects.DetectedObject face : faces) { + Image subImg = getSubImage(image, face.getBoundingBox()); + Classifications classifications = classifier.predict(subImg); + names.add(classifications.best().getClassName()); + prob.add(face.getProbability()); + rect.add(face.getBoundingBox()); + } + + return new DetectedObjects(names, prob, rect); + } + + public Criteria criteria() { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, Classifications.class) + .optTranslator( + ImageClassificationTranslator.builder() + .addTransform(new Resize(128, 128)) + .addTransform(new ToTensor()) // HWC -> CHW div(255) + .addTransform( + new Normalize( + new float[] {0.5f, 0.5f, 0.5f}, new float[] {1.0f, 1.0f, 1.0f})) + .addTransform(nd -> nd.flip(0)) // RGB -> GBR + .build()) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_mask.zip") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .build(); + + return criteria; + } + + private int[] extendSquare( + double xmin, double ymin, double width, double height, double percentage) { + double centerx = xmin + width / 2; + double centery = ymin + height / 2; + double maxDist = Math.max(width / 2, height / 2) * (1 + percentage); + return new int[] {(int) (centerx - maxDist), (int) (centery - maxDist), (int) (2 * maxDist)}; + // return new int[] {(int) xmin, (int) ymin, (int) width, (int) height}; + } + + private Image getSubImage(Image img, BoundingBox box) { + Rectangle rect = box.getBounds(); + int width = img.getWidth(); + int height = img.getHeight(); + int[] squareBox = + extendSquare( + rect.getX() * width, + rect.getY() * height, + rect.getWidth() * width, + rect.getHeight() * height, + 0); // 0.18 + return img.getSubImage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); + // return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[3]); + } +} diff --git a/4_video_sdks/rtsp_face_sdk/lib/aias-face-lib-0.1.0.jar b/4_video_sdks/rtsp_face_sdk/lib/aias-face-lib-0.1.0.jar deleted file mode 100644 index 65a056bbc60fcdff616590094e226707c0204be3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6492 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 Cv2C{i diff --git a/4_video_sdks/rtsp_face_sdk/pom.xml b/4_video_sdks/rtsp_face_sdk/pom.xml index d8e4edbf..a672c843 100644 --- a/4_video_sdks/rtsp_face_sdk/pom.xml +++ b/4_video_sdks/rtsp_face_sdk/pom.xml @@ -31,7 +31,7 @@ UTF-8 1.8 1.8 - 0.13.0 + 0.14.0 @@ -94,14 +94,13 @@ ai.djl.pytorch pytorch-native-auto - 1.9.0 + 1.9.1 ai.djl.paddlepaddle paddlepaddle-engine ${djl.version} - runtime ai.djl.paddlepaddle @@ -118,13 +117,6 @@ javacv-platform 1.5.4 - - aias - face-lib - 0.1.0 - system - ${project.basedir}/lib/aias-face-lib-0.1.0.jar - org.testng testng diff --git a/4_video_sdks/rtsp_face_sdk/rtsp-face-sdk.iml b/4_video_sdks/rtsp_face_sdk/rtsp-face-sdk.iml new file mode 100644 index 00000000..6278679a --- /dev/null +++ b/4_video_sdks/rtsp_face_sdk/rtsp-face-sdk.iml @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/4_video_sdks/rtsp_face_sdk/src/main/java/me/aias/example/RtspFaceDetectionExample.java b/4_video_sdks/rtsp_face_sdk/src/main/java/me/aias/example/RtspFaceDetectionExample.java index 520adb62..6e613dee 100644 --- a/4_video_sdks/rtsp_face_sdk/src/main/java/me/aias/example/RtspFaceDetectionExample.java +++ b/4_video_sdks/rtsp_face_sdk/src/main/java/me/aias/example/RtspFaceDetectionExample.java @@ -11,7 +11,7 @@ import ai.djl.repository.zoo.Criteria; import ai.djl.repository.zoo.ModelZoo; import ai.djl.repository.zoo.ZooModel; import ai.djl.translate.TranslateException; -import me.aias.FaceDetection; +import me.aias.example.utils.FaceDetection; import me.aias.example.utils.OpenCVImageUtil; import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.FFmpegFrameGrabber; diff --git a/4_video_sdks/rtsp_face_sdk/src/main/java/me/aias/example/utils/FaceDetection.java b/4_video_sdks/rtsp_face_sdk/src/main/java/me/aias/example/utils/FaceDetection.java new file mode 100644 index 00000000..f5cfdd48 --- /dev/null +++ b/4_video_sdks/rtsp_face_sdk/src/main/java/me/aias/example/utils/FaceDetection.java @@ -0,0 +1,104 @@ +package me.aias.example.utils; + +import ai.djl.Device; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.util.NDImageUtils; +import ai.djl.ndarray.NDArray; +import ai.djl.ndarray.NDList; +import ai.djl.ndarray.NDManager; +import ai.djl.ndarray.types.Shape; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.Batchifier; +import ai.djl.translate.Translator; +import ai.djl.translate.TranslatorContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class FaceDetection { + + private static final Logger logger = LoggerFactory.getLogger(FaceDetection.class); + + public FaceDetection() {} + + public Criteria criteria(float shrink, float threshold) { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, DetectedObjects.class) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_detection.zip") + // .optModelUrls("/Users/calvin/model/face_mask/pyramidbox_lite/") + // .optModelName("inference") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .optTranslator(new FaceTranslator(shrink, threshold)) + .build(); + + return criteria; + } + + private final class FaceTranslator implements Translator { + + private float shrink; + private float threshold; + private List className; + + FaceTranslator(float shrink, float threshold) { + this.shrink = shrink; + this.threshold = threshold; + className = Arrays.asList("Not Face", "Face"); + } + + @Override + public DetectedObjects processOutput(TranslatorContext ctx, NDList list) { + return processImageOutput(list, className, threshold); + } + + @Override + public NDList processInput(TranslatorContext ctx, Image input) { + return processImageInput(ctx.getNDManager(), input, shrink); + } + + @Override + public Batchifier getBatchifier() { + return null; + } + + NDList processImageInput(NDManager manager, Image input, float shrink) { + NDArray array = input.toNDArray(manager); + Shape shape = array.getShape(); + array = + NDImageUtils.resize(array, (int) (shape.get(1) * shrink), (int) (shape.get(0) * shrink)); + array = array.transpose(2, 0, 1).flip(0); // HWC -> CHW BGR -> RGB + NDArray mean = manager.create(new float[] {104f, 117f, 123f}, new Shape(3, 1, 1)); + array = array.sub(mean).mul(0.007843f); // normalization + array = array.expandDims(0); // make batch dimension + return new NDList(array); + } + + DetectedObjects processImageOutput(NDList list, List className, float threshold) { + NDArray result = list.singletonOrThrow(); + float[] probabilities = result.get(":,1").toFloatArray(); + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List boxes = new ArrayList<>(); + for (int i = 0; i < probabilities.length; i++) { + if (probabilities[i] >= threshold) { + float[] array = result.get(i).toFloatArray(); + names.add(className.get((int) array[0])); + prob.add((double) probabilities[i]); + boxes.add(new Rectangle(array[2], array[3], array[4] - array[2], array[5] - array[3])); + } + } + return new DetectedObjects(names, prob, boxes); + } + } +} diff --git a/4_video_sdks/rtsp_facemask_sdk/lib/aias-mask-lib-0.1.0.jar b/4_video_sdks/rtsp_facemask_sdk/lib/aias-mask-lib-0.1.0.jar deleted file mode 100644 index 071e0e430d6fbeefcb7ac3b5488f406c00ebbdd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9200 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 U2VNEycXxMYz`q_do7mg_AH%Ahh5!Hn diff --git a/4_video_sdks/rtsp_facemask_sdk/pom.xml b/4_video_sdks/rtsp_facemask_sdk/pom.xml index 3dc6f2bd..696dda21 100644 --- a/4_video_sdks/rtsp_facemask_sdk/pom.xml +++ b/4_video_sdks/rtsp_facemask_sdk/pom.xml @@ -31,7 +31,7 @@ UTF-8 1.8 1.8 - 0.13.0 + 0.14.0 @@ -94,14 +94,13 @@ ai.djl.pytorch pytorch-native-auto - 1.9.0 + 1.9.1 ai.djl.paddlepaddle paddlepaddle-engine ${djl.version} - runtime ai.djl.paddlepaddle @@ -118,13 +117,6 @@ javacv-platform 1.5.4 - - aias - mask-lib - 0.1.0 - system - ${project.basedir}/lib/aias-mask-lib-0.1.0.jar - org.testng testng diff --git a/4_video_sdks/rtsp_facemask_sdk/rtsp-facemask-sdk.iml b/4_video_sdks/rtsp_facemask_sdk/rtsp-facemask-sdk.iml new file mode 100644 index 00000000..6278679a --- /dev/null +++ b/4_video_sdks/rtsp_facemask_sdk/rtsp-facemask-sdk.iml @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/RtspFaceMaskDetectionExample.java b/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/RtspFaceMaskDetectionExample.java index 98c7f83e..56d7c3fe 100644 --- a/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/RtspFaceMaskDetectionExample.java +++ b/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/RtspFaceMaskDetectionExample.java @@ -12,8 +12,8 @@ import ai.djl.repository.zoo.Criteria; import ai.djl.repository.zoo.ModelZoo; import ai.djl.repository.zoo.ZooModel; import ai.djl.translate.TranslateException; -import me.aias.FaceDetection; -import me.aias.FaceMaskDetect; +import me.aias.example.utils.FaceDetection; +import me.aias.example.utils.FaceMaskDetect; import me.aias.example.utils.OpenCVImageUtil; import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.FFmpegFrameGrabber; @@ -191,7 +191,7 @@ public class RtspFaceMaskDetectionExample { if (squareBox[1] > height) squareBox[1] = height; if ((squareBox[0] + squareBox[2]) > width) squareBox[2] = width - squareBox[0]; if ((squareBox[1] + squareBox[2]) > height) squareBox[2] = height - squareBox[1]; - return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); + return img.getSubImage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); // return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[3]); } } diff --git a/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java b/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java new file mode 100644 index 00000000..f5cfdd48 --- /dev/null +++ b/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/utils/FaceDetection.java @@ -0,0 +1,104 @@ +package me.aias.example.utils; + +import ai.djl.Device; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.util.NDImageUtils; +import ai.djl.ndarray.NDArray; +import ai.djl.ndarray.NDList; +import ai.djl.ndarray.NDManager; +import ai.djl.ndarray.types.Shape; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.Batchifier; +import ai.djl.translate.Translator; +import ai.djl.translate.TranslatorContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public final class FaceDetection { + + private static final Logger logger = LoggerFactory.getLogger(FaceDetection.class); + + public FaceDetection() {} + + public Criteria criteria(float shrink, float threshold) { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, DetectedObjects.class) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_detection.zip") + // .optModelUrls("/Users/calvin/model/face_mask/pyramidbox_lite/") + // .optModelName("inference") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .optTranslator(new FaceTranslator(shrink, threshold)) + .build(); + + return criteria; + } + + private final class FaceTranslator implements Translator { + + private float shrink; + private float threshold; + private List className; + + FaceTranslator(float shrink, float threshold) { + this.shrink = shrink; + this.threshold = threshold; + className = Arrays.asList("Not Face", "Face"); + } + + @Override + public DetectedObjects processOutput(TranslatorContext ctx, NDList list) { + return processImageOutput(list, className, threshold); + } + + @Override + public NDList processInput(TranslatorContext ctx, Image input) { + return processImageInput(ctx.getNDManager(), input, shrink); + } + + @Override + public Batchifier getBatchifier() { + return null; + } + + NDList processImageInput(NDManager manager, Image input, float shrink) { + NDArray array = input.toNDArray(manager); + Shape shape = array.getShape(); + array = + NDImageUtils.resize(array, (int) (shape.get(1) * shrink), (int) (shape.get(0) * shrink)); + array = array.transpose(2, 0, 1).flip(0); // HWC -> CHW BGR -> RGB + NDArray mean = manager.create(new float[] {104f, 117f, 123f}, new Shape(3, 1, 1)); + array = array.sub(mean).mul(0.007843f); // normalization + array = array.expandDims(0); // make batch dimension + return new NDList(array); + } + + DetectedObjects processImageOutput(NDList list, List className, float threshold) { + NDArray result = list.singletonOrThrow(); + float[] probabilities = result.get(":,1").toFloatArray(); + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List boxes = new ArrayList<>(); + for (int i = 0; i < probabilities.length; i++) { + if (probabilities[i] >= threshold) { + float[] array = result.get(i).toFloatArray(); + names.add(className.get((int) array[0])); + prob.add((double) probabilities[i]); + boxes.add(new Rectangle(array[2], array[3], array[4] - array[2], array[5] - array[3])); + } + } + return new DetectedObjects(names, prob, boxes); + } + } +} diff --git a/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java b/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java new file mode 100644 index 00000000..bf6f9d92 --- /dev/null +++ b/4_video_sdks/rtsp_facemask_sdk/src/main/java/me/aias/example/utils/FaceMaskDetect.java @@ -0,0 +1,98 @@ +package me.aias.example.utils; + +import ai.djl.Device; +import ai.djl.inference.Predictor; +import ai.djl.modality.Classifications; +import ai.djl.modality.cv.Image; +import ai.djl.modality.cv.output.BoundingBox; +import ai.djl.modality.cv.output.DetectedObjects; +import ai.djl.modality.cv.output.Rectangle; +import ai.djl.modality.cv.transform.Normalize; +import ai.djl.modality.cv.transform.Resize; +import ai.djl.modality.cv.transform.ToTensor; +import ai.djl.modality.cv.translator.ImageClassificationTranslator; +import ai.djl.repository.zoo.Criteria; +import ai.djl.training.util.ProgressBar; +import ai.djl.translate.TranslateException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public final class FaceMaskDetect { + + private static final Logger logger = LoggerFactory.getLogger(FaceMaskDetect.class); + + public FaceMaskDetect() {} + + public DetectedObjects predict( + Predictor faceDetector, + Predictor classifier, + Image image) + throws TranslateException { + + DetectedObjects detections = faceDetector.predict(image); + List faces = detections.items(); + + List names = new ArrayList<>(); + List prob = new ArrayList<>(); + List rect = new ArrayList<>(); + for (DetectedObjects.DetectedObject face : faces) { + Image subImg = getSubImage(image, face.getBoundingBox()); + Classifications classifications = classifier.predict(subImg); + names.add(classifications.best().getClassName()); + prob.add(face.getProbability()); + rect.add(face.getBoundingBox()); + } + + return new DetectedObjects(names, prob, rect); + } + + public Criteria criteria() { + Criteria criteria = + Criteria.builder() + .optEngine("PaddlePaddle") + .setTypes(Image.class, Classifications.class) + .optTranslator( + ImageClassificationTranslator.builder() + .addTransform(new Resize(128, 128)) + .addTransform(new ToTensor()) // HWC -> CHW div(255) + .addTransform( + new Normalize( + new float[] {0.5f, 0.5f, 0.5f}, new float[] {1.0f, 1.0f, 1.0f})) + .addTransform(nd -> nd.flip(0)) // RGB -> GBR + .build()) + .optModelUrls( + "https://aias-home.oss-cn-beijing.aliyuncs.com/models/face_mask/face_mask.zip") + .optProgress(new ProgressBar()) + .optDevice(Device.cpu()) + .build(); + + return criteria; + } + + private int[] extendSquare( + double xmin, double ymin, double width, double height, double percentage) { + double centerx = xmin + width / 2; + double centery = ymin + height / 2; + double maxDist = Math.max(width / 2, height / 2) * (1 + percentage); + return new int[] {(int) (centerx - maxDist), (int) (centery - maxDist), (int) (2 * maxDist)}; + // return new int[] {(int) xmin, (int) ymin, (int) width, (int) height}; + } + + private Image getSubImage(Image img, BoundingBox box) { + Rectangle rect = box.getBounds(); + int width = img.getWidth(); + int height = img.getHeight(); + int[] squareBox = + extendSquare( + rect.getX() * width, + rect.getY() * height, + rect.getWidth() * width, + rect.getHeight() * height, + 0); // 0.18 + return img.getSubImage(squareBox[0], squareBox[1], squareBox[2], squareBox[2]); + // return img.getSubimage(squareBox[0], squareBox[1], squareBox[2], squareBox[3]); + } +}