Skip to content
SanjayPradeep97Public

About

Segment, count and measure particles in SEM and TEM micrographs with Segment Anything Model

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Konimeter

tests

Segment, count and measure particles in SEM and TEM micrographs with Meta's Segment Anything Model (SAM), in an app that runs in your browser: SAM proposes the particles, and you check and correct them. It has been used for carbon nanotubes, microplastics and wildfire particulate matter, and works for anything else that can be imaged as particles.

For every image you get a particle count and, per particle, the area and the equivalent circular diameter, in pixels and in nanometres.

The name: a konimeter (Greek konis, dust) was the instrument that measured dust exposure in mines by catching particles on a glass slide, to be counted under a microscope. This is the same job, done by a model instead of an eye. The project was called SAM-SEM-Segmentation until October 2026; old links redirect here.

Reviewing the paper? The code, results and reproduction scripts for Quantification and Classification of Carbon Nanotubes in Electron Micrographs using Vision Foundation Models are on the publication branch: git clone -b publication https://github.com/SanjayPradeep97/Konimeter.git


Install

You need Miniconda or Anaconda and Git — the SAM package installs straight from its GitHub repository. Python 3.10 to 3.12 work; the commands below use 3.11. Run them in a terminal (on Windows, the Anaconda Prompt).

git clone https://github.com/SanjayPradeep97/Konimeter.git
cd Konimeter

conda create -n konimeter python=3.11
conda activate konimeter

Install PyTorch before the package. EasyOCR depends on it, and if it is not already there pip fetches the default build — which on Windows is CPU-only, and SAM then runs ten times slower without any error to say why.

# NVIDIA GPU (RTX 20, 30, 40 and 50 series, with a current driver):
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128

# Apple Silicon, or no GPU:
pip install torch torchvision

Then the package and everything else:

pip install -e .

The SAM model

The first time you start the app, its Setup tab offers Download the SAM model (ViT-B, 358 MB). It is saved in the sam_weights/ folder inside your Konimeter folder, which is where the app looks every time it starts, so you download it once. ViT-B is fast enough to use interactively on a laptop.

ViT-H (2.4 GB) segments slightly better. To add it to the app's list, run python download_sam_weights.py --model vit_h in the Konimeter folder. To keep weights somewhere else, set SAM_WEIGHTS_DIR to that folder.

The app uses an NVIDIA GPU (CUDA) or Apple Silicon (MPS) when it finds one, and the CPU otherwise. The Setup tab says which, once the model is loaded.

The first time a scale bar is read, EasyOCR downloads its text models (about 100 MB) to ~/.EasyOCR; after that, everything runs offline.


Run the app

Windows double-click run_app.bat
Any platform konimeter, in the activated environment

Then open http://127.0.0.1:7860. --port and --host change where it listens. --share also serves the app through a public Gradio link, for looking at it from another device. The image folder is always chosen on the computer running Konimeter, in its own folder window, so choose it there.

run_app.bat finds conda in the usual Anaconda, Miniconda and Miniforge install folders, or the one an Anaconda Prompt was started from, and activates the konimeter environment (or SEM_analysis, its name before the rename); set SEM_ENV first to use another environment. On Windows outside the launcher, set KMP_DUPLICATE_LIB_OK=TRUE before starting — PyTorch and NumPy each ship an OpenMP runtime and otherwise refuse to share a process.

The tabs, in the order you use them

Tab What happens there
⚙️ Setup Load the SAM model (the first time, download it with the button there), say whether the images are from an SEM or a TEM, then press Choose folder… and pick the folder of images. Results go to analysis_results.csv in that folder, and choosing the folder again carries on with it
🖼️ Gallery Pick an image. Ticked images already have saved results
📏 Scale & Frame The image beside three panels: Scale (the value, where it came from, and whether it needs a look), Measure the scale bar (by a box or by its two ends) and Frame (microscope, particles brighter or darker, databar, area left out). See below
🔬 Segment & Refine The image opens with SAM's best outline already in use; its other two candidates are thumbnails beside it, a click away. Correct the outline with Remove, Add, Merge, or Redraw a particle with include/exclude clicks, then Apply; every click and every applied change can be undone. Particles are (darker / brighter than the background) sets which candidate comes first. The particle count and sizes update as you go, and Save & next is at the top
💾 Results The measurements per image, and the whole folder's results: delete rows, remove duplicates, export
📊 Plots Size and shape of every particle saved in the folder: equivalent diameter (with the geometric mean and geometric standard deviation on a log axis) and aspect ratio, with the 3:1 ratio that defines a fibre marked

The app keeps one process-wide session, so it is built for one analyst at a time; two browser tabs pointed at the same server share it.

Scale

Every measurement is a pixel count multiplied by one number, so scale gets its own tab. Three methods, tried in order of trustworthiness:

Method When
1 Pixel size read from the file's own metadata Automatic on load. Exact — nothing to check. Read from FEI/Thermo, Zeiss, Hitachi and TESCAN TIFFs, AMT TEM cameras, and the .txt a JEOL SEM saves beside each image. A TIFF's resolution tag is ignored: programs fill it with a print setting
2 Read the printed scale bar Runs automatically when there is no metadata. To read it yourself, choose Draw a box, drag a box around the bar and its label, and press Read scale bar
3 Click both ends of the bar and type its length: the outer edge of a solid bar, the middle of each end tick of a |—| bar When the bar cannot be read. A 7x magnifier follows the cursor so you land exactly

A reading from the printed bar is marked Unconfirmed until you press Confirm, and the measured span is drawn on the bar so you can see what was read. The value read off the label is shown beside the button: if OCR misread it, type the right one before confirming, and the measured bar is kept. The same misreading of a bar the same length is corrected the same way from then on, and every scale you confirm lets later images at that magnification through without asking. Metadata and hand measurement are trusted outright, since neither involves a machine reading a glyph. Detect again throws away a scale set by hand and goes back to what the file says. How each scale was obtained is recorded beside every row in the scale_method column.

SEM or TEM

On the Setup tab, say which Microscope the folder came from. It tells the app which way round the particles are: brighter than the background in SEM, darker in TEM bright field. That matters most for a large particle, where the particle and the background around it are equally plausible outlines and only knowing which way round the image is settles it.

It is filled in for you when the files say: FEI, Zeiss, Hitachi and TESCAN TIFFs, JEOL TEM files (by the tags JEOL's software writes), the .txt a JEOL SEM saves beside each image, and AMT TEM cameras. If you pick one and the files say the other, the app tells you. Particles are on the Segment & Refine tab overrides it for an unusual image, a dark-field TEM frame say; either way the other side's outlines are still offered, just after.

An information strip (databar) below the image, as most SEMs write, is found and cut off, including Zeiss's, which sits a few rows above the bottom edge. A scale bar burned into the image itself, as on most TEMs, is left out of measurement instead: just the bar and the line of text it sits on.

Micrographs often contain large areas that are not specimen — the black corners left by a circular aperture, a grid bar blocking the beam, a burned-in scale bar. Each of them out-contrasts the particles, so they are excluded before anything is measured. The share excluded is shown on the Scale & Frame tab.

Prefer original TIFFs straight from the microscope: once an image has been converted to PNG or JPEG, or cropped in another tool, its pixel-size metadata is gone and scale has to come from the printed bar or from a hand measurement.


Output

analysis_results.csv has one row per image:

Column Contents
file_name the image
num_particles particle count
nm_per_px the scale used
scale_method how that scale was obtained: metadata, box_ocr, two_points or none; +unconfirmed if nobody confirmed it
particle_areas_px, particle_areas_nm2 each particle's area
equiv_diameters_px, equiv_diameters_nm each particle's equivalent circular diameter
aspect_ratios each particle's length over width (the axes of its fitted ellipse, as ImageJ's AR); 1 for a disc

Supported images: .tif, .tiff, .png, .jpg, .jpeg, in any letter case, directly inside the folder (subfolders are not searched).

Training data

Every frame you save has been segmented by SAM and then checked, and corrected where needed, by you, so its mask is a label. The app keeps each one in konimeter_dataset/, beside the results file, so analysing a folder also builds a labelled dataset for training a classifier or fine-tuning the segmentation model:

Path Contents
images/<name>.png the frame exactly as segmented, with any databar trimmed off
masks/<name>_mask.png 8-bit, 255 = particle: the format the paper's classification pipeline reads
labels/<name>_labels.png 16-bit, one value per particle; value i is the i-th particle in the frame's row of analysis_results.csv
valid/<name>_valid.png 255 where the frame is specimen; 0 where it was left out of analysis (aperture vignette, grid bar, burned-in scale bar), so those pixels count as neither particle nor background
index.csv one row per frame: the source file's name and SHA-256, size, scale and how it was set, instrument kind, particle polarity, SAM model, and when it was saved

Saving a frame again replaces its entry; deleting its row on the Results tab deletes it. The index records file names, never paths, so the folder can be shared without revealing where it lived. Nothing leaves your computer; to turn it off, untick Also keep each saved image and its mask as training data on the Setup tab.


Troubleshooting

Symptom Cause and fix
The Setup tab says the model is on cpu, but there is an NVIDIA GPU PyTorch is the CPU-only build. In the environment, run pip install --force-reinstall torch torchvision --index-url https://download.pytorch.org/whl/cu128
OMP: Error #15 ... already initialized on Windows Start the app with run_app.bat, or set KMP_DUPLICATE_LIB_OK=TRUE first
The app will not start because the port is in use Another copy is running; close it, or start with --port 7861
"No images in …" The images must be directly inside the folder, with one of the extensions above
"Results cannot be saved in …" The folder is read-only (a network share, say). Copy the images to a folder you can write to, and choose that one
konimeter: command not found, or ModuleNotFoundError for sem_particle_analysis or sem_analysis_app The environment is not active, or pip install -e . was not run in it

Anything else: please open an issue with the message and what you were doing.


Tests

pip install pytest
pytest                      # everything, including a run of SAM itself
pytest -m "not slow"        # skip the tests that need SAM weights or EasyOCR models

Measurements are checked against shapes of exactly known size — tests/synthetic.py builds micrographs whose scale bar length, printed label and particle mask are all ground truth — so a regression shows up as a wrong number rather than merely a changed one.


Layout

sem_analysis_app/        the web app (konimeter, or python -m sem_analysis_app)
sem_particle_analysis/   the segmentation and measurement library the app is built on
tests/                   the test suite
download_sam_weights.py  fetches SAM checkpoints into sam_weights/
run_app.bat              Windows launcher (scripts/activate_env.bat finds conda)
data/                    a place for your own images; nothing in it is tracked

Citation

If you use this tool, please cite the paper it was built for (under review; CITATION.cff has the details, and GitHub's "Cite this repository" button formats it):

S. Pradeep, C. Wang, M. M. Dahm, J. D. Eldredge and C. S. J. Tsai. Quantification and Classification of Carbon Nanotubes in Electron Micrographs using Vision Foundation Models. Scientific Reports (under review), 2026.

It builds on Meta's Segment Anything Model:

@article{kirillov2023segment,
  title={Segment Anything},
  author={Kirillov, Alexander and Mintun, Eric and Ravi, Nikhila and Mao, Hanzi and Rolland, Chloe and Gustafson, Laura and Xiao, Tete and Whitehead, Spencer and Berg, Alexander C. and Lo, Wan-Yen and Doll{\'a}r, Piotr and Girshick, Ross},
  journal={arXiv:2304.02643},
  year={2023}
}

License

MIT — see LICENSE.

Built with Segment Anything, Gradio, EasyOCR and scikit-image.

About

Segment, count and measure particles in SEM and TEM micrographs with Segment Anything Model

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages