instance segmentation pipeline - graph post processing#69
instance segmentation pipeline - graph post processing#69stmartineau99 wants to merge 5 commits into
Conversation
constantinpape
left a comment
There was a problem hiding this comment.
I think this all looks good. There are only a few cosmetic things to address.
Some of the things could be rewritten more readable and efficient by using better graph primitives. But I don't know if we have all of the ones needed, especially a contraction graph, so this is work for a follow-up.
| return indptr, dst, eid, degrees | ||
|
|
||
|
|
||
| def remove_ticks(vertices, edges, tick_length, radii=None): |
There was a problem hiding this comment.
I skimmed the implementation. The algorithm makes sense high-level:
- Build a supergraph of distances between junctions (degree >= 3) and endpoints (degree == 1)
- Drop the edges between junctions and endpoints that are shorter than tick-length
There are two possible things to address:
Update the distances during graph contraction (second step) --- this seems to be missing(Never mind, this actually happens)- Use more graph primitives (adjacency and a contraction graph) --- I have to check what we have in our graph impl already and we can do this in a follow-up PR
| for x in (far1, far2, node): | ||
| incident[x].discard(s1) | ||
| incident[x].discard(s2) | ||
| supers[sid] = [far1, far2, l1 + l2, p1 + p2] |
There was a problem hiding this comment.
The length update happens here.
| sid += 1 | ||
|
|
||
| dropped = set() | ||
| while True: |
There was a problem hiding this comment.
This would be more readable if we used a graph structure again.
| return volume | ||
|
|
||
|
|
||
| __all__ = ["clean_graph", "draw_instances", "join_close_components", "remove_ticks"] |
There was a problem hiding this comment.
Typically goes to the top of the file.
| return [int(edge_ids[odd])] | ||
|
|
||
|
|
||
| def split_degree4(v, graph, vertices, direction_span=1, min_through_angle=160.0): |
There was a problem hiding this comment.
Should either be a proper public function and have a doc-string and type annotations or be private (= _split_degree4). I would make it private.
| return vertices[used], remap[edges], radii | ||
|
|
||
|
|
||
| def split_degree3(v, graph, vertices, direction_span=1, min_branch_angle=30.0): |
There was a problem hiding this comment.
Either public function with doc-string and type annotations or ptivate (_split_degree3)
| return [int(edge_ids[k]) for k in pair_b] | ||
|
|
||
|
|
||
| def clean_graph( |
There was a problem hiding this comment.
This should have a more distinct name --- we can have skeleton graphs for all kinds of things not necessarily only filament graphs. In other cases having junctions may be fine. I would go with clean_filament_graph.
graph postprocessing (postprocessing.py)
draw_instancesfunction - rasterize the instances or skeleton graph for easy viewing in napariclean_graphhas 4 stepsremove_ticksreimplemented function from kimimaro, prune ticks (spurs) below a certaintick_lengthmin_branch_angle.min_through_angle.join_distand if they are sufficiently colinear, as determined bymin_join_angletests/skeleton/test_postprocessing.py
clean_graphexamples/skeleton/instance_segmentation.py
clean_graphconnected_components- input todraw_instancesdirection_spanto get better tangent measurements, I found this helps best at around 8-10 to minimize aliasing artifacts