Table of Contents
- Flatbed Scanners For Entomology Uses and Limitations
- What EntoScan Is
- Hardware Setup and Focus Considerations
- Installing and Running with Docker
- Interface
- Running Scans
- Result Files and Database
- Printing Labels
EntoScan is a free and open-source scientific tool developed in the DARSA group, at Aarhus University. Please cite our publication if you use EntoScan.
Digital imaging is increasingly used in entomology to study insects, but capturing large numbers of specimens at scale remains challenging. Traditional imaging approaches rely on specialised and expensive camera systems—often using motorised stages to tile images — which makes it difficult to standardise lighting, scale, and image quality across experiments.
For small specimens and other biomedical applications, flatbed scanners have proven to be a powerful and affordable alternative. However, a gap remains between proof-of-principle demonstrations and widespread adoption. Scanners suffer from a shallow depth of field, which can limit their effectiveness, but this issue can be mitigated through simple hardware modifications.
Another limitation lies in the proprietary software provided by scanner manufacturers, which is poorly suited for high-throughput biomedical imaging. It is difficult to associate scanned images with external metadata, and users often need to devise their own visual labelling systems, such as two-dimensional barcodes. Moreover, images are not stored in a structured format that facilitates downstream analysis, and biomedical imaging frequently requires custom configurations—for instance, capturing multiple regions of interest within the same sample.
EntoScan addresses some of the above limitations with a hardware and software stack for high-throughput imaging of individual or bulk of insects. A modified flatbed scanner captures each specimen in a configurable layout. The custom control software runs as a portable webapp. 2D barcodes are used to label scans and link images to relevant metadata. The platform stores full-resolution images, thumbnails, and metadata in a structured database, which ensures consistent naming and metadata handling, and can easily be queried to filter and display relevant images.
This repository is organised around three services:
services/scanner-api: a FastAPI service that talks to the scanner, keeps the configuration, generates previews, performs barcode-aware scans, and writes structured metadata.services/webapp: a Shiny dashboard that surfaces recent scans, previews, and metadata stored in the database.services/db: a PostgreSQL instance seeded with the schema EntoScan uses to persist scan records.
At the moment EntoScan is tested on Epson Perfection V850 Pro. For optimal images, it is preferable to place insects as close as possible to the focal plane of the scanner: the top of the glass bed. There are several ways to do that:
- Place samples directly on top of the bed (optionally seal the edge of the bed with grout)
- Replace the thick glass with an aluminium plate with a cut-out "frame" that can hold a container (e.g., petri dish or well plate) and offset it so that the floor of the container, where the specimens are, is on the focal plane.
In some cases (e.g., sticky cards), placing the insects on the glass directly will be efficient and reliable. However, specimens kept in liquid it is much more advisable to use containers such as petri dishes or well plates and move containers rather than individual insects, Since this approach is less trivial, we describe how to modify the scanner:
- Power off the scanner, unplug USB, and work in a dust-free space.
- Remove the four screws that hold the factory glass platen, lift the glass with a thin spatula, and clean residual adhesive.
- Replace the glass with a 250 mm × 378 mm × 3.3 mm aluminium plate that has a 135 mm × 95 mm cut-out matching the well-plate footprint. Secure it with thin double-sided tape.
- Preserve the calibration reference: tape a white strip to the top edge of the aluminium so the scanner retains its exposure baseline.
- The cut-out lowers the specimen plane so insects rest closer to the optics' focal point; keep the plate flat to avoid defocus and artefacts.
- Always power down before mechanical work, keep the glass surfaces spotless, and avoid bending the aluminium insert to maintain focus.
- Ensure the well-plate holder, barcode stamp, and lid are clean and dry; dust quickly degrades scan quality.
- If you replace the scanner model, measure the new platen carefully and replicate the cut-out dimensions so the ROI coordinates stay meaningful.
- Install Docker and the Compose plugin, and make sure the host user can access the scanner's USB bus (the compose file shares
/dev/bus/usbwith the container). - On your machine, create a directory for EntoScan.
- In this directory download
docker-compose.yaml(from our repository). - Create file named
.envwith these three variables:# A to a writable directory on the host machine (your computer). # This is where all the data and the database will live. SCANNER_HOST_OUTPUT_DIR=/ABC/DEF # Whether you want to use a mock scanner # Usefull if you want to test or develop the API without a physical device USE_MOCK_SCANNER=1 # No need to change, this is the link to our bespoke label making tool LABEL_MAKER_URL=https://darsa.info/EntoScan-labels/ - From your EntoScan directory, execute:
docker compose pull - Plug the scanner in your computer and turn it on
- Run
docker compose upto launch the services. Check the output (it should show the services starting in order, with the web app last) - The web interface should now be available at on
http://localhost:8080. - Use
docker compose downwhen you need to stop the services. If you move the data directory, updateSCANNER_HOST_OUTPUT_DIRso the container continues to write and read historical scans.
Once the Docker services have started, the interface is served at http://localhost:8080. On your browser, it should look like this:
The first tab in the dashboard is for configuration and preview. The left hand side is the content of the current configuration file that describes how each scan is handled. This is the most important aspect of the interface.
The default template (YAML file) looks like:
global:
enforce_barcode: false
roi_defaults:
file_format: "jpg"
dpi: 600
brightness: 0
preview:
xyxy_mm: [0.0, 0.0, 210.0, 200.0]
file_format: "jpg"
dpi: 150
barcode:
xyxy_mm: [0.0, 0.0, 100.0, 100.0]
file_format: "jpg"
dpi: 300
rois:
- name: "ROI-1"
xyxy_mm: [0.0, 0.0, 90.0, 90.0]
file_format: "tiff"
- name: "ROI-2"
xyxy_mm: [100.0, 100.0, 190.0, 190.0]
dpi: 600Key fields:
global: Global variables defining the overall behaviourenforce_barcode: iftrue, the scanner fails if no barcode is detectedroi_defaults: set the default vaalues for all ROI fields such asdpi,file_format, andbrigthness, (see below). All ROIs inherit these (i.e., they uuuse the default values unless specified)
preview: Special Region Of Interest (ROI) used to generate a preview;xyxy_mmis[x0, y0, x1, y1]in millimetres measured from the scanner origin (top-left). Choose a low DPI for fast feedback.barcode: Special ROI where a 2d barecode (data matrix) is expected; The decoded content (wither a just a string of characters or a JSON dictionary) is attached to every image underscan_metadata.rois: list (one or more) of regions to acquire subimages on. Each ROI must have:name: a unique and arbitrary namexyxy_mm: the coordinates of the ROIfile_format:"jpg"or"tiff"dpi: the resolution in dot per inchbrightness: a value from
After setting the configuration, you can press the preview button. The scaner then uploads the config and starts scanning. When done, the interface displays, on the right hand side, the preview image and where regions described above would be.
Note that you can display the coordinates in mm by hovering your mouse on the image, which is useful to write or correct the xyxy_mm position fields.
In addition, that the current configuration is saved. You may want to copy it to your own file in case you or another user wants a new one.
After satisfied with the configuration for your project, you most likely want to start scanning. In the scanning page just press "scan", according to the number of ROIs and the resolution, it might take a moment. When done, all the resulting images are displayed on this page. In addition, if a barcode was found and used:
the embedded metadata is also displayed, so you chan check it is correct. If so, you can continue scanning. Note that, each image is named with a timestamp, and the ROI name. In addition, each image is associated with a metadata file (JSON) that contains additional information such as the computer and scanner used, the driver, a checksum for the image, etc
In the "Files" tab, you can display the resulting images and their metadata in a filterable table:
All of these images are stored in the location defined in SCANNER_OUTPUT_DIR (in your .env file, see Installation).
The file structure is as follow:
├── acabb787f1a24180912d8483cacbfdc9
│ └── Epson Perfection V850
│ └── 2025-11-06
│ └── 2025-11-06_08-39-36
│ ├── ROI-1
│ │ ├── 2025-11-06_08-39-36.ROI-1.jpg
│ │ ├── 2025-11-06_08-39-36.ROI-1.json
│ │ └── 2025-11-06_08-39-36.ROI-1.thumb.jpg
│ └── ROI-2
│ ├── 2025-11-06_08-39-36.ROI-2.json
│ ├── 2025-11-06_08-39-36.ROI-2.thumb.jpg
│ └── 2025-11-06_08-39-36.ROI-2.tiff
├── config.yaml
└── temporary
├── barcode.jpg
└── preview.svg
So, each image is stored in a directory with the following hierarchy:
/<computer_id>/<scanner_model>/<date>/<datetime>/<roi_id>
This structure is designed so that if users merge data from multiple scanners/machines in the same directory/file structure, collisions (no duplicated path/filenames) should not happen.
In each image directory is names after the ROI and contains:
- the image
- a thumbnail of the image for fast display (
.thum.jpg) - a JSON file with metadata (
.json)
Each ROI emits a JSON companion with:
timestamp,dirname,filename,uri, andthumbnail.- Optical settings:
name,xyxy_mm,dpi,file_format, plus the probeddriver,device_id,sane_device, andhost_id. - Integrity: the image MD5 checksum.
scan_metadata: the decoded Data Matrix payload (typically the plate label and replication identifiers).
We provide a standalone webapp to seamlessly generate labels that can be printed on standard paper or label paper.



