Hi Julia community!
I’m excited to share ImageTally.jl, a package I’ve been working on for interactive counting and tagging of objects in scientific images.
The backstory
During my Masters and PhD I worked on butterfly genetics and spent a lot of time doing image analysis and geometric morphometrics — placing landmarks on wing images in MorphoJ and running the analyses in R. It was painstaking work, and the tools available were functional but dated. MorphoJ is a Java application from the early 2000s that hasn’t changed much since. The workflow always felt like it deserved something better.
During my postdoc I started using Julia more extensively, and I had a project that brought the image counting problem into sharp focus. I was working with leafroller egg masses — these are remarkable structures where a moth can lay anywhere from a few dozen to a couple hundred eggs, all overlapping each other in a tight tiling pattern on a leaf surface. I developed staining techniques to improve the contrast in photographs and make individual eggs more visible. My workflow at the time was loading images in GIMP, adding colored points manually on each egg, then loading the point layer in Julia to count by color. It worked, but it was awkward and inflexible.
In February 2019 I came across this Discourse thread where Andrew McKay was building exactly the kind of tool I needed — a Makie-based image annotation solution. I responded the same day. We exchanged ideas, and I shared one of my egg mass images — deliberately choosing one of the simpler ones, quietly hoping someone would tell me automated segmentation was straightforward. Andrew’s response was diplomatic: “it does look like you have quite the challenge there.” A few days later he published ImageTrainer.jl, explicitly notifying me when it went public. It was a promising proof of concept — but it was never completed, and the Makie API has changed substantially in the six years since. I forked it, but never took it further at the time. I ended up using a Python tool to finish that project.
That conversation was in 2019. When I recently checked the Julia ecosystem again, the gap was still there — six years later. So I built ImageTally — starting fresh with modern Makie, a clean architecture, proper tests and documentation, and the lessons learned from that original effort.
What ImageTally does
ImageTally provides an interactive GLMakie-based GUI for manually counting and tagging objects in images, plus a full programmatic API for batch processing and data export.
Core features:
- Interactive counting — left-click to place markers, right-click to delete, left-drag to move. Scroll to zoom, R to reset view
- Multiple tags — define up to 10 named categories (e.g. “male”, “female”, “egg”, “parasitized”), each with its own color and marker shape
- Session persistence — save and reload sessions as TOML files so work can be interrupted and resumed
- CSV export — every counted point is exported with relative coordinates, pixel coordinates, and timestamp
- Programmatic API — create and manipulate sessions entirely in code, no window needed
julia> using CSV, DataFrames
julia> df = CSV.read("/your/directory/saved_CSV_File.csv", DataFrame)
25×7 DataFrame
Row │ id tag x_relative y_relative x_pixel y_pixel timestamp
│ Int64 String15 Float64 Float64 Int64 Int64 DateTime
─────┼─────────────────────────────────────────────────────────────────────────────────────
1 │ 1 uneclosed 0.536547 0.7544 1629 3054 2026-04-13T14:14:02.024
2 │ 2 uneclosed 0.590601 0.56311 1793 2279 2026-04-13T14:14:06.924
3 │ 3 eclosed 0.395175 0.785505 1200 3180 2026-04-13T14:14:11.690
4 │ 4 eclosed 0.330726 0.668864 1004 2708 2026-04-13T14:14:12.491
5 │ 5 eclosed 0.436755 0.682861 1326 2764 2026-04-13T14:14:13.457
6 │ 6 eclosed 0.5511 0.642425 1673 2601 2026-04-13T14:14:14.591
7 │ 7 eclosed 0.494967 0.56311 1503 2279 2026-04-13T14:14:15.657
8 │ 8 eclosed 0.399333 0.60199 1212 2437 2026-04-13T14:14:16.290
⋮ │ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮
19 │ 19 eclosed 0.372306 0.396702 1130 1606 2026-04-13T14:14:26.223
20 │ 20 eclosed 0.463782 0.368708 1408 1493 2026-04-13T14:14:27.157
21 │ 21 uneclosed 0.284988 0.308055 865 1247 2026-04-13T14:14:32.458
22 │ 23 uneclosed 0.349437 0.238071 1061 964 2026-04-13T14:14:43.691
23 │ 24 eclosed 0.424281 0.266064 1288 1077 2026-04-13T14:14:46.890
24 │ 25 eclosed 0.395175 0.34227 1200 1386 2026-04-13T14:14:47.791
25 │ 26 eclosed 0.513678 0.328273 1560 1329 2026-04-13T14:14:48.590
10 rows omitted
Quick start
julia
# Install (not yet in the General Registry — registration in process, three day mandatory waiting period!)
] add https://github.com/alejandromerchan/ImageTally.jl
# Also install GLMakie and FileIO for the GUI
] add GLMakie, FileIO
# Launch the counter
using GLMakie, FileIO
using ImageTally
fig, sess = launch_counter("path/to/image.jpg")
# Or resume a previous session
fig, sess = launch_counter("path/to/image.jpg"; session="image_session.toml")
Without GLMakie, the package works as a pure data processing tool:
julia
using ImageTally
# Load a saved session and analyze without opening a window
sess = load_session("my_count.toml")
count_by_tag(sess) # Dict("egg" => 47, "parasitized" => 3)
total_count(sess) # 50
export_csv(sess, "results.csv")
println(session_summary(sess))
Supported image formats
Tested formats include JPEG, PNG, TIFF (8-bit and 16-bit, color and grayscale), and BMP. Large images are supported — tested up to 18 megapixels with good interactive performance on a desktop GPU.
Platform note: The GLMakie GUI extension is officially tested on Linux. It may work on macOS and Windows but those platforms are not currently covered by CI.
Design philosophy
The package follows a strict separation between the logic layer and the GUI:
- Core logic (
src/) — pure Julia, depends only onDatesandTOMLfrom stdlib. Fully testable without a display, works headlessly on servers and clusters - GUI (
ext/GLMakieExt.jl) — activated automatically whenGLMakieandFileIOare loaded, implemented as a package extension
This means a researcher can use ImageTally to count images interactively on their laptop, save sessions as TOML files, and then batch-process all sessions on a computing cluster without GLMakie ever being installed there.
A gap in the Julia ecosystem
Before starting this project I searched for existing Julia tools for interactive image counting or landmark digitization. I didn’t find anything that fit this use case — the closest were general image viewers without structured counting output, or plotting tools not designed for interactive annotation. If there are existing packages I missed, I sincerely apologize — please let me know in the comments and I’ll add them to the documentation.
For context, here is what exists in other languages and environments:
Python:
- ClickPoints — a well-designed scientific image annotation tool published in Methods in Ecology and Evolution (2017). Supports point counting with categories, masks, tracking, and a Python API. Actively maintained and genuinely excellent for Python users.
- labelme — general purpose annotation tool, more focused on machine learning applications than scientific counting workflows.
R:
- geomorph — the standard package for geometric morphometrics and landmark-based shape analysis. Powerful for analysis but not designed for interactive image digitization.
Standalone:
- MorphoJ — Java-based application for geometric morphometrics, widely used in evolutionary biology. Functional but largely unchanged since the early 2000s.
- tpsDig2 — another Java application widely used for landmark digitization in morphometrics. Also aging.
The pattern is clear: the Python ecosystem has good general annotation tools, R has powerful analysis tools, and Java has the legacy morphometrics applications. ImageTally is an attempt to start filling that gap in Julia — beginning with the interactive counting and annotation layer that everything else builds on.
A note on development process
I want to be transparent: Claude Code was used extensively in developing ImageTally. I have a background in biology and consider myself an intermediate programmer, and this is probably one of the largest software projects I’ve ever done, so the use of AI agents has been very useful. However, I was involved at every step — testing the code interactively in the Julia REPL, guiding the architecture decisions, identifying and debugging errors, and providing the biological domain knowledge that shaped the tool’s design. The ideas, the use cases, the testing with real images, and the overall direction came from me. Claude Code was a very capable pair programmer, not an autonomous agent.
I think this kind of transparent disclosure is important as AI-assisted development becomes more common in the open source community.
Intended use cases
- Entomology — counting insects on sticky traps, eggs on plant material, specimens in collection images
- Microscopy — counting cells, nuclei, or other objects in histological sections
- Ecology — counting organisms in field photographs, aerial surveys, camera trap images
- Geometric morphometrics — placing landmarks on biological structures for shape analysis (fluctuating asymmetry, Procrustes analysis)
- Any domain where manual object counting in images is needed and automation is unreliable or unavailable
What’s coming
ImageTally v0.1.0 is intentionally focused. Ideas on the roadmap for future versions:
- Scale calibration — draw a line over a known scale bar, enter the real-world distance, and all subsequent measurements are automatically converted to physical units
- Distance measurements — measure distances between points in real-world units, useful for taxonomy and morphometrics
- Landmark mode — named/numbered landmarks with side designation (left/right) for geometric morphometrics workflows, with export compatible with R’s
geomorph - Human-in-the-loop annotation — display predictions from automated detection models (SAM, YOLO) as a starting point for human verification
Longer term, I’m thinking about a small ecosystem of composable image analysis packages built on shared infrastructure — something the Julia ecosystem is particularly well suited for. But that depends entirely on whether this tool finds users and real use cases.
Links
- Repository: GitHub - alejandromerchan/ImageTally.jl · GitHub
- Documentation: https://alejandromerchan.github.io/ImageTally.jl/stable
- Issues and feedback: Issues · alejandromerchan/ImageTally.jl · GitHub
Feedback, suggestions, bug reports, and pull requests are all very welcome. I’m especially curious to hear from anyone working in biological image analysis — whether ImageTally fits your workflow, what’s missing, and what would make it more useful.
