Loading FaceEngines/src/main/java/cz/fidentis/analyst/engines/face/ApiService.java +14 −2 Original line number Diff line number Diff line Loading @@ -31,9 +31,11 @@ public class ApiService { public ApiService(ApiConfig apiConfig) { this.apiConfig = apiConfig; LOGGER.debug( "ApiEnvironmentManager initialized: landmarks local={}, external={}", "ApiEnvironmentManager initialized: landmarks local={}, stratus={}, masks local={}, stratus={}", apiConfig.getLandmarks().getUrl().getLocal(), apiConfig.getLandmarks().getUrl().getStratus()); apiConfig.getLandmarks().getUrl().getStratus(), apiConfig.getMasks().getUrl().getLocal(), apiConfig.getMasks().getUrl().getStratus()); } /** Loading Loading @@ -64,4 +66,14 @@ public class ApiService { var url = apiConfig.getLandmarks().getUrl(); return environment == ApiEnvironment.LOCAL ? url.getLocal() : url.getStratus(); } /** * Returns the masks service URL for the current environment. * * @return masks service URL */ public String getMasksServiceUrl() { var url = apiConfig.getMasks().getUrl(); return environment == ApiEnvironment.LOCAL ? url.getLocal() : url.getStratus(); } } FaceEngines/src/main/java/cz/fidentis/analyst/engines/face/config/ApiConfig.java +12 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ import org.springframework.stereotype.Component; public class ApiConfig { private LandmarksConfig landmarks; private MasksConfig masks; /** * Configuration for the landmarks detection service. Loading @@ -30,6 +31,17 @@ public class ApiConfig { private UrlConfig url; } /** * Configuration for the masks detection service. * * @author Marek Drozdik */ @Getter @Setter public static class MasksConfig { private UrlConfig url; } /** * Holds local and stratus URL variants for a service. * Loading FaceEngines/src/main/java/cz/fidentis/analyst/engines/face/impl/FaceMasksServicesImpl.java +38 −19 Original line number Diff line number Diff line package cz.fidentis.analyst.engines.face.impl; import cz.fidentis.analyst.authentication.AuthService; import cz.fidentis.analyst.authentication.exceptions.AuthException; import cz.fidentis.analyst.data.face.Aca; import cz.fidentis.analyst.data.face.HumanFace; import cz.fidentis.analyst.data.mesh.MeshIO; import cz.fidentis.analyst.data.mesh.MeshModel; import cz.fidentis.analyst.data.shapes.Box; import cz.fidentis.analyst.data.surfacemask.Mask3DProjection; import cz.fidentis.analyst.data.surfacemask.MaskVariant; import cz.fidentis.analyst.engines.face.ApiService; import cz.fidentis.analyst.engines.face.exception.LocalResourceUnavailableException; import cz.fidentis.analyst.engines.face.exception.RemoteServiceFailedException; import cz.fidentis.analyst.engines.face.exception.RemoteServiceUnreachableException; Loading @@ -16,13 +20,17 @@ import cz.fidentis.analyst.engines.face.facemasksapi.model.FaceMask; import cz.fidentis.analyst.engines.face.facemasksapi.model.FaceMaskVariant; import cz.fidentis.analyst.engines.interactivemask.BoundingBoxMaskProjector; import cz.fidentis.analyst.engines.interactivemask.BoundingBoxMaskProjectorConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.vecmath.Point2d; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.*; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Services related to the masks detection and management. Loading @@ -32,6 +40,8 @@ import java.util.*; */ public class FaceMasksServicesImpl { private static final Logger LOGGER = LoggerFactory.getLogger(FaceMasksServicesImpl.class); /** * Runs automatic detection of face masks for pre-defined parts of the face. * Loading Loading @@ -127,27 +137,36 @@ public class FaceMasksServicesImpl { return mask3DProjections; } /** * Creates and configures a client for interacting with the masks detection API. * <p> * In local mode, no authentication is needed. * </p> * * @return A configured {@link FaceMasksApi} client for making requests to the * masks detection service. * @throws LocalResourceUnavailableException if user is not authenticated (non-local mode only) */ private FaceMasksApi getFaceMaskDetectorClient() throws LocalResourceUnavailableException { // Read config data from property file generated by maven InputStream is = getClass().getClassLoader().getResourceAsStream("my.properties"); java.util.Properties p = new Properties(); try { p.load(is); } catch (IOException e) { throw new LocalResourceUnavailableException(e); } String apiUrl = p.getProperty("fidentis.ai.masks.service.url"); String apiKey = p.getProperty("fidentis.ai.masks.api.key"); ApiService apiService = Aca.getInstance().getBean(ApiService.class); String apiUrl = apiService.getMasksServiceUrl(); ApiClient apiClient = new ApiClient(); apiClient.setBasePath(apiUrl); apiClient.setVerifyingSsl(false); // allowing self-signed certificates // allowing self-signed certificates apiClient.setVerifyingSsl(false); // setting authentication key apiClient.setApiKeyPrefix("Bearer"); apiClient.setApiKey(apiKey); // Local env does not require authentication if (!apiService.isLocal()) { String accessToken; try { AuthService authService = Aca.getInstance().getBean(AuthService.class); accessToken = authService.getValidAccessToken(); } catch (AuthException e) { LOGGER.warn("User not authenticated for mask detection: {}", e.getMessage()); throw new LocalResourceUnavailableException("User not authenticated", e); } apiClient.setBearerToken(accessToken); } return new FaceMasksApi(apiClient); } Loading FaceEngines/src/test/resources/application-test.yml +4 −0 Original line number Diff line number Diff line Loading @@ -15,3 +15,7 @@ fidentis: url: local: https://localhost:8080 stratus: https://localhost:8080 masks: url: local: https://localhost:8000 stratus: https://localhost:8000 GUI/src/main/java/cz/fidentis/analyst/gui/task/masks/InteractiveMaskAction.java +18 −1 Original line number Diff line number Diff line package cz.fidentis.analyst.gui.task.masks; import cz.fidentis.analyst.authentication.AuthService; import cz.fidentis.analyst.canvas.Canvas; import cz.fidentis.analyst.data.face.Aca; import cz.fidentis.analyst.data.shapes.Box; import cz.fidentis.analyst.data.shapes.CrossSection3D; import cz.fidentis.analyst.data.surfacemask.*; import cz.fidentis.analyst.engines.face.ApiService; import cz.fidentis.analyst.engines.face.FaceMasksServices; import cz.fidentis.analyst.engines.face.FaceStateServices; import cz.fidentis.analyst.engines.face.exception.RemoteServiceException; Loading @@ -11,8 +14,8 @@ import cz.fidentis.analyst.engines.interactivemask.BoundingBoxMaskProjector; import cz.fidentis.analyst.engines.interactivemask.MaskProjector; import cz.fidentis.analyst.engines.interactivemask.MaskProjectorBack; import cz.fidentis.analyst.engines.interactivemask.MaskProjectorConfig; import cz.fidentis.analyst.gui.task.ControlPanelAction; import cz.fidentis.analyst.gui.elements.RemoteServiceWorker; import cz.fidentis.analyst.gui.task.ControlPanelAction; import cz.fidentis.analyst.project.Task; import cz.fidentis.analyst.rendering.Camera; Loading @@ -36,6 +39,9 @@ import static cz.fidentis.analyst.gui.task.masks.InteractiveMaskPanel.ACTION_PRO public class InteractiveMaskAction extends ControlPanelAction<InteractiveMaskPanel> { private static final Vector3d FRONTAL_CAMERA_POSITION = new Vector3d(0, 0, BoundingBoxMaskProjector.PROJECTION_DISTANCE); private final AuthService authService; private final ApiService apiService; /** * Constructor * A new {@code InteractiveMaskPanel} is instantiated and added to the {@code topControlPane} Loading @@ -46,6 +52,8 @@ public class InteractiveMaskAction extends ControlPanelAction<InteractiveMaskPan */ public InteractiveMaskAction(Canvas canvas, Task task, JTabbedPane topControlPane) { super(canvas, task, topControlPane); this.authService = Aca.getInstance().getBean(AuthService.class); this.apiService = Aca.getInstance().getBean(ApiService.class); InteractiveMaskPanel pl = new InteractiveMaskPanel(this); setControlPanel(pl); pl.getSurfaceMaskPanel1().setFaceBoundingBox(getPrimaryFace().getBoundingBox()); Loading Loading @@ -255,6 +263,15 @@ public class InteractiveMaskAction extends ControlPanelAction<InteractiveMaskPan renderScene(); break; case InteractiveMaskPanel.ACTION_DETECTION_RUN: // Check authentication for non-local env if (!apiService.isLocal() && !authService.isAuthenticated()) { JOptionPane.showMessageDialog( getCanvas(), "Please login to use automatic mask detection.", "Authentication Required", JOptionPane.WARNING_MESSAGE); break; } updateCurrentLayerHistory(); detectFaceMasks(); break; Loading Loading
FaceEngines/src/main/java/cz/fidentis/analyst/engines/face/ApiService.java +14 −2 Original line number Diff line number Diff line Loading @@ -31,9 +31,11 @@ public class ApiService { public ApiService(ApiConfig apiConfig) { this.apiConfig = apiConfig; LOGGER.debug( "ApiEnvironmentManager initialized: landmarks local={}, external={}", "ApiEnvironmentManager initialized: landmarks local={}, stratus={}, masks local={}, stratus={}", apiConfig.getLandmarks().getUrl().getLocal(), apiConfig.getLandmarks().getUrl().getStratus()); apiConfig.getLandmarks().getUrl().getStratus(), apiConfig.getMasks().getUrl().getLocal(), apiConfig.getMasks().getUrl().getStratus()); } /** Loading Loading @@ -64,4 +66,14 @@ public class ApiService { var url = apiConfig.getLandmarks().getUrl(); return environment == ApiEnvironment.LOCAL ? url.getLocal() : url.getStratus(); } /** * Returns the masks service URL for the current environment. * * @return masks service URL */ public String getMasksServiceUrl() { var url = apiConfig.getMasks().getUrl(); return environment == ApiEnvironment.LOCAL ? url.getLocal() : url.getStratus(); } }
FaceEngines/src/main/java/cz/fidentis/analyst/engines/face/config/ApiConfig.java +12 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ import org.springframework.stereotype.Component; public class ApiConfig { private LandmarksConfig landmarks; private MasksConfig masks; /** * Configuration for the landmarks detection service. Loading @@ -30,6 +31,17 @@ public class ApiConfig { private UrlConfig url; } /** * Configuration for the masks detection service. * * @author Marek Drozdik */ @Getter @Setter public static class MasksConfig { private UrlConfig url; } /** * Holds local and stratus URL variants for a service. * Loading
FaceEngines/src/main/java/cz/fidentis/analyst/engines/face/impl/FaceMasksServicesImpl.java +38 −19 Original line number Diff line number Diff line package cz.fidentis.analyst.engines.face.impl; import cz.fidentis.analyst.authentication.AuthService; import cz.fidentis.analyst.authentication.exceptions.AuthException; import cz.fidentis.analyst.data.face.Aca; import cz.fidentis.analyst.data.face.HumanFace; import cz.fidentis.analyst.data.mesh.MeshIO; import cz.fidentis.analyst.data.mesh.MeshModel; import cz.fidentis.analyst.data.shapes.Box; import cz.fidentis.analyst.data.surfacemask.Mask3DProjection; import cz.fidentis.analyst.data.surfacemask.MaskVariant; import cz.fidentis.analyst.engines.face.ApiService; import cz.fidentis.analyst.engines.face.exception.LocalResourceUnavailableException; import cz.fidentis.analyst.engines.face.exception.RemoteServiceFailedException; import cz.fidentis.analyst.engines.face.exception.RemoteServiceUnreachableException; Loading @@ -16,13 +20,17 @@ import cz.fidentis.analyst.engines.face.facemasksapi.model.FaceMask; import cz.fidentis.analyst.engines.face.facemasksapi.model.FaceMaskVariant; import cz.fidentis.analyst.engines.interactivemask.BoundingBoxMaskProjector; import cz.fidentis.analyst.engines.interactivemask.BoundingBoxMaskProjectorConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.vecmath.Point2d; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.*; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Services related to the masks detection and management. Loading @@ -32,6 +40,8 @@ import java.util.*; */ public class FaceMasksServicesImpl { private static final Logger LOGGER = LoggerFactory.getLogger(FaceMasksServicesImpl.class); /** * Runs automatic detection of face masks for pre-defined parts of the face. * Loading Loading @@ -127,27 +137,36 @@ public class FaceMasksServicesImpl { return mask3DProjections; } /** * Creates and configures a client for interacting with the masks detection API. * <p> * In local mode, no authentication is needed. * </p> * * @return A configured {@link FaceMasksApi} client for making requests to the * masks detection service. * @throws LocalResourceUnavailableException if user is not authenticated (non-local mode only) */ private FaceMasksApi getFaceMaskDetectorClient() throws LocalResourceUnavailableException { // Read config data from property file generated by maven InputStream is = getClass().getClassLoader().getResourceAsStream("my.properties"); java.util.Properties p = new Properties(); try { p.load(is); } catch (IOException e) { throw new LocalResourceUnavailableException(e); } String apiUrl = p.getProperty("fidentis.ai.masks.service.url"); String apiKey = p.getProperty("fidentis.ai.masks.api.key"); ApiService apiService = Aca.getInstance().getBean(ApiService.class); String apiUrl = apiService.getMasksServiceUrl(); ApiClient apiClient = new ApiClient(); apiClient.setBasePath(apiUrl); apiClient.setVerifyingSsl(false); // allowing self-signed certificates // allowing self-signed certificates apiClient.setVerifyingSsl(false); // setting authentication key apiClient.setApiKeyPrefix("Bearer"); apiClient.setApiKey(apiKey); // Local env does not require authentication if (!apiService.isLocal()) { String accessToken; try { AuthService authService = Aca.getInstance().getBean(AuthService.class); accessToken = authService.getValidAccessToken(); } catch (AuthException e) { LOGGER.warn("User not authenticated for mask detection: {}", e.getMessage()); throw new LocalResourceUnavailableException("User not authenticated", e); } apiClient.setBearerToken(accessToken); } return new FaceMasksApi(apiClient); } Loading
FaceEngines/src/test/resources/application-test.yml +4 −0 Original line number Diff line number Diff line Loading @@ -15,3 +15,7 @@ fidentis: url: local: https://localhost:8080 stratus: https://localhost:8080 masks: url: local: https://localhost:8000 stratus: https://localhost:8000
GUI/src/main/java/cz/fidentis/analyst/gui/task/masks/InteractiveMaskAction.java +18 −1 Original line number Diff line number Diff line package cz.fidentis.analyst.gui.task.masks; import cz.fidentis.analyst.authentication.AuthService; import cz.fidentis.analyst.canvas.Canvas; import cz.fidentis.analyst.data.face.Aca; import cz.fidentis.analyst.data.shapes.Box; import cz.fidentis.analyst.data.shapes.CrossSection3D; import cz.fidentis.analyst.data.surfacemask.*; import cz.fidentis.analyst.engines.face.ApiService; import cz.fidentis.analyst.engines.face.FaceMasksServices; import cz.fidentis.analyst.engines.face.FaceStateServices; import cz.fidentis.analyst.engines.face.exception.RemoteServiceException; Loading @@ -11,8 +14,8 @@ import cz.fidentis.analyst.engines.interactivemask.BoundingBoxMaskProjector; import cz.fidentis.analyst.engines.interactivemask.MaskProjector; import cz.fidentis.analyst.engines.interactivemask.MaskProjectorBack; import cz.fidentis.analyst.engines.interactivemask.MaskProjectorConfig; import cz.fidentis.analyst.gui.task.ControlPanelAction; import cz.fidentis.analyst.gui.elements.RemoteServiceWorker; import cz.fidentis.analyst.gui.task.ControlPanelAction; import cz.fidentis.analyst.project.Task; import cz.fidentis.analyst.rendering.Camera; Loading @@ -36,6 +39,9 @@ import static cz.fidentis.analyst.gui.task.masks.InteractiveMaskPanel.ACTION_PRO public class InteractiveMaskAction extends ControlPanelAction<InteractiveMaskPanel> { private static final Vector3d FRONTAL_CAMERA_POSITION = new Vector3d(0, 0, BoundingBoxMaskProjector.PROJECTION_DISTANCE); private final AuthService authService; private final ApiService apiService; /** * Constructor * A new {@code InteractiveMaskPanel} is instantiated and added to the {@code topControlPane} Loading @@ -46,6 +52,8 @@ public class InteractiveMaskAction extends ControlPanelAction<InteractiveMaskPan */ public InteractiveMaskAction(Canvas canvas, Task task, JTabbedPane topControlPane) { super(canvas, task, topControlPane); this.authService = Aca.getInstance().getBean(AuthService.class); this.apiService = Aca.getInstance().getBean(ApiService.class); InteractiveMaskPanel pl = new InteractiveMaskPanel(this); setControlPanel(pl); pl.getSurfaceMaskPanel1().setFaceBoundingBox(getPrimaryFace().getBoundingBox()); Loading Loading @@ -255,6 +263,15 @@ public class InteractiveMaskAction extends ControlPanelAction<InteractiveMaskPan renderScene(); break; case InteractiveMaskPanel.ACTION_DETECTION_RUN: // Check authentication for non-local env if (!apiService.isLocal() && !authService.isAuthenticated()) { JOptionPane.showMessageDialog( getCanvas(), "Please login to use automatic mask detection.", "Authentication Required", JOptionPane.WARNING_MESSAGE); break; } updateCurrentLayerHistory(); detectFaceMasks(); break; Loading