Right now AI is making a visual judgement. Later we will add a known-size reference beside the finger, calculate pixels per millimetre, locate the fingertip and nail edges, and compare a calibrated free-edge measurement with the school rule.
IMAGE → REFERENCE SCALE → PIXELS PER MM → FINGERTIP EDGE → NAIL EDGE → FREE EDGE PIXELS → MILLIMETRES → COMPARE WITH SCHOOL RULE
API mode: Interactions
Model: gemini-3.6-flash
Gemini configured: Yes
Connection: Not tested
Gemini requests today: 0 / 100
[
{
"request_id": "gem_20260903133650_bec871f44d21",
"created_at": "2026-09-03T13:37:01+00:00",
"request_type": "interactions_vision",
"api_mode": "interactions",
"interaction_id": null,
"ok": true,
"code": null,
"http_status": 200,
"google_status": null,
"google_error_code": null,
"sanitized_error": null,
"model": "gemini-3.6-flash",
"prompt_version": "1",
"processing_time_ms": 11309.4,
"input": {
"sha256": "085fcb0cc2ceb20bbc8dd037858083a15d0ffdd1e3c2857c9191b2d9a9855ac9",
"width": 564,
"height": 224,
"size_bytes": 10651,
"mime": "image/jpeg"
},
"cache_hit": false,
"school_rules": {
"rules_version": "school_rules_v1",
"length_check_enabled": true,
"maximum_free_edge_mm": 3,
"visual_tolerance": "normal",
"cleanliness_check_enabled": false,
"polish_check_enabled": false,
"artificial_nail_check_enabled": false,
"uncertain_policy": "RECHECK",
"borderline_result": "RECHECK",
"prompt_behavior": "NORMAL: make a cautious ordinary visual screening; return UNCERTAIN for borderline views."
},
"result": {
"suitable": true,
"finger_count": 5,
"finger": {
"box_2d": [
294,
395,
735,
460
],
"tip": [
294,
432
]
},
"nail": {
"visible": true,
"box_2d": [
294,
417,
360,
458
],
"polygon": [
[
294,
432
],
[
298,
421
],
[
315,
417
],
[
345,
418
],
[
358,
428
],
[
358,
442
],
[
348,
455
],
[
318,
458
],
[
298,
450
]
],
"free_edge": [
[
294,
423
],
[
294,
432
],
[
295,
445
]
],
"mask": [
[
294,
432
],
[
298,
421
],
[
315,
417
],
[
345,
418
],
[
358,
428
],
[
358,
442
],
[
348,
455
],
[
318,
458
],
[
298,
450
]
]
},
"quality": {
"blur": "low",
"lighting": "dim",
"occluded": false
},
"school_screening": {
"status": "LOOKS_ACCEPTABLE",
"rule_maximum_free_edge_mm": 3,
"visual_assessment": "The fingernails appear neatly trimmed and short. They are well within acceptable length limits.",
"confidence": "high",
"measurement_available": false,
"requires_calibration_for_mm": true
},
"student_message": ""
},
"normalized_coordinates": {
"finger_box": [
294,
395,
735,
460
],
"finger_tip": [
294,
432
],
"nail_box": [
294,
417,
360,
458
],
"nail_polygon": [
[
294,
432
],
[
298,
421
],
[
315,
417
],
[
345,
418
],
[
358,
428
],
[
358,
442
],
[
348,
455
],
[
318,
458
],
[
298,
450
]
]
},
"source_coordinates": {
"finger_box": {
"x": 222.78,
"y": 65.86,
"width": 36.66,
"height": 98.78
},
"finger_tip": {
"x": 243.65,
"y": 65.86
},
"nail_box": {
"x": 235.19,
"y": 65.86,
"width": 23.12,
"height": 14.78
},
"nail_polygon": [
{
"x": 243.65,
"y": 65.86
},
{
"x": 237.44,
"y": 66.75
},
{
"x": 235.19,
"y": 70.56
},
{
"x": 235.75,
"y": 77.28
},
{
"x": 241.39,
"y": 80.19
},
{
"x": 249.29,
"y": 80.19
},
{
"x": 256.62,
"y": 77.95
},
{
"x": 258.31,
"y": 71.23
},
{
"x": 253.8,
"y": 66.75
}
],
"free_edge": [
{
"x": 238.57,
"y": 65.86
},
{
"x": 243.65,
"y": 65.86
},
{
"x": 250.98,
"y": 66.08
}
]
}
},
{
"request_id": "gem_20260903132034_aedec74cd827",
"created_at": "2026-09-03T13:20:43+00:00",
"request_type": "interactions_vision",
"api_mode": "interactions",
"interaction_id": null,
"ok": true,
"code": null,
"http_status": 200,
"google_status": null,
"google_error_code": null,
"sanitized_error": null,
"model": "gemini-3.6-flash",
"prompt_version": "1",
"processing_time_ms": 8581.4,
"input": {
"sha256": "ea31c0b189b4d90d8126221c89c80c2de790585be6c372edc8ce9462ae4e524b",
"width": 564,
"height": 224,
"size_bytes": 10685,
"mime": "image/jpeg"
},
"cache_hit": false,
"result": {
"suitable": true,
"finger_count": 1,
"finger": {
"box_2d": [
292,
510,
529,
925
],
"tip": [
375,
510
]
},
"nail": {
"visible": true,
"box_2d": [
300,
513,
440,
570
],
"polygon": [
[
300,
545
],
[
320,
518
],
[
375,
510
],
[
425,
525
],
[
440,
550
],
[
400,
568
],
[
340,
565
]
],
"mask": [
[
300,
545
],
[
320,
518
],
[
375,
510
],
[
425,
525
],
[
440,
550
],
[
400,
568
],
[
340,
565
]
]
},
"quality": {
"blur": "low",
"lighting": "dim",
"occluded": false
},
"student_message": ""
},
"normalized_coordinates": {
"finger_box": [
292,
510,
529,
925
],
"finger_tip": [
375,
510
],
"nail_box": [
300,
513,
440,
570
],
"nail_polygon": [
[
300,
545
],
[
320,
518
],
[
375,
510
],
[
425,
525
],
[
440,
550
],
[
400,
568
],
[
340,
565
]
]
},
"source_coordinates": {
"finger_box": {
"x": 287.64,
"y": 65.41,
"width": 234.06,
"height": 53.09
},
"finger_tip": {
"x": 287.64,
"y": 84
},
"nail_box": {
"x": 289.33,
"y": 67.2,
"width": 32.15,
"height": 31.36
},
"nail_polygon": [
{
"x": 307.38,
"y": 67.2
},
{
"x": 292.15,
"y": 71.68
},
{
"x": 287.64,
"y": 84
},
{
"x": 296.1,
"y": 95.2
},
{
"x": 310.2,
"y": 98.56
},
{
"x": 320.35,
"y": 89.6
},
{
"x": 318.66,
"y": 76.16
}
]
}
},
{
"request_id": "gem_20260903122848_02a49695907c",
"created_at": "2026-09-03T12:28:49+00:00",
"ok": false,
"code": "gemini_model_unavailable",
"http_status": 404,
"google_status": "NOT_FOUND",
"google_error_code": 404,
"sanitized_error": "This model models/gemini-2.5-flash is no longer available to new users. Please update your code to use models/gemini-3.6-flash for the latest features and improvements. We recommend you to use the Interactions API.",
"model": "gemini-2.5-flash",
"prompt_version": "1",
"processing_time_ms": 310.4,
"input": {
"sha256": "e3a50eb67f2002cbebb67b582667ec2089d2308d97da652ca56a248b0161b8d1",
"width": 564,
"height": 224,
"size_bytes": 11923,
"mime": "image/jpeg"
},
"cache_hit": false
},
{
"request_id": "gem_20260903122432_b6dbe17a42ea",
"created_at": "2026-09-03T12:24:33+00:00",
"ok": false,
"code": "gemini_model_unavailable",
"http_status": 404,
"google_status": "NOT_FOUND",
"google_error_code": 404,
"sanitized_error": "This model models/gemini-2.5-flash is no longer available to new users. Please update your code to use models/gemini-3.6-flash for the latest features and improvements. We recommen",
"model": "gemini-2.5-flash",
"prompt_version": "1",
"processing_time_ms": 315.4,
"input": {
"sha256": "06e5610e36a80dda493e4443450fe00e1eb72eb7fa1fadaca4afaba50547cc12",
"width": 564,
"height": 224,
"size_bytes": 15530,
"mime": "image/jpeg"
},
"cache_hit": false
},
{
"request_id": "gem_20260903121941_825125b9eaf8",
"created_at": "2026-09-03T12:19:42+00:00",
"ok": false,
"code": "gemini_http_error",
"sanitized_error": "HTTP 404",
"model": "gemini-2.5-flash",
"prompt_version": "1",
"processing_time_ms": 401.6,
"input": {
"sha256": "3adfb83b1c405b6840c60998c2364dcfa1580ef624002127a22df462eca8eb1f",
"width": 564,
"height": 224,
"size_bytes": 15249,
"mime": "image/jpeg"
},
"cache_hit": false
}
]Development mode: analysis images are currently being stored on this server for detector improvement. Oldest attempts are automatically removed after 300 records.
Student STEM Lab · Experimental Detectors / Full Hand Detector · Teacher / Presentation Mode · Export Training Dataset
Student Mode is collecting the examples that will teach a future AI what a nail looks like. The student's marking is the correct answer, called ground truth.
Ground Truth: The correct answer provided by a person for an AI training example.
Reprocess Original ROI with OpenCV Detector — creates a new linked attempt and preserves this record.
Click an image for full-size inspection. Missing stages remain visible so detector versions can be compared.







Compare a map or trace directly over RGB. The images are scaled into the same viewport.
| Representation | Score / Evidence |
|---|---|
| Geometry | N/A |
| Grayscale | N/A |
| Local Contrast | N/A |
| Edge | N/A |
| Saturation | N/A |
| Chroma | N/A |
| Texture | N/A |
| Boundary | N/A |
| Highlight Penalty | N/A |
| Fused | N/A |
| Representation Agreement | N/A |
| Ensemble Agreement | N/A |
| ID | Detector | BBox | Area | Width ratio | Length ratio | Aspect | Centerline | Tip distance | Brightness Δ | Saturation Δ | Chroma Δ | Texture | Edge | Boundary | Highlight | Geometry | Fused | Total | Decision |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | [] |
| N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | ["below_minimum_area_ratio"] |
| N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | ["below_minimum_area_ratio"] |
| N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | ["below_minimum_area_ratio"] |
| N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | ["below_minimum_area_ratio"] |
| N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | ["below_minimum_area_ratio"] |
{
"camera": {
"width": 720,
"height": 1280,
"frame_rate": 10,
"facing_mode": "environment"
},
"roi": {
"x": 109,
"y": 570,
"width": 504,
"height": 142
},
"original_roi": {
"width": 504,
"height": 142
},
"analysis": {
"width": 400,
"height": 113
},
"segmentation": {
"raw_skin_pixels": 25841,
"cleaned_skin_pixels": 25899,
"cleaned_skin_ratio": 0.5729867256637168
},
"finger": {
"detected": true,
"area_pixels": 25899,
"bounding_box": {
"x": 65,
"y": 1,
"width": 334,
"height": 101
},
"centroid": {
"x": 247.99795358894167,
"y": 55.69369473724854
},
"area_ratio": 0.5729867256637168,
"boundary_clipped": true,
"center_offset_ratio": 0.08
},
"fingertip": {
"detected": true,
"x": 368.17755443886097,
"y": 6.785594639865996,
"method": "centroid_of_uppermost_10_percent_band"
},
"nail_search": {
"bounding_box": {
"x": 255,
"y": 1,
"width": 227,
"height": 49
},
"finger_mean_brightness": 116.43113633731032,
"finger_mean_saturation": 0.42216816161526477,
"brightness_threshold_offset": 8,
"saturation_threshold_factor": 0.92
},
"nail_candidates": {
"count": 6,
"considered": [
{
"bounding_box": {
"x": 255,
"y": 1,
"width": 97,
"height": 27
},
"area_pixels": 470,
"area_ratio": 0.01814741881925943,
"mean_brightness": 139.98510638297873,
"mean_saturation": 0.22780884322722283,
"contrast": 23.553970045668407,
"candidate_score": 88.60909573109177,
"valid_size": true,
"rejection_reasons": []
},
{
"bounding_box": {
"x": 276,
"y": 36,
"width": 6,
"height": 7
},
"area_pixels": 29,
"area_ratio": 0.0011197343526777096,
"mean_brightness": 145.48275862068965,
"mean_saturation": 0.3781758648945056,
"contrast": 29.05162228337933,
"candidate_score": 34.29419611855214,
"valid_size": false,
"rejection_reasons": [
"below_minimum_area_ratio"
]
},
{
"bounding_box": {
"x": 355,
"y": 13,
"width": 9,
"height": 4
},
"area_pixels": 28,
"area_ratio": 0.0010811228232750299,
"mean_brightness": 154.53571428571428,
"mean_saturation": 0.3795032325502337,
"contrast": 38.10457794840396,
"candidate_score": 48.47172341689662,
"valid_size": false,
"rejection_reasons": [
"below_minimum_area_ratio"
]
},
{
"bounding_box": {
"x": 384,
"y": 7,
"width": 4,
"height": 5
},
"area_pixels": 15,
"area_ratio": 0.0005791729410401946,
"mean_brightness": 148.86666666666667,
"mean_saturation": 0.3870678842872902,
"contrast": 32.435530329356354,
"candidate_score": 46.86114026749929,
"valid_size": false,
"rejection_reasons": [
"below_minimum_area_ratio"
]
},
{
"bounding_box": {
"x": 390,
"y": 10,
"width": 4,
"height": 4
},
"area_pixels": 14,
"area_ratio": 0.0005405614116375149,
"mean_brightness": 149.92857142857142,
"mean_saturation": 0.37784605210734973,
"contrast": 33.497435091261096,
"candidate_score": 45.80443015830591,
"valid_size": false,
"rejection_reasons": [
"below_minimum_area_ratio"
]
},
{
"bounding_box": {
"x": 349,
"y": 11,
"width": 7,
"height": 3
},
"area_pixels": 14,
"area_ratio": 0.0005405614116375149,
"mean_brightness": 137.21428571428572,
"mean_saturation": 0.37020682463048843,
"contrast": 20.783149376975402,
"candidate_score": 47.238894956171016,
"valid_size": false,
"rejection_reasons": [
"below_minimum_area_ratio"
]
}
]
},
"nail_candidate": {
"detected": true,
"bounding_box": {
"x": 255,
"y": 1,
"width": 97,
"height": 27
},
"area_pixels": 470,
"area_ratio": 0.01814741881925943,
"mean_brightness": 139.98510638297873,
"mean_saturation": 0.22780884322722283,
"contrast": 23.553970045668407,
"candidate_score": 88.60909573109177,
"valid_size": true,
"rejection_reasons": []
},
"confidence": {
"finger_score": 65,
"nail_score": 35,
"boundary_adjustment": -15,
"components": {
"finger_area": 30,
"centering": 20,
"fingertip": 15,
"nail_size": 25,
"nail_contrast": 10,
"boundary": -15
},
"overall_score": 85
},
"result": "Nail candidate detected",
"processing_time_ms": 62.3,
"client": {
"user_agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/30.0 Chrome/143.0.0.0 Mobile Safari/537.36",
"viewport": {
"width": 384,
"height": 661
},
"device_pixel_ratio": 2.8125
},
"attempt_id": "20260903_035013_bd4d1a6f9ea5",
"timestamp": "2026-09-03T03:50:13+00:00",
"detector_version": "1.1.0",
"detector_config": {
"camera_width": 1280,
"camera_height": 720,
"target_fps": 10,
"camera_facing": "environment",
"guide_width_percent": 70,
"guide_height_percent": 35,
"default_max_nail_length_mm": 3,
"analysis_width": 400,
"skin_cb_min": 72,
"skin_cb_max": 138,
"skin_cr_min": 128,
"skin_cr_max": 180,
"skin_saturation_min": 0.05,
"skin_saturation_max": 0.78,
"skin_value_min": 0.12,
"mask_cleanup_passes": 1,
"minimum_finger_area_ratio": 0.1,
"maximum_finger_area_ratio": 0.88,
"nail_minimum_area_ratio": 0.008,
"nail_maximum_area_ratio": 0.2,
"nail_brightness_offset": 8,
"nail_saturation_factor": 0.92,
"nail_search_depth_ratio": 0.48,
"finger_center_tolerance_ratio": 0.24,
"boundary_clip_penalty": 15,
"confidence_detected_threshold": 70,
"confidence_retry_threshold": 40,
"debug_enabled": true,
"detector_version": "1.1.0",
"debug_capture_enabled": true,
"debug_storage_path": "debug_attempts",
"debug_max_attempts": 300,
"debug_jpeg_quality": 0.82
},
"saved_artifacts": [
"original_roi.jpg",
"analysis_input.jpg",
"skin_mask.png",
"cleaned_mask.png",
"finger_detection.png",
"fingertip_detection.png",
"nail_search.png",
"nail_candidates.png",
"nail_candidate.png",
"final_overlay.jpg"
],
"user_feedback": null
}