← All posts

STAYCHARTED BLOG · AMAZON S3 · IMAGE CLASSIFICATION

How to classify images in an S3 bucket with your own categories

Sort the photos in your S3, R2, B2 or Google Cloud bucket into your own categories, learned from the folders you have. Originals untouched.

By Manoj Mohandas ·

The usual ways to classify images in S3

1. A Lambda function calling a general image API. An S3 upload triggers a Lambda, which sends the photo to Amazon Rekognition's DetectLabels (or Google Cloud Vision) and stores the labels. It's quick to build, but the labels are the service's own: "Box", "Car", "Machine". They can't say crushed corner or PN-10423, because they've never seen your categories.

2. Amazon Rekognition Custom Labels. It learns your own labels, and it can take them from your S3 folder names. The catch is running it: you start the trained model before you use it, you're charged for every hour it's running, and you stop it yourself. For a folder that fills up once a day, you either leave it running or build the start and stop around it.

3. Build your own. A SageMaker notebook, a pre-trained vision model, a training script, an endpoint and the code around it. That's flexible, but it's weeks of work and someone to keep it running.

If you used Amazon Lookout for Vision for defect photos: AWS ended support for it on 31 October 2025, so those models need a new home too.

What you probably already have

Most teams don't start from nothing. The photos are already sorted, one way or another:

  • By folder: parts/PN-10423/IMG_4412.jpg, claims/water-damage/…
  • By file name: PN-10423_front.jpg, crushed-corner_0041.jpg
  • By keyword: your photo library or inspection app wrote the category into each photo's own metadata (its keywords, title or description).

That sorting is the training data. You don't need to label anything again.

Train from the bucket

With StayCharted AI Model Trainer, the photos are read where they already are. There's no ZIP to build and no spreadsheet of links.

  1. Connect the storage in Settings → Storage. For Amazon S3, a CloudFormation template makes a role in your account, with no key to paste. You list the folders AMT may read, and, only if you want sorted copies, the folders it may copy into. The role is written from those lists: read-only unless you ask for copies, and never a delete.
  2. New model → Pictures → From your storage. Pick the folder, and say where each photo's category is: its folder name (at the level you choose), its file name, or a metadata field in the photo. A preview shows the categories and counts before anything is read.
  3. Check your pictures. Every photo is checked before training. You see photos that look like they belong in another category, the same photo under two categories, and near-identical copies, each one click to fix.
  4. Train and test. The model learns from the picture itself, never from the folder or file name, because a new photo arrives as IMG_4412.jpg. It's tested on photos it never trained on, and the report shows how often it's right per category.

New photos for a category later? Add new photos from this folder reads only the ones it hasn't read before, then you retrain.

Sort new photos back into the bucket

Categorize new pictures → From your storage. Pick the folder of new photos. It can be in another bucket. By default only photos this model hasn't answered before are read, so a folder that fills up every day is one click: Fill new photos.

What you get back:

  • A spreadsheet in Filled files, one row per photo, with its category and confidence.
  • Answers it's unsure of go to the Review Queue, for a person to check.
  • Optional: a sorted copy of each photo, in <your folder>/<category>/, with unsure ones in <your folder>/_needs-review/. It's a server-side copy, so the photo isn't downloaded again, and only folders you listed can be written to.
  • Optional: tags on each copy: staycharted-category, staycharted-confidence, staycharted-review and staycharted-model, beside the photo's own tags.
  • Optional: the category in each copy's metadata, as a keyword, title or description, so your photo library or DAM sees it too.

Your originals are never written to. Not moved, not re-encoded, not tagged, not deleted. A sorted copy is your photo exactly, with only the additions you ticked.

Route them with EventBridge

Because the copies land in folders by category, your own AWS workflow can pick them up. Turn on Amazon EventBridge notifications for the bucket, then add a rule that matches new copies in the review folder:

Show JSON example
{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": { "name": ["parts-photos"] },
    "object": { "key": [{ "prefix": "sorted/_needs-review/" }] }
  }
}

Send it to an SNS topic for the team, a Step Functions workflow, or a Lambda. Match sorted/PN-10423/ instead to start the reorder for one part. The setup guide has the details: Connect your storage.

Not only Amazon S3

The same connection works with any storage that speaks the S3 API at a public HTTPS address:

Storage How it connects
Amazon S3 A role made by our template (no key), or an access key
Cloudflare R2 An R2 API token's access key and your account ID
Backblaze B2 An application key and your bucket's region
Wasabi An access key and region
DigitalOcean Spaces A Spaces access key and region
Google Cloud Storage An HMAC key (Cloud Storage → Settings → Interoperability)
Other S3-compatible Any S3 endpoint at a public HTTPS address

How accurate is it?

It depends on your photos and how different your categories look, so the report measures it on your own photos, per category, before you rely on it. On a public set of car damage photos (6 categories, front or rear, broken, crushed or undamaged, 552 held-out photos), measured on our production service:

StayChartedAI Model Trainer · model comparison
Model Right Projected after review
AI Image Classifier Model 76.6% 83.5% (12% checked)
Dedicated AI Image Model 86.4% 95.8% (23% checked)

The full method is in the car photo benchmark.

Projected results assume a person corrects every flagged mistake without introducing errors. Human review was not measured in this test.

What it doesn't do yet

Azure Blob Storage isn't S3-compatible. It needs its own connector, which is planned.

  • Private storage (inside a VPN, or a MinIO only your network can reach) can't be reached from our service. That's a self-hosted conversation: contact us.
  • Watching a folder by itself. New photos are read when someone presses Fill new photos. Filling on a schedule is planned.

Common questions

Does StayCharted change the photos in my bucket?

No. Originals are only read. When you ask for sorted copies, the only write is a copy into a folder you listed, and the role itself can't write anywhere else.

What permissions does it need?

To train and fill: list and read, on the folders you name. For sorted copies: write on the copy folder only, plus reading the original's tags so the copy keeps them. Never delete.

Does it keep my photos?

It keeps its own small copy of each photo (at most 512 pixels on a side), made from the pixels alone, plus a thumbnail, for training, the report and the Review Queue. The original isn't kept. Deleting the model deletes them.

How many photos do I need per category?

At least 10, and 20 or more is better. Categories that look alike need more. The report shows which ones.

I already use Rekognition Custom Labels. Can I use the same bucket?

Yes. If your training photos are in folders named by label, which Custom Labels can also use, connect the same bucket and train from the same folders.

What does it cost?

Reading pictures needs the Vision add-on, on Essentials or Business. The photos read count toward your plan's pictures a month. See pricing.

Sources and further reading

Put it into practice with StayCharted

Start free →

Check plans and allowances · Security and your data