<feed xmlns='http://www.w3.org/2005/Atom'>
<title>albumen.git/scripts/faces.py, branch main</title>
<subtitle>Ruby/Sinatra photo album</subtitle>
<link rel='alternate' type='text/html' href='https://git.jots.org/albumen.git/'/>
<entry>
<title>Switch face detection to CNN model with parallel batch processing</title>
<updated>2026-06-08T17:34:18+00:00</updated>
<author>
<name>Ken D'Ambrosio</name>
<email>ken@jots.org</email>
</author>
<published>2026-06-08T17:34:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.jots.org/albumen.git/commit/?id=73d6f8c9ac0177ca3a6587e6534592a545d44d67'/>
<id>73d6f8c9ac0177ca3a6587e6534592a545d44d67</id>
<content type='text'>
- faces.py: use model="cnn" (more accurate, better at angles/small faces/poor
  lighting) instead of HOG; model comment explains the trade-off clearly
- faces.py: accept multiple image paths; process with ThreadPoolExecutor
  (dlib releases GIL during C++ inference → genuine thread parallelism);
  output JSON dict {path: [faces]} for batch calls
- update.rb: batch_detect_faces() collects all unprocessed images per
  directory and calls faces.py once per directory rather than once per image,
  avoiding repeated model load overhead
- update.rb: FACES_WORKERS read from config.yml faces.workers (default 4;
  set to 20 in this install's config.yml on a 64-core Xeon)
- update.rb: process_dir() now takes idx/total and prints [N/total] prefix
  on every Scanning/Skipping line for progress monitoring

To monitor a long run:
  nohup ruby /opt/albumen/scripts/update.rb &gt; /tmp/faces_update.log 2&gt;&amp;1 &amp;
  tail -f /tmp/faces_update.log

Resume/restart is fully safe: sentinel files are only written after
atomic_write_json, so an aborted directory reruns cleanly from scratch.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- faces.py: use model="cnn" (more accurate, better at angles/small faces/poor
  lighting) instead of HOG; model comment explains the trade-off clearly
- faces.py: accept multiple image paths; process with ThreadPoolExecutor
  (dlib releases GIL during C++ inference → genuine thread parallelism);
  output JSON dict {path: [faces]} for batch calls
- update.rb: batch_detect_faces() collects all unprocessed images per
  directory and calls faces.py once per directory rather than once per image,
  avoiding repeated model load overhead
- update.rb: FACES_WORKERS read from config.yml faces.workers (default 4;
  set to 20 in this install's config.yml on a 64-core Xeon)
- update.rb: process_dir() now takes idx/total and prints [N/total] prefix
  on every Scanning/Skipping line for progress monitoring

To monitor a long run:
  nohup ruby /opt/albumen/scripts/update.rb &gt; /tmp/faces_update.log 2&gt;&amp;1 &amp;
  tail -f /tmp/faces_update.log

Resume/restart is fully safe: sentinel files are only written after
atomic_write_json, so an aborted directory reruns cleanly from scratch.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Add opt-in facial recognition: detection and embedding storage</title>
<updated>2026-06-08T17:09:51+00:00</updated>
<author>
<name>Ken D'Ambrosio</name>
<email>ken@jots.org</email>
</author>
<published>2026-06-08T17:09:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.jots.org/albumen.git/commit/?id=da28a20f091372375822f9dde4486ecade859e7e'/>
<id>da28a20f091372375822f9dde4486ecade859e7e</id>
<content type='text'>
- scripts/faces.py: Python helper using face_recognition (dlib/HOG) to
  detect faces and return 128-D encodings as JSON; called by update.rb
- scripts/update.rb: enrich_faces() stores face boxes and encodings in
  album.json per image (null = not yet processed, [] = processed/none found);
  skips files already processed; gated on faces.enabled in config.yml
- Reads CONFIG_PATH (same env var as app.rb) to check faces.enabled flag
- Feature is off by default; enabled in this install via config.yml
- README.md, DESIGN.md: document installation, opt-in config, data model,
  and planned clustering/people-management pipeline

People management UI and clustering script are the next milestone.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- scripts/faces.py: Python helper using face_recognition (dlib/HOG) to
  detect faces and return 128-D encodings as JSON; called by update.rb
- scripts/update.rb: enrich_faces() stores face boxes and encodings in
  album.json per image (null = not yet processed, [] = processed/none found);
  skips files already processed; gated on faces.enabled in config.yml
- Reads CONFIG_PATH (same env var as app.rb) to check faces.enabled flag
- Feature is off by default; enabled in this install via config.yml
- README.md, DESIGN.md: document installation, opt-in config, data model,
  and planned clustering/people-management pipeline

People management UI and clustering script are the next milestone.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
