← back to Dw Photo Capture
Fix aug-training crash (cannot write empty image): guard augment against tiny/empty crops + wrap JPEG recompress + AugSet falls back to a neighbor on a corrupt cache image (never crashes the run)
27b572c567c50b36ba0b2dafbaaf8df2a19f56dd · 2026-07-07 13:09:39 -0700 · Steve Abrams
Files touched
M visual-search/train/finetune_aug.py
Diff
commit 27b572c567c50b36ba0b2dafbaaf8df2a19f56dd
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jul 7 13:09:39 2026 -0700
Fix aug-training crash (cannot write empty image): guard augment against tiny/empty crops + wrap JPEG recompress + AugSet falls back to a neighbor on a corrupt cache image (never crashes the run)
---
visual-search/train/finetune_aug.py | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/visual-search/train/finetune_aug.py b/visual-search/train/finetune_aug.py
index e768bdf..845b37f 100644
--- a/visual-search/train/finetune_aug.py
+++ b/visual-search/train/finetune_aug.py
@@ -18,16 +18,20 @@ Image.MAX_IMAGE_PIXELS = None
def augment(im):
# simulate a handheld iPhone shot of a physical sample — varied strength, each applied ~probabilistically
+ if im.width < 48 or im.height < 48: return im # too small to degrade safely (corrupt/tiny cache)
w, h = im.size
if random.random() < 0.7: im = im.rotate(random.uniform(-8, 8), expand=False, fillcolor=(238,238,238))
if random.random() < 0.7:
cx, cy = random.uniform(0.02, 0.10), random.uniform(0.02, 0.10)
- im = im.crop((int(w*cx), int(h*cy), int(w*(1-cx)), int(h*(1-cy))))
+ l,t,r,bt = int(w*cx), int(h*cy), int(w*(1-cx)), int(h*(1-cy))
+ if r-l >= 32 and bt-t >= 32: im = im.crop((l,t,r,bt)) # never crop to an empty/tiny box
if random.random() < 0.6: im = im.filter(ImageFilter.GaussianBlur(random.uniform(0.4, 1.6)))
if random.random() < 0.7: im = ImageEnhance.Brightness(im).enhance(random.uniform(0.85, 1.30)) # glare / shadow
if random.random() < 0.5: im = ImageEnhance.Contrast(im).enhance(random.uniform(0.80, 1.15))
- if random.random() < 0.6:
- b = io.BytesIO(); im.save(b, 'JPEG', quality=random.randint(45, 80)); b.seek(0); im = Image.open(b).convert('RGB')
+ if random.random() < 0.6 and im.width >= 32 and im.height >= 32:
+ try:
+ b = io.BytesIO(); im.save(b, 'JPEG', quality=random.randint(45, 80)); b.seek(0); im = Image.open(b).convert('RGB')
+ except Exception: pass # a bad recompress must never crash training
return im
class AugSet(Dataset):
@@ -36,8 +40,11 @@ class AugSet(Dataset):
def __len__(self): return len(self.rows)
def __getitem__(self, i):
idv, pat, col, ven, typ = self.rows[i]
- im = Image.open(os.path.join(CACHE, idv + '.jpg')).convert('RGB')
- img = self.pp(augment(im)) # <-- degrade before CLIP preprocess
+ try:
+ im = Image.open(os.path.join(CACHE, idv + '.jpg')).convert('RGB')
+ img = self.pp(augment(im)) # <-- degrade before CLIP preprocess
+ except Exception:
+ return self.__getitem__((i + 1) % len(self.rows)) # corrupt cache image → use a neighbor, never crash
txt = self.tok([T.caption(pat, col, ven, typ)])[0]
return img, txt
← a376a2d DEVICE-TEST: multi-photo tip — take 2-3 pattern shots for vi
·
back to Dw Photo Capture
·
Look Up SKU pill: camera-first pure-identify flow — shoot FR e56063d →