AI: Improve Face Detection with an ONNX-based model #5167

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2025-10-06 18:51:49 +02:00
parent 677e190b6e
commit 94f8a5f35d
39 changed files with 1713 additions and 43 deletions

View file

@ -33,6 +33,9 @@ tensorflow-amd64-avx: install-tensorflow
tensorflow-amd64-avx2: install-tensorflow
install-tensorflow:
/scripts/install-tensorflow.sh auto
onnxruntime: install-onnx
install-onnx:
/scripts/install-onnx.sh
tensorflow-gpu: install-tensorflow-gpu
install-tensorflow-gpu:
/scripts/install-tensorflow.sh gpu

126
scripts/dist/install-onnx.sh vendored Executable file
View file

@ -0,0 +1,126 @@
#!/usr/bin/env bash
set -euo pipefail
ONNX_VERSION=${ONNX_VERSION:-1.22.0}
TMPDIR=${TMPDIR:-/tmp}
SYSTEM=$(uname -s)
ARCH=${PHOTOPRISM_ARCH:-$(uname -m)}
DESTDIR_ARG="${1:-/usr}"
if [[ ! -d "${DESTDIR_ARG}" ]]; then
mkdir -p "${DESTDIR_ARG}"
fi
DESTDIR=$(realpath "${DESTDIR_ARG}")
if [[ $(id -u) != 0 ]] && ([[ "${DESTDIR}" == "/usr" ]] || [[ "${DESTDIR}" == "/usr/local" ]]); then
echo "Error: Run ${0##*/} as root to install in '${DESTDIR}'." >&2
exit 1
fi
mkdir -p "${DESTDIR}" "${TMPDIR}"
archive=""
sha=""
case "${SYSTEM}" in
Linux)
case "${ARCH}" in
amd64|AMD64|x86_64|x86-64)
archive="onnxruntime-linux-x64-${ONNX_VERSION}.tgz"
sha="8344d55f93d5bc5021ce342db50f62079daf39aaafb5d311a451846228be49b3"
;;
arm64|ARM64|aarch64)
archive="onnxruntime-linux-aarch64-${ONNX_VERSION}.tgz"
sha="bb76395092d150b52c7092dc6b8f2fe4d80f0f3bf0416d2f269193e347e24702"
;;
*)
echo "Warning: ONNX Runtime is not provided for Linux/${ARCH}; skipping install." >&2
exit 0
;;
esac
;;
Darwin)
case "${ARCH}" in
arm64|ARM64|aarch64|x86_64|x86-64)
archive="onnxruntime-osx-universal2-${ONNX_VERSION}.tgz"
sha="cfa6f6584d87555ed9f6e7e8a000d3947554d589efe3723b8bfa358cd263d03c"
;;
*)
echo "Unsupported macOS architecture '${ARCH}'." >&2
exit 1
;;
esac
;;
*)
echo "Unsupported operating system '${SYSTEM}'." >&2
exit 1
;;
esac
verify_sha() {
local expected="$1"
local file="$2"
if command -v sha256sum >/dev/null 2>&1; then
echo "${expected} ${file}" | sha256sum -c - >/dev/null
else
echo "${expected} ${file}" | shasum -a 256 -c - >/dev/null
fi
}
if [[ -z "${archive}" ]]; then
echo "Could not determine ONNX Runtime archive." >&2
exit 1
fi
url="https://github.com/microsoft/onnxruntime/releases/download/v${ONNX_VERSION}/${archive}"
package_path="${TMPDIR}/${archive}"
if [[ -f "${package_path}" ]]; then
if verify_sha "${sha}" "${package_path}"; then
echo "Using cached archive ${package_path}."
else
echo "Cached archive ${package_path} failed checksum, re-downloading..."
rm -f "${package_path}"
fi
fi
if [[ ! -f "${package_path}" ]]; then
echo "Downloading ONNX Runtime ${ONNX_VERSION} (${archive})..."
curl -fsSL --retry 3 --retry-delay 2 -o "${package_path}" "${url}"
fi
echo "Verifying checksum..."
verify_sha "${sha}" "${package_path}"
echo "Extracting to ${DESTDIR}..."
tar --overwrite --mode=755 -C "${DESTDIR}" -xzf "${package_path}"
# Normalize layout: copy libraries into ${DESTDIR}/lib and remove extracted tree.
output_lib_dir="${DESTDIR}/lib"
mkdir -p "${output_lib_dir}"
for extracted in "${DESTDIR}/onnxruntime-linux-x64-${ONNX_VERSION}" "${DESTDIR}/onnxruntime-linux-aarch64-${ONNX_VERSION}" "${DESTDIR}/onnxruntime-osx-universal2-${ONNX_VERSION}"; do
if [[ -d "${extracted}/lib" ]]; then
find "${extracted}/lib" -maxdepth 1 -type f -name "libonnxruntime*.so*" -print0 | while IFS= read -r -d '' file; do
cp -af "${file}" "${output_lib_dir}/"
done
# copy any symlinks as well to preserve SONAME links
find "${extracted}/lib" -maxdepth 1 -type l -name "libonnxruntime*.so*" -print0 | while IFS= read -r -d '' link; do
target=$(readlink "${link}")
ln -sf "${target}" "${output_lib_dir}/$(basename "${link}")"
done
rm -rf "${extracted}"
fi
done
if [[ "${SYSTEM}" == "Linux" ]]; then
if [[ "${DESTDIR}" == "/usr" || "${DESTDIR}" == "/usr/local" ]]; then
ldconfig
else
ldconfig -n "${DESTDIR}/lib" >/dev/null 2>&1 || true
fi
fi
echo "ONNX Runtime ${ONNX_VERSION} installed in '${DESTDIR}'."

82
scripts/download-scrfs.sh Executable file
View file

@ -0,0 +1,82 @@
#!/usr/bin/env bash
set -euo pipefail
TODAY=$(date -u +%Y%m%d)
MODEL_SOURCE="scrfd_500m_bnkps_shape640x640.onnx"
LOCAL_MODEL_NAME="scrfd.onnx"
PRIMARY_URL="https://dl.photoprism.app/onnx/scrfd/${MODEL_SOURCE}?${TODAY}"
FALLBACK_URL="https://raw.githubusercontent.com/laolaolulu/FaceTrain/master/model/scrfd/${MODEL_SOURCE}"
MODEL_URL=${MODEL_URL:-"${PRIMARY_URL}"}
MODELS_PATH="assets/models"
MODEL_DIR="$MODELS_PATH/scrfs"
MODEL_FILE="$MODEL_DIR/${LOCAL_MODEL_NAME}"
MODEL_TMP="/tmp/photoprism/${MODEL_SOURCE}"
MODEL_HASH="ae72185653e279aa2056b288662a19ec3519ced5426d2adeffbe058a86369a24 ${MODEL_TMP}"
MODEL_VERSION="$MODEL_DIR/version.txt"
MODEL_BACKUP="storage/backup/scrfs-${TODAY}"
mkdir -p /tmp/photoprism
mkdir -p storage/backup
mkdir -p "${MODEL_DIR}"
hash_file() {
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$1" | awk '{print $1}'
else
shasum -a 256 "$1" | awk '{print $1}'
fi
}
verify_hash() {
local expected="$1"
local file="$2"
if command -v sha256sum >/dev/null 2>&1; then
echo "${expected} ${file}" | sha256sum -c - >/dev/null
else
echo "${expected} ${file}" | shasum -a 256 -c - >/dev/null
fi
}
if [[ -f "${MODEL_FILE}" ]]; then
CURRENT_HASH=$(hash_file "${MODEL_FILE}")
if [[ "${CURRENT_HASH}" == ${MODEL_HASH%% *} ]]; then
echo "SCRFD model already up to date."
exit 0
fi
fi
echo "Downloading SCRFD detector from ${MODEL_URL}..."
if ! curl -fsSL --retry 3 --retry-delay 2 -o "${MODEL_TMP}" "${MODEL_URL}"; then
if [[ "${MODEL_URL}" != "${FALLBACK_URL}" ]]; then
echo "Primary download failed, trying fallback..."
MODEL_URL="${FALLBACK_URL}"
MODEL_HASH="ae72185653e279aa2056b288662a19ec3519ced5426d2adeffbe058a86369a24 ${MODEL_TMP}"
if ! curl -fsSL --retry 3 --retry-delay 2 -o "${MODEL_TMP}" "${MODEL_URL}"; then
echo "Failed to download SCRFD detector." >&2
exit 1
fi
else
echo "Failed to download SCRFD detector." >&2
exit 1
fi
fi
echo "Verifying checksum..."
verify_hash "${MODEL_HASH%% *}" "${MODEL_TMP}"
if [[ -f "${MODEL_FILE}" ]]; then
echo "Creating backup of existing detector at ${MODEL_BACKUP}"
rm -rf "${MODEL_BACKUP}"
mkdir -p "${MODEL_BACKUP}"
mv "${MODEL_FILE}" "${MODEL_BACKUP}/"
if [[ -f "${MODEL_VERSION}" ]]; then
cp "${MODEL_VERSION}" "${MODEL_BACKUP}/"
fi
fi
mv "${MODEL_TMP}" "${MODEL_FILE}"
echo "SCRFD ${TODAY} ${MODEL_HASH%% *} (${MODEL_SOURCE})" > "${MODEL_VERSION}"
echo "SCRFD detector installed in ${MODEL_DIR}."