Inspiration

Medicine powders have to be made consistently. Particle size, shape and clumping change how a powder flows, dissolves and behaves in a patient, and substandard or falsified medicines are a recognised safety problem. Checking powders under a microscope is slow and manual, and the data to automate it barely exists: labelled microscopy images are expensive to make, and pharmaceutical data is rarely shared.

I had already been building a particle-segmentation pipeline for a research project, trained on synthetic microscope images because labelled real ones are scarce. The hackathon theme, healthcare and the best use of data, made me ask a different question: can the same pipeline answer a quality-control question and not just count particles?

What it does

PowderPrint screens a powder sample against a trusted reference batch.

  1. You upload 10 microscope images of a powder.
  2. A segmentation model finds and outlines every particle.
  3. The batch is summarised as a five-number "fingerprint".
  4. The fingerprint is compared with a reference batch, and the app returns green (consistent), amber (inconclusive, send to lab) or red (deviates), with a plain-English reason such as "smaller particles (-41%)".

There is a second mode for labs with their own reference: upload a trusted batch and a sample batch, and the app shows how much they differ on each feature against a tolerance you set yourself. It makes no pass/fail call, because that decision belongs to the pharmacist. This mode is a prototype and has not been validated.

How I built it

Data. I generated synthetic powder images by compositing real single-particle photos onto a background, which gives exact particle masks for free. I had 100 real powder images: 70 form the reference, and 30 were held out and never touched while building it.

Model. A StarDist model trained on the synthetic images and applied to real ones. Synthetic-to-real transfer is the core of the data story.

Fingerprint. For each batch of 10 images I compute the mean particles per image, the median particle area, the spread of particle sizes, the mean circularity and a clumping score (the share of particle area in particles that touch another particle).

Score. Each feature's relative deviation from the reference is $d_i = |x_i - r_i| / r_i$, and the match score is

$$S = \frac{100}{1 + 10\sum_i w_i\, d_i}$$

with fixed weights $w_i$. Verdict thresholds come from the reference images only: green if $S$ is above the 5th percentile of scores from random 10-image batches of reference images, red if below half of that, amber in between. Nothing was tuned on the test sets.

App. Streamlit, with the overlay of detected particles, a table and chart of differences from the reference, and size-distribution curves.

Results

Test set (50 random groups of 10 images) Mean score Verdicts
Unseen real images (30 held out) 64.2 98% green, 2% amber
Synthetic sets A, B, C and the original synthetic set 10-18 100% red

The tool recognises unseen real powder and rejects clearly different batches. The synthetic sets differ from real in size, density and darkness, so this shows it separates clearly different batches. It does not yet show that it catches subtle drift or real counterfeits.

Segmentation accuracy on real images: [add IoU or F1 from the v3 notebook].

Challenges

  • A feature that measured nothing. My first clumping score came out at about 1.0 for almost every image, because of a logic error. I only found it when I tested a clearly different sample and the feature stayed flat. I replaced it with an adjacency-based measure and re-ran every result.
  • A test that wasn't held out. My first evaluation sampled the "held-out" group from all 100 real images, including the 70 used for the reference. I caught it, restricted the test to the 30 unseen images, and the real-batch score dropped from 72 to 64. The lower number is the honest one.
  • A generator that couldn't match real particle sizes. After repeated attempts, the synthetic particles stayed too small and too dark. I time-boxed the effort, stopped, and kept the synthetic sets as controlled, clearly different batches, so I don't claim they copy real powder.
  • Mixed-up data folders. At one point the real and synthetic folders were swapped in the code, and the reference was rebuilt from the wrong one. The names overlap, so nothing crashed. I fixed it by checking the file lists and rebuilding.

What I learned

Testing against a known-different sample is the fastest way to find a broken feature. A lower, honest number is worth more than an inflated one. And for a screening tool, being clear about what it cannot prove matters as much as what it can.

Limitations and what's next

This is a prototype, tested on one powder and one microscope. The next steps are validation on real batches and real substandard samples with a pharmaceutical partner, and a richer fingerprint (standard D10/D50/D90 size percentiles, aspect ratio, particle opacity). Testing sensitivity to gradual, subtle drift and validating the two-batch mode are also on the list. Microscopy alone cannot catch every counterfeit, so PowderPrint is meant to screen and send doubtful samples to the lab, not to certify medicine.

Built With

  • ai
Share this project:

Updates

Submission history