Unit 02.01: Resizing, and what it destroys
Resizing is lossy, and what it destroys is not recoverable by resizing back.
Fine detail below the target resolution is gone
A checkerboard reduced and enlarged again is no longer a checkerboard.
The code measures how many distinct values survive three round trips.
import numpy as np
from PIL import Image
original = Image.fromarray(
(np.indices((64, 64)).sum(axis=0) % 2 * 255).astype("uint8"))
for size in [(32, 32), (16, 16), (8, 8)]:
small = original.resize(size, Image.NEAREST)
back = np.asarray(small.resize((64, 64), Image.NEAREST))
unique = len(np.unique(back))
print(f"64 -> {size[0]:>2} -> 64 distinct values remaining: {unique}")
print(f"\noriginal distinct values: {len(np.unique(np.asarray(original)))}")
# A fine checkerboard resized down and back up is no longer a checkerboard.
# Resizing is lossy and the loss is not recoverable -- so anything smaller than
# a few pixels in the original is gone before the model sees it.
The distinct-value count collapses. Anything only a few pixels across in the original - a scratch, a small serial number, a hairline crack - is removed before the model ever sees it.
That is a constraint on the task, not on the model. If the thing you are detecting is small in the source image, no architecture recovers it after a standard resize.
The mistake this prevents
The mistake is choosing an input resolution from what the network expects and checking nothing else. Measure how large your target feature is in pixels after the resize; if it is under a few pixels, you need tiling rather than a bigger model.
Takeaway
Resizing destroys detail permanently. Measure your target feature's size after the resize before assuming the model can see it.
