[object Object]

← 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

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 →