How do facetiles in Apple Photos that correspond to RKFace.modelId?

262 views Asked by At

I have been digging through the Apple Photos macOS app for a couple weekends now and I am stuck. I am hoping the smart people at StackOverflow can figure this out.

What I don't know:

  1. How are new hex directories determined and how do they correspond to RK.modelId. Perhaps 16 mod of RKFace.ModelId, or mod 256 of RKFace.ModelId?
  2. After a while, the facetile hex value no longer corresponds to the RKFace.ModelId. For example RKFace.modelId 61047 should be facetile_ee77.jpeg. The correct facetile, however, is face/20/01/facetile_1209b.jpeg. hex value 1209b is dec value 73883 for which I have no RKFace.ModelId.

Things I know:

  1. Apple Photos leverages deep learning networks to detect and crop faces out of your imported photos. It saves a cropped jpeg these detected faces into your photo library in resources/media/face/00/00/facetile_1.jpeg.
  2. A record corresponding to this facetile is inserted into RKFace where RKFace.modelId integer is the decimal number of tail hex version of the filename. You can use a standard dec to hex converter and derive the correct values. For example: RKFace.modelId to facetile filename
  3. Each subdirectory, for example "/00/00" will only hold a maximum of 256 facetiles before it starts a new directory. The directory name is also in hex format with directories. For example 3e, 3f.
1

There are 1 answers

0
tcc On

While trying to render photo mosaics, I stumbled upon that issue, too...

Then I was lucky to find both a master image and the corresponding facetile, allowing me to grep around, searching for the decimal and hex equivalent of the numbers embedded in the filenames.

This is what I came up with (assuming you are searching for someone named NAME):

SELECT 
    printf('%04x', mr.modelId) AS tileId 
FROM 
    RKModelResource mr, RKFace f, RKPerson p 
WHERE 
    f.modelId = mr.attachedModelId 
    AND f.personId = p.modelId 
    AND p.displayName = NAME

This select prints out all RKModelResource.modelIds in hex, used to name the corresponding facetiles you were searching for. All that is needed now is the complete path to the facetile.

So, a complete bash script to copy all those facetiles of a person (to a local folder out in the current directory) could be:

#!/bin/bash
set -eEu

PHOTOS_PATH=$HOME/Pictures/Photos\ Library.photoslibrary
DB_PATH=$PHOTOS_PATH/database/photos.db

echo $NAME
mkdir -p out/$NAME

TILES=( $(sqlite3 "$DB_PATH" "SELECT printf('%04x', mr.modelId) AS tileId FROM RKModelResource mr, RKFace f, RKPerson p WHERE f.modelId = mr.attachedModelId AND f.personId = p.modelId AND p.displayName='"$NAME"'") )
for TILE in ${TILES[@]}; do
    FOLDER=${TILE:0:2}
    SOURCE="$PHOTOS_PATH/resources/media/face/$FOLDER/00/facetile_$TILE.jpeg"
    [[ -e "$SOURCE" ]] || continue
    TARGET=out/$NAME/$TILE.jpeg
    [[ -e "$TARGET" ]] && continue
    cp "$SOURCE" "$TARGET" || :
done