Skip to content

Latest commit

 

History

42 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Intro-to-CV — Specimen Image Classifier

A ResNet-50 image classification pipeline for identifying biological specimens (built and tested on beetle family classification) from photographs. Built for usability in pathology and ecology labs: train a model on your own labelled photos, evaluate it against held-out data, and hand a trained model to user through a point-and-click desktop UI — no code required to run it day-to-day.

The interactive classifier is internally named EcoVision; you'll see that name in its window title and in some file paths.

Contents

Overview

Notebook / script Purpose
Code/Split_Dataset.ipynb Randomly splits a folder of images sorted by category into the training/testing layout the other notebooks expect, at a ratio you choose.
Code/Train_Model.ipynb Trains a transfer-learned ResNet-50 classifier on your own image folders and saves the resulting model, metrics, and metadata.
Code/Compare_Models_on_Dataset.ipynb Runs one or more trained models against a shared evaluation dataset and produces ROC/PR curves and confusion matrices for side-by-side comparison.
Code/Model_UI.ipynb Launches a desktop GUI (no coding required) for classifying a single image or a whole folder with a trained model, including a Grad-CAM heatmap of what the model focused on.

All three read from and write to two shared top-level folders: Data/ (your images) and Models/ (trained weights and their metrics).

Repository structure

Specimen_Classifier/
├── Code/
│   ├── Split_Dataset.ipynb             Randomly split a category-sorted folder into training/testing
│   ├── Train_Model.ipynb               Train a new ResNet-50 classifier
│   ├── Model_UI.ipynb                  Desktop GUI for running inference with a trained model
│   ├── Compare_Models_on_Dataset.ipynb Batch-evaluate & plot ROC/PR curves and confusion matrices
│   └── Python-Requirements.txt         Pinned dependency versions
│
├── Data/                              ⚠ not tracked in git — populate this folder locally
│   └── <dataset name>/
│       ├── training/
│       │   └── <class name>/*.jpg
│       └── testing/
│           └── <class name>/*.jpg
│
├── Models/
│   └── <model_run_name>/
│       ├── best_weights_ResNet50.h5   Trained weights (tracked via Git LFS)
│       ├── model_info.json            Architecture, source dataset, per-class training counts
│       ├── confusion_matrix.csv
│       ├── classification_report.csv
│       └── ResNet-Predictions.csv     Raw per-class prediction probabilities on the test set
│
├── Presentation_Plots/                ⚠ not tracked in git — regenerated by Compare_Models_on_Dataset.ipynb
│   └── cache/                         Cached predictions, keyed by model/dataset/class-scheme hash
│
├── .gitattributes                     Marks *.h5 / *.zip for Git LFS
├── .gitignore
└── README.md

Data/ and Presentation_Plots/ are intentionally excluded from version control (see .gitignore) — raw datasets are too large to commit, and plots are cheap to regenerate. Everything under Models/ is committed, with the large .h5 weight files handled by Git LFS.

Data format

Both Train_Model.ipynb and Compare_Models_on_Dataset.ipynb expect images sorted into one subfolder per class. For training, that structure is duplicated under separate training/ and testing/ roots so the split is explicit:

Data/InHouse_July/
├── training/
│   ├── Carabidae/
│   │   ├── img001.jpg
│   │   └── ...
│   ├── Chrysomelidae/
│   ├── Other/
│   └── Staphylinidae/
└── testing/
    ├── Carabidae/
    ├── Chrysomelidae/
    ├── Other/
    └── Staphylinidae/

The training/ and testing/ trees must contain the same set of class subfolders — Keras infers class labels (and their order) alphabetically from these folder names. Compare_Models_on_Dataset.ipynb instead expects a single flat folder of class subfolders (no train/test split), since it's evaluating rather than training.

Trained model format

Each subfolder of Models/ is one training run, named after that run's model_run_name. Train_Model.ipynb creates it automatically and writes five files into it:

File Contents
best_weights_ResNet50.h5 The model checkpoint with the lowest validation loss (via Keras ModelCheckpoint + EarlyStopping).
model_info.json Base architecture, source dataset name, and per-class training image counts.
confusion_matrix.csv Predicted vs. true class counts on the test set.
classification_report.csv Per-class precision / recall / F1 / support, plus macro and accuracy rows.
ResNet-Predictions.csv Raw softmax output for every test image (one row per image, one column per class).

Model_UI.ipynb and Compare_Models_on_Dataset.ipynb both read this folder structure directly, so a model isn't usable by either until all five files are present.

Getting started

Prerequisites

Tool Why
Git Clone this repository.
Git LFS Required before cloning — the .h5 model weights in Models/ are stored via Git LFS. Without it you'll get small placeholder pointer files instead of usable weights.
Anaconda Supplies Python plus numpy, pandas, matplotlib, scikit-learn, Pillow, and Jupyter out of the box.
An IDE with Jupyter support, e.g. VS Code with the Python and Jupyter extensions To open and run the .ipynb notebooks.

Setup

Windows: run the git-related commands below in Git Bash (installed alongside Git for Windows) — they won't work as-is in Command Prompt or PowerShell. Run the pip install command in Anaconda Prompt specifically, not Git Bash — Git Bash can silently resolve python/pip to the wrong install (e.g. the Windows Store stub) instead of Anaconda's. Mac: Terminal handles every step below, no switching required.

# 1. Install Git LFS once per machine, before cloning
git lfs install

# 2. Clone the repository
git clone https://github.com/timlee-bioinf/Specimen_Classifier.git
cd Specimen_Classifier

# 3. Confirm the model weights actually downloaded (should be ~100-130MB each,
#    not a few bytes — if they're tiny, Git LFS wasn't active during clone)
ls -lh Models/*/*.h5
# 4. Install the one dependency Anaconda doesn't ship with by default
#    (In Anaconda Prompt, `base` is already active, so this is all you need.)
pip install tensorflow

Using a plain PowerShell window instead of Anaconda Prompt (e.g. VS Code's default integrated terminal)? Activate the environment explicitly first, since PowerShell doesn't always do this automatically:

conda activate base
pip install tensorflow

This project intentionally runs on Anaconda's plain base environment — no custom virtual environment is required. See Code/Python-Requirements.txt for the exact versions this codebase is tested against.

Place your own image data under Data/ following the structure above before running any of the notebooks.

Usage

1. Split a category folder into training/testing

If your images are sorted into one flat folder per category (e.g. Data/Collection/Carabidae/, Data/Collection/Chrysomelidae/, ...) rather than already split into training//testing/, open Code/Split_Dataset.ipynb and run it top to bottom. It walks you through picking that source folder, picking an output folder, and choosing a training/testing percentage split (80/20 by default) — no coding required, just two folder-picker pop-ups and one number to edit. It copies images (your originals are left untouched) into the same training//testing/ layout the other notebooks expect.

2. Train a model

Open Code/Train_Model.ipynb and run it top to bottom. Before running, edit these two variables near the top to name the run and point at your data:

model_run_name = "InHouse_0603_ResNet50_1"  # change this for every new training run
dataset_dir = os.path.join(REPO_ROOT, "Data", "<dataset>")  # change this to point at a different Data/ subfolder

REPO_ROOT is found automatically (it walks up from wherever the notebook is running until it finds this repo's Models/ folder), so these paths work regardless of whose machine or which folder the repo is cloned into — no need to edit REPO_ROOT, train_data_dir, test_data_dir, or models_dir directly.

The notebook trains a ResNet-50 (ImageNet weights, frozen base layers) with early stopping, then writes the five output files into Models/<model_run_name>/.

3. Compare models / generate presentation plots

Code/Compare_Models_on_Dataset.ipynb scores one or more trained models against a shared dataset and plots per-class and combined ROC/PR curves plus a confusion matrix per model. Open it, select the Anaconda base kernel, and edit only its Config cell (DATASET_DIR, EVAL_CLASSES, MODELS, TARGET_CLASS, AVERAGING) to point it at the dataset and models you want to compare — every markdown cell above it explains what each setting does in plain language, so no Python knowledge is needed to change what gets compared. Nothing past the Config cell needs to change. It also supports mapping a model's finer-grained classes down onto a coarser evaluation scheme (e.g. collapsing extra classes into "Other").

Then choose Run All. Every plot renders inline in the notebook and is saved to Presentation_Plots/, with intermediate predictions cached under Presentation_Plots/cache/ so re-running doesn't re-run inference unless the config actually changed.

4. Run the interactive classifier

Open Code/Model_UI.ipynb in VS Code (or Jupyter), select the Anaconda base kernel, and choose Run All. This opens a separate desktop window — titled EcoVision Beetle Classifier — that may appear behind your other windows the first time.

From that window you can:

  • Pick any trained model from Models/ via the dropdown.
  • Classify a single image, with a Grad-CAM heatmap showing what the model focused on.
  • Classify a whole folder of images at once and see a live confusion matrix if the folder is organized into class subfolders.

Troubleshooting

Model weight files are a few bytes instead of ~100MB

Git LFS wasn't active when you cloned. Install it (git lfs install), then run git lfs pull from inside the repository to fetch the real files.

No "base" kernel available when opening a notebook

Make sure Anaconda is installed and your IDE has been restarted since. In VS Code, confirm the Python and Jupyter extensions are installed, then use "Select Kernel" → Python Environments → the environment labeled base.

The classifier window never appears after "Run All"

Check your taskbar/dock — it's a separate desktop window (built with Tkinter) and can open behind your editor rather than in front of it.

Contributors

License

No license has been specified for this repository yet. Until one is added, please contact the maintainers before reusing or redistributing this code.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages