madoo.mask-measurements/v1
Madoo mask measurements — Where the subject of an image is and how big it is, per region: box, area, coverage, centroid, edges touched, bands and profile (Measure Subject).
| Reference | madoo.mask-measurements/v1 |
| Schema id | urn:madoo:schema:mask-measurements:v1 |
| Version | 1.0.0 |
| Served at | GET /api/v1/json-schemas/madoo.mask-measurements/v1 · MCP get_json_schema |
Where it appears
Section titled “Where it appears”No node port declares it.
Fields
Section titled “Fields”| Field | Type | Required | Rules | Description |
|---|---|---|---|---|
schema |
"madoo.mask-measurements/v1" |
yes | ||
image |
object | yes | ||
image.width |
integer | yes | ≥ 1 | |
image.height |
integer | yes | ≥ 1 | |
source |
one of "alpha", "luminance" |
yes | The channel actually read. | |
threshold |
integer | yes | ≥ 0; ≤ 254 | A pixel is subject when its value is greater than this. |
invert |
boolean | yes | ||
axis |
one of "rows", "columns" |
yes | ||
length_mode |
one of "count", "span", "longest_run" |
What a line’s length is for bands and profile. Absent in documents written before the parameter existed: read it as count. | ||
min_line_pixels |
integer | yes | ≥ 0 | |
grid |
object or null | The grid, or null when explicit regions were measured. | ||
grid.rows |
integer | |||
grid.cols |
integer | |||
regions |
array of objects | yes | ||
regions[].index |
integer | yes | ≥ 1 | |
regions[].row |
integer | ≥ 0 | Grid row; absent for explicit regions. | |
regions[].col |
integer | ≥ 0 | ||
regions[].cell |
object | yes | The measured region. | |
regions[].cell.x |
integer | yes | ||
regions[].cell.y |
integer | yes | ||
regions[].cell.width |
integer | yes | ||
regions[].cell.height |
integer | yes | ||
regions[].empty |
boolean | yes | True when no line has more than min_line_pixels subject pixels; then only area and coverage (0) and touches (all false) are present. | |
regions[].first_line |
integer | First line of the subject along the axis (a y on rows, an x on columns). | ||
regions[].last_line |
integer | Last line of the subject, included. | ||
regions[].extent |
integer | ≥ 1 | last_line - first_line + 1: lines occupied, the bounding box side along the axis. | |
regions[].bbox |
object | |||
regions[].bbox.x |
integer | yes | ||
regions[].bbox.y |
integer | yes | ||
regions[].bbox.width |
integer | yes | ||
regions[].bbox.height |
integer | yes | ||
regions[].bbox_normalized |
object | The bbox divided by the image width and height. | ||
regions[].bbox_normalized.x |
number | yes | ||
regions[].bbox_normalized.y |
number | yes | ||
regions[].bbox_normalized.width |
number | yes | ||
regions[].bbox_normalized.height |
number | yes | ||
regions[].area |
integer | ≥ 0 | Subject pixels on lines first_line..last_line. | |
regions[].coverage |
number | ≥ 0; ≤ 1 | area / cell area. | |
regions[].centroid |
object | |||
regions[].centroid.x |
number | yes | ||
regions[].centroid.y |
number | yes | ||
regions[].centroid_normalized |
object | |||
regions[].centroid_normalized.x |
number | yes | ||
regions[].centroid_normalized.y |
number | yes | ||
regions[].touches |
object | Whether the subject reaches each edge of the region: cut off, or spilling in from a neighbouring cell. | ||
regions[].touches.left |
boolean | yes | ||
regions[].touches.right |
boolean | yes | ||
regions[].touches.top |
boolean | yes | ||
regions[].touches.bottom |
boolean | yes | ||
regions[].bands |
array of objects | |||
regions[].bands[].start |
number | yes | ||
regions[].bands[].end |
number | yes | ||
regions[].bands[].first_line |
integer | yes | first_line + floor(extent x start), included. | |
regions[].bands[].end_line |
integer | yes | first_line + floor(extent x end), excluded. | |
regions[].bands[].pixels |
integer | yes | Sum of the band lines’ lengths: the band’s subject pixels with length_mode count, the pixels the spans or longest runs cover otherwise. | |
regions[].bands[].mean_length |
number or null | pixels / band lines: a mean width on rows, a mean height on columns, per length_mode. | ||
regions[].bands[].relative_length |
number or null | mean_length / extent: independent of zoom and distance. | ||
regions[].bands[].center |
number or null | Mean position across the axis of what was measured (subject pixels, spans or longest runs per length_mode): an x on rows, a y on columns. | ||
regions[].profile |
array of objects | |||
regions[].profile[].at |
number | yes | ≥ 0; ≤ 1 | |
regions[].profile[].line |
integer | yes | ||
regions[].profile[].length |
integer | yes | The line’s length per length_mode. | |
regions[].profile[].relative_length |
number | yes |
The complete schema
Section titled “The complete schema”madoo.mask-measurements/v1 (JSON Schema)
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "urn:madoo:schema:mask-measurements:v1", "title": "Madoo mask measurements", "description": "What Measure Subject (image/mask_measure) measured: the image, the settings that matter to read the numbers, and one entry per region (the whole image, each grid cell in reading order, or each requested rectangle). Coordinates are pixels of the whole image, origin top left. A line is a row on axis rows and a column on axis columns. Its length, for bands and profile, follows length_mode: count = every subject pixel on it, span = from the first to the last subject pixel (gaps included), longest_run = the longest unbroken run of subject pixels. Area, coverage, bbox, centroid, first_line and last_line always count subject pixels. An empty region carries its index, cell, empty: true, area and coverage 0 and touches all false; no shape measurement.", "type": "object", "required": [ "schema", "image", "source", "threshold", "invert", "axis", "min_line_pixels", "regions" ], "properties": { "schema": { "const": "madoo.mask-measurements/v1" }, "image": { "type": "object", "required": [ "width", "height" ], "properties": { "width": { "type": "integer", "minimum": 1 }, "height": { "type": "integer", "minimum": 1 } } }, "source": { "enum": [ "alpha", "luminance" ], "description": "The channel actually read." }, "threshold": { "type": "integer", "minimum": 0, "maximum": 254, "description": "A pixel is subject when its value is greater than this." }, "invert": { "type": "boolean" }, "axis": { "enum": [ "rows", "columns" ] }, "length_mode": { "enum": [ "count", "span", "longest_run" ], "description": "What a line's length is for bands and profile. Absent in documents written before the parameter existed: read it as count." }, "min_line_pixels": { "type": "integer", "minimum": 0 }, "grid": { "type": [ "object", "null" ], "properties": { "rows": { "type": "integer" }, "cols": { "type": "integer" } }, "description": "The grid, or null when explicit regions were measured." }, "regions": { "type": "array", "items": { "type": "object", "required": [ "index", "cell", "empty" ], "properties": { "index": { "type": "integer", "minimum": 1 }, "row": { "type": "integer", "minimum": 0, "description": "Grid row; absent for explicit regions." }, "col": { "type": "integer", "minimum": 0 }, "cell": { "$ref": "#/$defs/rect", "description": "The measured region." }, "empty": { "type": "boolean", "description": "True when no line has more than min_line_pixels subject pixels; then only area and coverage (0) and touches (all false) are present." }, "first_line": { "type": "integer", "description": "First line of the subject along the axis (a y on rows, an x on columns)." }, "last_line": { "type": "integer", "description": "Last line of the subject, included." }, "extent": { "type": "integer", "minimum": 1, "description": "last_line - first_line + 1: lines occupied, the bounding box side along the axis." }, "bbox": { "$ref": "#/$defs/rect" }, "bbox_normalized": { "$ref": "#/$defs/rectNormalized", "description": "The bbox divided by the image width and height." }, "area": { "type": "integer", "minimum": 0, "description": "Subject pixels on lines first_line..last_line." }, "coverage": { "type": "number", "minimum": 0, "maximum": 1, "description": "area / cell area." }, "centroid": { "$ref": "#/$defs/point" }, "centroid_normalized": { "$ref": "#/$defs/point" }, "touches": { "type": "object", "required": [ "left", "right", "top", "bottom" ], "properties": { "left": { "type": "boolean" }, "right": { "type": "boolean" }, "top": { "type": "boolean" }, "bottom": { "type": "boolean" } }, "description": "Whether the subject reaches each edge of the region: cut off, or spilling in from a neighbouring cell." }, "bands": { "type": "array", "items": { "type": "object", "required": [ "start", "end", "first_line", "end_line", "pixels" ], "properties": { "start": { "type": "number" }, "end": { "type": "number" }, "first_line": { "type": "integer", "description": "first_line + floor(extent x start), included." }, "end_line": { "type": "integer", "description": "first_line + floor(extent x end), excluded." }, "pixels": { "type": "integer", "description": "Sum of the band lines' lengths: the band's subject pixels with length_mode count, the pixels the spans or longest runs cover otherwise." }, "mean_length": { "type": [ "number", "null" ], "description": "pixels / band lines: a mean width on rows, a mean height on columns, per length_mode." }, "relative_length": { "type": [ "number", "null" ], "description": "mean_length / extent: independent of zoom and distance." }, "center": { "type": [ "number", "null" ], "description": "Mean position across the axis of what was measured (subject pixels, spans or longest runs per length_mode): an x on rows, a y on columns." } } } }, "profile": { "type": "array", "items": { "type": "object", "required": [ "at", "line", "length", "relative_length" ], "properties": { "at": { "type": "number", "minimum": 0, "maximum": 1 }, "line": { "type": "integer" }, "length": { "type": "integer", "description": "The line's length per length_mode." }, "relative_length": { "type": "number" } } } } } } } }, "$defs": { "rect": { "type": "object", "required": [ "x", "y", "width", "height" ], "properties": { "x": { "type": "integer" }, "y": { "type": "integer" }, "width": { "type": "integer" }, "height": { "type": "integer" } } }, "rectNormalized": { "type": "object", "required": [ "x", "y", "width", "height" ], "properties": { "x": { "type": "number" }, "y": { "type": "number" }, "width": { "type": "number" }, "height": { "type": "number" } } }, "point": { "type": "object", "required": [ "x", "y" ], "properties": { "x": { "type": "number" }, "y": { "type": "number" } } } }, "examples": [ { "schema": "madoo.mask-measurements/v1", "image": { "width": 1536, "height": 2048 }, "source": "alpha", "threshold": 128, "invert": false, "axis": "rows", "length_mode": "count", "min_line_pixels": 3, "grid": { "rows": 2, "cols": 4 }, "regions": [ { "index": 1, "row": 0, "col": 0, "cell": { "x": 0, "y": 0, "width": 384, "height": 1024 }, "empty": false, "first_line": 37, "last_line": 989, "extent": 953, "bbox": { "x": 24, "y": 37, "width": 344, "height": 953 }, "bbox_normalized": { "x": 0.015625, "y": 0.018066, "width": 0.223958, "height": 0.465332 }, "area": 213674, "coverage": 0.543401, "centroid": { "x": 196.4, "y": 541.2 }, "centroid_normalized": { "x": 0.127865, "y": 0.264258 }, "touches": { "left": false, "right": false, "top": false, "bottom": false }, "bands": [ { "start": 0.35, "end": 0.6, "first_line": 370, "end_line": 608, "pixels": 77090, "mean_length": 323.9076, "relative_length": 0.339882, "center": 196.157 } ] }, { "index": 4, "row": 0, "col": 3, "cell": { "x": 1152, "y": 0, "width": 384, "height": 1024 }, "empty": true, "area": 0, "coverage": 0, "touches": { "left": false, "right": false, "top": false, "bottom": false } } ] } ]}