ProcessBlock example — segment a micrograph
SegmentCellsBlock (segment_cells.py) turns a microscope image into a
labeled cell map: threshold the foreground, fill holes, flood-fill each
connected patch its own integer label, drop the sensor noise. It is the
simplest and most common kind of block: a per-item transform.
Why ProcessBlock
ProcessBlock is for blocks where:
- every item is transformed independently, and
- the number of items does not change (no filtering, merging, or splitting).
You write only process_item(self, item, config, state=None) — the base class
loops over the incoming batch (Collection) and calls it once per item, packing
the results back into a Collection for the output port. About 80% of blocks
need nothing more than this.
What to notice
- Reading the image.
item.to_memory()hands you the pixel grid as a NumPy array. (to_numpy()and the typed accessors are there too; see theArraypage in the API reference.) - Parameters.
config_schemais JSON Schema; read values withconfig.get("threshold", 70). Every parameter the user sees carries atitleand adescription— those strings are the parameter panel. - Provenance travels. The output keeps
framework=item.framework, so the result is still named after the slide it came from in previews and saves. - The
caxis. The block returns the micrograph and its label map as two channels of oneImage(c=0/c=1) so a preview can draw the labels over the cells — anArraysubclass may name acaxis for exactly this.
This block is also honest about being imperfect: both the threshold and the
adaptive method run for real, and neither is right everywhere. That is what
segmentation is like — the example is the science, not a toy.
Depends on the Image type
The block imports from image import Image. Copy
types/image/ into your project's types/ first — the
types/ folder is on the import path, so the block resolves the project type
by its module name. Together with
io-load-tiff/ and
workflows/load-and-segment.yaml these
examples form one small pipeline: load .tif → segment.
When you need the whole batch instead
ProcessBlock hides the batch from you. If your block must filter, merge,
split, or otherwise change the item count, subclass Block and write
run(), which receives and returns whole Collections — see the
interactive Data Router for a block that does.
Try it
Wire an Image source into image, run, and the labels port carries one
two-channel Image per input.