ImageDrawBoxes
Annotate a page with detection boxes or NER entities. Drawing is a pipeline stage, so the annotated page is just another image column.
- Import
import { ImageDrawBoxes } from '@stabrise/scaledp'- Group
- Transform
- Reads
- image, boxes
- Writes
- image
- Needs
- nothing
- Note
- Terminal — output is for looking at.
import { Pipeline, ImageDrawBoxes } from '@stabrise/scaledp'
new ImageDrawBoxes({
inputCols: ['image', 'text', 'ner'],
outputCol: 'annotated',
displayDataList: ['entity_group', 'score'],
lineWidth: 2,
})The first entry in inputCols is the image; every other entry is a box or entity
source. A source with entities is drawn as NER, one with bboxes as boxes — so
one stage can annotate a page with both.
displayDataList renders fields above each box, joined by :. Valid names are
the schema's own: text, score, angle, x, y, width, height for a
box; entity_group, word, score for an entity. Numbers are formatted to two
decimals.
whiteList and blackList filter entity groups only.
Colours
color: null (the default) colours by group, and the colour is stable: a
given label is the same colour on every render, in the drawn boxes and in
visualizeNer's text, because both call colorForGroup.
Python picks a random colour per run, which makes two renders of the same
document impossible to compare.
import { colorForGroup } from '@stabrise/scaledp'
colorForGroup('person') // the same HSL string every timeEvery entity group the NER models in this library emit has a hue assigned by
hand, spaced 18° from its neighbours. Hashing the name alone is not enough: over
the default PII labels it gives phone_number and date the same hue and puts
person one degree from ip_address, which defeats the point of colouring by
group. Any hash over that many labels collides — it is the birthday problem, not
a bad multiplier. Names for one concept share a hue on purpose, so phone and
phone_number match. A group outside that table still gets a colour, hashed from
its name, so a label nobody anticipated still works.
One stage takes one color for all its sources, which is why a two-colour
overlay is two chained passes — the second reading what the first wrote. That is
how the demo draws detections in cyan and then leaves the entity pass unset, so
each kind of PII gets its own colour.
It is a terminal stage
An annotated page is still an image, but feeding it to a detector means detecting
through the boxes drawn on top of it. The registry marks the stage terminal for
this reason, and column-suggesting interfaces skip it.
Rotated boxes
Drawn as rotated quads, with the label chip riding the box's own top edge. Python places the chip at the envelope corner instead, which detaches it from a steeply rotated box.
Parameters
| Parameter | Type | Default | Meaning |
|---|---|---|---|
inputCols | string[] (2+) | ['image', 'boxes'] | The image first, then one or more box, document or entity columns. |
color | string | null | One colour for every box. Unset colours by group instead. |
filled | boolean | false | Fill boxes as well as outlining them. |
lineWidth | number 0–20 | 1 | Line width |
textSize | number 4–72 | 24 | Text size |
displayDataList | string[] | [] | Rendered above each box, joined by ":". Pick "text" to read the OCR output back off the page. |
padding | number | 0 | Grow each box by this many pixels before drawing. |
whiteList | string[] | [] | Draw only these entity groups; empty draws all. |
blackList | string[] | [] | Never draw these entity groups. |
imageType | 'png' | 'webp' | 'jpeg' | 'png' | Image format |