Skip to content

AtlasPatch + other additions - #43

Open
polejowska wants to merge 8 commits into
mainfrom
methods-tune
Open

AtlasPatch + other additions#43
polejowska wants to merge 8 commits into
mainfrom
methods-tune

Conversation

@polejowska

@polejowska polejowska commented Apr 9, 2026

Copy link
Copy Markdown
Collaborator

#24: after experimentation with "2stage_pipeline.py", currently SAM working in a segment anything mode demonstrates the most promising results compared to the text-based prompting.

Classical methods (also those newly added) refinement (parameters tuning and review) will be be covered by #38

@polejowska polejowska linked an issue Apr 9, 2026 that may be closed by this pull request
@polejowska polejowska linked an issue Apr 9, 2026 that may be closed by this pull request
@polejowska
polejowska marked this pull request as ready for review April 9, 2026 09:47
@polejowska
polejowska requested a review from Copilot April 9, 2026 09:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands segmenteer’s segmentation method catalog (notably adding SAM3 and AtlasPatch+SAM2 options) and improves benchmarking/reporting ergonomics to better support experimentation with “segment anything” style workflows.

Changes:

  • Add new DL segmenters (SAM3, AtlasPatch+SAM2) and expose them through the public API.
  • Add new classical segmenters (connected components, edge-based) and adjust Otsu thresholding behavior.
  • Enhance benchmarking/report output (optional thumbnail saving, prompt persistence, and report thumbnail fallback generation) and make TRIDENT imports lazier.

Reviewed changes

Copilot reviewed 26 out of 28 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
segmenteer/methods/ensemble/init.py Formatting/structure tweaks in ensemble utilities.
segmenteer/methods/dl/trident.py Import formatting; integrates PathProfiler TRIDENT wrapper change.
segmenteer/methods/dl/sam3.py New SAM3Segmenter implementation (Ultralytics SAM3).
segmenteer/methods/dl/rtlucassen.py Minor formatting change.
segmenteer/methods/dl/pathprofiler.py Refactor to lazy TRIDENT loading via dynamic class creation.
segmenteer/methods/dl/grandqc.py Uses parenthesized context manager for tqdm/file handling.
segmenteer/methods/dl/fastsam.py Return type adjusted to boolean mask (NumpySegmenter contract).
segmenteer/methods/dl/atlaspatch_sam2.py New AtlasPatchSAM2Segmenter integrating atlas-patch + SAM2.
segmenteer/methods/dl/init.py Export new DL segmenters with optional-import pattern.
segmenteer/methods/classical/threshold.py Fix Otsu direction; add new classical segmenters.
segmenteer/methods/classical/background_subtractor.py Minor formatting change.
segmenteer/methods/classical/init.py Export new classical segmenters.
segmenteer/methods/init.py Re-export new classical methods and reorder imports.
segmenteer/core/base.py Add lazy TRIDENT import helper and adjust TRIDENTSegmenter.
segmenteer/benchmark/workflows.py Add save_thumbnails option for single/dataset benchmark runs.
segmenteer/benchmark/runner.py Extend BenchmarkResult with prompt; attempt to capture it.
segmenteer/benchmark/ensemble.py Persist prompts per image; formatting refactors.
segmenteer/init.py Expose new segmenters at top-level via getattr and all.
run.py Add AtlasPatchSAM2Segmenter to example list; disable thumbnails in dataset run.
README.md Document FastSAM text-prompt dependency caveats for uv/pip installs.
pyproject.toml Add sam3 and atlaspatch-sam2 extras; adjust dl/fastsam extras.
postensemble.py Minor formatting.
docs/fastsam.md New FastSAM documentation page.
docs/classical_methods.md New documentation for classical segmentation methods.
create_report.py Minor formatting for readability.
app/report.py Add on-the-fly thumbnail generation fallback in report output.
app/loader.py Minor formatting.
.gitignore Ignore runs/ directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread segmenteer/methods/classical/threshold.py Outdated
Comment thread segmenteer/methods/classical/threshold.py Outdated
Comment thread docs/classical_methods.md Outdated
Comment thread app/report.py Outdated
Comment thread segmenteer/methods/dl/pathprofiler.py
Comment thread segmenteer/benchmark/runner.py
Comment thread run.py
Comment thread docs/fastsam.md
polejowska and others added 4 commits April 9, 2026 11:57
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@polejowska
polejowska requested a review from siemdejong April 9, 2026 10:05

@siemdejong siemdejong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, agata!

Comment thread docs/classical_methods.md

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like docs like this

# Filter components by minimum area
mask = np.zeros_like(binary)
for component_id in np.unique(labeled):
if component_id == 0: # Skip background

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking: are we sure that component 0 is always background?

# Build mask from components, filtering by minimum area
mask = np.zeros_like(inverted_edges)
for component_id in np.unique(labeled):
if component_id == 0: # Skip background (edges)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here


if not results or len(results) == 0:
return mask_to_geojson(np.zeros(image.shape[:2], dtype=bool), self.min_area)
return np.zeros(image.shape[:2], dtype=bool)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup well spotted bug

TRIDENTSegmentationModel, _ = _require_trident()

# Dynamically create the actual class with TRIDENT base
class _PathProfilerImpl(TRIDENTSegmentationModel):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part reads really really hard. Not many people understand what __new__ does and this __new__ method in particular defines its own class.

What is the rationale behind this change? It looks like a Copilot suggestion and correlates with the Copilot comment below. Maybe we should indeed use string annotations here or put the _TORCH_AVAILABLE guard before the LIBTRIDENTPathProfilerSegmenter definition.

I'm also fine with keeping the code as-is, but with some comments why this is structured like this.

Comment thread segmenteer/methods/dl/sam3.py
Comment thread postensemble.py
seg.run_ensemble(
manifest_path=None, # or: Path("outputs/.../ensemble_manifest.json")
threshold=0.5, # 0.0 = union | 0.5 = majority | 1.0 = intersection
threshold=0.5, # 0.0 = union | 0.5 = majority | 1.0 = intersection

@siemdejong siemdejong Apr 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this comment a bit confusing, especially because the threshold actually means what is in the brackets below which is clearer in my opinion. I know this is not really a change in this PR, but it only now caught my eye.

* threshold = 0.0union   (any method wins)
* threshold = 0.5majority (>50 % weighted agreement)
* threshold = 1.0intersection (all methods must agree)

Comment thread pyproject.toml
# all deep learning methods dependecies combined
# (bigpicture excluded: tissue-segmentation requires tensorflow-cpu, no macOS ARM wheel)
dl = [
"atlas-patch",

@siemdejong siemdejong Apr 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we pin all atlas-patch to >=1.1.0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AtlasPatch segmenter Visual evaluation of prompt engineering for FastSAM

3 participants