From 235bee9fa6429b561f50a3c9937081b86576b795 Mon Sep 17 00:00:00 2001 From: Liam Wu Date: Mon, 11 Nov 2024 12:11:19 +1100 Subject: [PATCH] feat: add spec get endpoint --- api/config/models.py | 34 +++++++++++++++++++++-- api/routes/index.py | 65 +++++++++++++++++++++++++++++++++++++++++++- api/utils.py | 23 ++++++++++++++++ 3 files changed, 119 insertions(+), 3 deletions(-) diff --git a/api/config/models.py b/api/config/models.py index 125c353..a184333 100644 --- a/api/config/models.py +++ b/api/config/models.py @@ -644,7 +644,7 @@ class TaskQueue(BaseModel): class FaceSpecBQAT(str, Enum): ipd = "Inter-pupillary distance." - confidence = "Confidence level of face dectection (not quality score)." + face_detection = "Confidence level of face dectection (not quality score)." bbox_left = "Left border of the face bounding box coordinates in pixels." bbox_right = "Right border of the face bounding box coordinates in pixels." bbox_upper = "Upper border of the face bounding box coordinates in pixels." @@ -662,7 +662,37 @@ class FaceSpecBQAT(str, Enum): roll_pose = "Roll in head pose direction." roll_degree = "Roll in head pose degree." smile = "Smile detected or not." - glassed = "Glasses detected or not." + glasses = "Eyeglasses/Spectacles detected or not." + face_ratio = "Ratio of face area to whole image." + brightness = "Average brightness of the image." + dynamic_range = "Dynamic range of the image." + sharpness = "Shaphness of the image." + contrast = "Contrast of the image." + face_offset_x = "Horizontal offset of the face from image centre." + face_offset_y = "Vertical offset of the face from image centre." + background_colour_name = "Background colour name." + background_colour_rgb = "Background colour rgb values." + background_uniformity = "Background colour uniformity." + hair_coverage = "Ratio of detected hair area to whole face bounding box." + blur_lap_var = "Laplacian variance of image as a indicator of blurriness" + blurriness = "Blur effect metric. A estimate strength of perceptual blurriness." + gaze_right_x = "Right eyeball gazing direction offset percentage horizontal." + gaze_right_y = "Right eyeball gazing direction offset percentage vertical." + gaze_left_x = "Left eyeball gazing direction offset percentage horizontal." + gaze_left_y = "Left eyeball gazing direction offset percentage vertical." + pupil_colour_right_name = "Right pupil colour name." + pupil_colour_right_rgb = "Right pupil colour rgb values." + pupil_colour_left_name = "Left pupil colour name." + pupil_colour_left_rgb = "Left pupil colour rgb values." + brisque_quality = "Blind/Referenceless Image Spatial Quality Evaluator (BRISQUE) no-reference image quality score" + age = "Estimation of age." + gender = "Estimation of gender." + ethnicity = "Estimation of ethnicity." + emotion = "Estimation of emotions." + is_hologram = "Hologram effect detected or not." + holograms = "Hologram area detected." + is_glare = "Glare/Reflection on the image detected or not." + glares = "Glare area detected." class FaceSpecOFIQ(str, Enum): diff --git a/api/routes/index.py b/api/routes/index.py index a7ddf18..8f3d428 100644 --- a/api/routes/index.py +++ b/api/routes/index.py @@ -17,7 +17,16 @@ from PIL import Image as PILImage from api.config import Settings -from api.config.models import ImageRequest +from api.config.models import ( + FaceSpecBIQT, + FaceSpecBQAT, + FaceSpecOFIQ, + FingerprintSpecDefault, + ImageRequest, + IrisSpecDefault, + Modality, + SpeechSpecDefault, +) from api.utils import ensure_base64_padding, extend, get_info router = APIRouter() @@ -216,3 +225,57 @@ async def delete_dataset( ) async def get_version_info(): return JSONResponse(status_code=status.HTTP_200_OK, content=get_info()) + + +@router.get( + "/specification", + response_description="Output descriptions retrieved", + description="Fetches output columns descriptions.", +) +async def get_description(modality: Modality, engine: str = "default"): + match modality: + case Modality.face: + match engine: + case "bqat" | "default": + return {item.name: item.value for item in FaceSpecBQAT} + case "ofiq": + return {item.name: item.value for item in FaceSpecOFIQ} + case "biqt": + return {item.name: item.value for item in FaceSpecBIQT} + case _: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid engine specified.", + ) + case Modality.fingerprint: + match engine: + case "default": + return {item.name: item.value for item in FingerprintSpecDefault} + case _: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid engine specified.", + ) + case Modality.iris: + match engine: + case "default": + return {item.name: item.value for item in IrisSpecDefault} + case _: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid engine specified.", + ) + case Modality.speech: + match engine: + case "default": + return {item.name: item.value for item in SpeechSpecDefault} + case _: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid engine specified.", + ) + case _: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid modality specified.", + ) diff --git a/api/utils.py b/api/utils.py index abb0282..439f3d4 100644 --- a/api/utils.py +++ b/api/utils.py @@ -897,6 +897,7 @@ async def run_report_tasks( { "mode": dataset_log["options"].get("mode"), "engine": dataset_log["options"].get("engine"), + "fusion": dataset_log["options"].get("fusion"), } ) @@ -1581,6 +1582,28 @@ def generate_report(data, **options): metadata = { "description": "Face image dataset, processed by BIQT engine." } + case "fusion": + descriptions = {} + engines = [] + fusion_code = options.get("fusion", 0) + if fusion_code & 4 == 4: + descriptions.update( + {item.name: item.value for item in FaceSpecBQAT} + ) + engines.append("BQAT") + if fusion_code & 2 == 2: + descriptions.update( + {item.name: item.value for item in FaceSpecOFIQ} + ) + engines.append("OFIQ") + if fusion_code & 1 == 1: + descriptions.update( + {item.name: item.value for item in FaceSpecBIQT} + ) + engines.append("BIQT") + metadata = { + "description": f"Folder of face images, processed by fusion engine{' (' + ', '.join(engines) + ')' if engines else ''}." + } case _: descriptions = {} metadata = {"description": "Face image dataset."}