Code

Your photographs — prepare.py and our dataset

Your photographs do not look like 28 × 28 gray PNGs. A phone gives a 4000 × 3000 colour JPEG, with a "rotated" flag on top. Before anything else they have to be put into the folder layout that data.py reads.

What prepare.py does

photos/                       data/
  category_a/  IMG_001.jpg        category_a/  0000.png  0001.png ...
  category_b/  IMG_002.jpg  →     category_b/  0000.png  0001.png ...

For every photograph it:

  1. opens any format Pillow understands (jpg, png, webp …);
  2. applies the phone's "rotation" flag (exif_transpose) — otherwise half of the pictures would lie on their side;
  3. converts to grayscale;
  4. cuts a square from the middle and shrinks it to 28 × 28 — nothing is stretched;
  5. saves it as 0000.png, 0001.png …

It is complete and ready — a tool, not an exercise. Create prepare.py (see the right panel).

Run it

python prepare.py

With no arguments it reads photos/ and writes to data/. You can name other folders too: python prepare.py photos_test data_test (your separate test folder). An example of what it prints (our trial with two folders of 6 JPEGs and one text file in each):

skipped (not an image): photos\cat\notes.txt
skipped (not an image): photos\dog\notes.txt
cat: 6 images
dog: 6 images

A file that is not a picture is skipped and you are told — it will not blow up later with a confusing error.

What you lose — honestly

Colour and fine detail. 28 × 28 in shades of gray is very little. If your categories differ by colour (say "ripe / unripe"), this step throws that difference away. It is a deliberate compromise: our CNN takes 1 channel and 28 × 28. In lesson 10, when we use a pretrained network, we read pictures from photos/ straight from the originals (colour, 224 × 224).

If 28 × 28 seems too small, you may change SIZE — but then the CNN (the reshape to 28 × 28 and the Linear input c2 · 7 · 7) has to change too. In this course we stay with 28.

Before your own photographs — reproduce our numbers

You do not have our stand-in dataset, but you can make it. A second file, make_standin.py, takes four FashionMNIST classes you already downloaded in lesson 2 and saves them as PNG folders with exactly the same layout as your photographs:

python make_standin.py
standin_data {'tshirt': 200, 'pullover': 200, 'coat': 200, 'sneaker': 200}
standin_test {'tshirt': 100, 'pullover': 100, 'coat': 100, 'sneaker': 100}
standin_imbalanced {'tshirt': 200, 'pullover': 200, 'coat': 20, 'sneaker': 200}

That is ~1,800 small files, so it can take a couple of minutes. Three folders:

  • standin_data — 4 classes of 200 (the lesson's numbers rest on this);
  • standin_test — 100 new pictures per class (we use it in lesson 11);
  • standin_imbalanced — like standin_data, but coat has only 20 (the trap in step 7).

Work with standin_data first, so that you can see your code produce our numbers. Only then move on to your own data/.

What next

You have data/<category>/*.png. In the next step you write the code that reads it, splits it and normalises it.