Privacy-first retail analytics: face embedding, customer revisit tracking, VIP recognition, demographic insights, and security alerts — fully self-hosted.
See the code
In high-touch hospitality, dining, and luxury retail environments, operational excellence and customer lifetime value (LTV) hinge on a single operational capability: timely customer recognition. Knowing whether an entering patron is a first-time visitor, a returning casual guest, or a high-value regular dictates the quality of service delivery:
However, traditional Customer Relationship Management (CRM) and loyalty programs suffer from high customer friction:
As a consequence, over 70% of physical guest interactions remain completely anonymous until checkout, leaving service staff uninformed and operational management blind to foot-traffic retention dynamics.
CustomerLens resolves this fundamental disconnect by transforming existing CCTV and security camera feeds into an ambient, zero-friction guest intelligence layer.
Patrons are not required to enroll, download an application, scan a barcode, or present identification. The system autonomously:
To support fast human interpretation during rush hours, CustomerLens classifies patrons into a dynamic 2-letter lifecycle taxonomy that automatically updates based on cumulative visit frequency and monetary transaction records:
stateDiagram-v2
direction LR
[*] --> LN: First Visit (New Guest)
LN --> LC: Visits 2 to 4 (Casual Guest)
LC --> LL: Visits >= 5 (Loyal Regular)
LL --> ML: Cumulative Spend >= 2,000,000 VND (Mass Loyal)
ML --> HL: Cumulative Spend >= 10,000,000 VND or VIP Flag (VIP Loyal)

H (High Tier): High-spending patrons ($\ge 10,000,000$ VND cumulative spend or designated VIP).M (Medium Tier): Mass loyal customers with steady ticket size ($\ge 2,000,000$ VND).L (Low / Standard Tier): Default baseline tier for standard or newly acquired patrons.N (New): First-time visitor (visit count $= 1$).C (Casual): Irregular visitor (visit count between $2$ and $4$).L (Loyal): Committed regular patron (visit count $\ge 5$).HL (High-Loyal) patron enters, enabling immediate host greetings and priority table assignment.CustomerLens is engineered as a distributed, event-driven streaming platform designed for horizontal scaling across multi-camera installations.

halfvec_cosine_ops) with binary parameter binding, backed by an in-memory Redis L1 cache for sub-millisecond retrieval of active patrons. Input Frame ──> [SCRFD 500M INT8] ──> [5-Point Affine Alignment] ──> [EdgeFace 512-D INT8]
│ │
▼ ▼
Kalman Tracking Quality Attention Pooling
(Corner Velocity) (Sharpness & Pose Weighted)
│ │
└──────────────────────┬─────────────────────────────┘
▼
Cancelable Biometrics
(Irreversible Orthogonal Matrix)
│
▼
Supabase HNSW Search
(K=3 Multi-Template)
Face detection is handled by an INT8-quantized SCRFD 500M model capable of localizing 5 facial landmarks (pupils, nose tip, mouth corners) across extreme pitch/yaw angles ($\pm 45^\circ$) down to a minimum bounding box of $16 \times 16$ pixels. Cropped faces are geometrically normalized into canonical ArcFace coordinate space ($112 \times 112 \times 3$) using similarity transformations, ensuring consistent orientation for subsequent feature extraction.
Normalized face crops are mapped into 512-dimensional unit feature embeddings using an INT8-quantized EdgeFace backbone.
To eliminate legal liability and strictly adhere to privacy frameworks (GDPR Article 9 and CCPA), CustomerLens implements distance-preserving Cancelable Biometrics:
Rather than naively averaging noisy video frames, CustomerLens aggregates multi-frame trajectories using an intelligent composite quality weighting mechanism:
The entire system was evaluated on real-world video sequences from the academic YouTube Faces (YTF) benchmark, specifically utilizing the curated Kaggle dataset release:
youtube_faces_with_keypoints_full_1).All video clips were evaluated across four real-world surveillance degradation conditions simulating physical camera distance:
close_1.5m: Native resolution, standard frontal entry camera.medium_3.5m: Optical downscale 0.60x, Gaussian blur $\sigma = 0.6$.far_6.0m: Optical downscale 0.38x, motion blur $\sigma = 1.2$, JPEG quality 55.veryFar_9m: Extreme optical downscale 0.22x, optical distortion $\sigma = 1.8$, JPEG quality 35.
Evaluating all genuine pairs (same identity, different video clips) against balanced impostor pairs (different identities):
| Camera Condition | Pair Count (Gen / Imp) | TAR @ FAR=0.1% | TAR @ FAR=0.01% | Equal Error Rate (EER) | AUC-ROC | Genuine Sim ($\mu \pm \sigma$) | Impostor Sim ($\mu \pm \sigma$) | Separation Margin |
|---|---|---|---|---|---|---|---|---|
close_1.5m | 511 / 1,533 | 93.15% | 92.76% | 4.50% | 0.9851 | $0.6370 \pm 0.1911$ | $0.0240 \pm 0.1042$ | +0.6129 |
medium_3.5m | 511 / 1,533 | 90.80% | 86.69% | 4.31% | 0.9845 | $0.6074 \pm 0.1954$ | $0.0160 \pm 0.1058$ | +0.5914 |
far_6.0m | 502 / 1,506 | 16.73% | 7.37% | 14.38% | 0.9325 | $0.4500 \pm 0.2054$ | $0.0657 \pm 0.1401$ | +0.3843 |
veryFar_9m | 331 / 993 | 2.11% | 2.11% | 32.33% | 0.7377 | $0.4526 \pm 0.2115$ | $0.2641 \pm 0.1990$ | +0.1884 |
At operational retail entry distances ($1.5\text{m} - 3.5\text{m}$), the system achieves an AUC-ROC of 0.985, an Equal Error Rate of 4.31%, and an impostor separation margin of +0.6129, confirming reliable distinction between genuine patrons and distinct individuals.
Evaluating identification across a gallery of $N = 206$ unique individuals (first clip per person), tested against 206 independent probe clips:
| Camera Condition | Gallery Size ($N$) | Rank-1 Identification | Rank-5 Identification | Rank-10 Identification |
|---|---|---|---|---|
close_1.5m | 206 | 90.78% | 92.72% | 93.20% |
medium_3.5m | 206 | 88.83% | 92.23% | 93.20% |
far_6.0m | 203 | 54.19% | 67.98% | 75.37% |
veryFar_9m | 138 | 18.84% | 36.96% | 44.20% |
In a closed gallery of 206 registered individuals, the system correctly identifies the target at position number one (Rank-1) in 90.78% of trials at close range and 88.83% at 3.5m range. Top-5 suggestion accuracy reaches 92.72%.
Simulating an authentic operational store scenario: the gallery contains only 155 registered loyalty members. The probe stream contains both 155 genuine returning members and 51 unregistered strangers (impostors):
| Camera Condition | Operating Threshold ($\theta$) | True Identification (DIR) | False Impostor Accept (FPIR) | False Patron Reject (FNIR) |
|---|---|---|---|---|
close_1.5m | $\theta = 0.50$ | 80.65% | 0.00% | 19.35% |
close_1.5m | $\theta = 0.44$ | 83.87% | 0.00% | 16.13% |
close_1.5m | $\theta = 0.40$ | 85.16% | 3.92% | 14.84% |
close_1.5m | $\theta = 0.35$ | 89.03% | 29.41% | 10.97% |
medium_3.5m | $\theta = 0.46$ | 79.35% | 1.96% | 20.65% |
medium_3.5m | $\theta = 0.44$ | 80.65% | 1.96% | 19.35% |
medium_3.5m | $\theta = 0.40$ | 84.52% | 5.88% | 15.48% |
far_6.0m | $\theta = 0.40$ | 47.06% | 56.86% | 52.94% |
Recommended Production Operating Point: Setting $\theta = 0.44$ yields 83.87% correct identification while maintaining 0.00% False Positive Identification Rate (zero impostors accepted).
Executing 500 consecutive 512-dimensional vector queries against the live Supabase PostgreSQL HNSW index under concurrent load:

| Infrastructure Metric | Observed Result | Production Target SLO | Evaluation Status |
|---|---|---|---|
| P50 Latency (Median) | 58.17 ms | < 60 ms | Compliant |
| P95 Latency | 62.73 ms | < 80 ms | Compliant |
| P99 Latency (Tail) | 73.82 ms | < 100 ms | Compliant (26% safety margin) |
| P99.9 Latency | 110.37 ms | < 150 ms | Compliant |
| Maximum Observed Latency | 142.84 ms | — | Stable |
| Sustained Query Throughput | 16.9 QPS | $\ge$ 10 QPS | Compliant (+69% headroom) |
The complete single-frame inference pipeline (Detection + Alignment + Embedding + Tracking) executes in 32.29 ms (equivalent to 30.34 FPS), fully sustaining real-time processing of standard 25–30 FPS RTSP cameras.
CustomerLens is designed to comply with privacy frameworks including GDPR Article 9 (Special Category Biometric Data) and GDPR Article 17 (Right to be Forgotten):
user_revoked_at:{user_id}) terminate credentials immediately across all cluster nodes upon logout or administrative disablement.| Layer | Technologies & Frameworks |
|---|---|
| Frontend UI | Next.js 14 (App Router), React 18, Tailwind CSS, HTML5 Canvas API |
| API Gateway | FastAPI, Uvicorn, Python 3.12, asyncio, WebSockets |
| Event Messaging | Redpanda (Apache Kafka v2.8+ wire compatible), Redis Pub/Sub |
| AI Inference Engine | ONNX Runtime INT8, EdgeFace, SCRFD 500M, OpenCV, NumPy, SciPy |
| Database & Vector Search | PostgreSQL 15+, Supabase, pgvector (HNSW Index with halfvec_cosine_ops) |
| Security & Cryptography | PyJWT (RS256 2048-bit RSA), Cryptography (AES-256-GCM), Orthogonal Matrix Projection |
| Deployment & DevOps | Docker, Docker Compose, Nginx, AWS EC2 |
git clone https://github.com/hotrungtruc/CustomerLens.git
cd CustomerLens
# Launch Redis cache container
docker run -d --name customerlens-redis -p 6379:6379 redis:alpine
Create backend/.env configured with environment credentials:
USE_SUPABASE=true
SUPABASE_URL="postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres"
REDIS_URL="redis://127.0.0.1:6379/0"
KAFKA_BOOTSTRAP_SERVERS="127.0.0.1:9092"
Initialize the Python environment and launch the API Gateway:
cd backend
python -m venv .venv
# Activate virtual environment
# Windows: .\.venv\Scripts\Activate.ps1
# Linux/macOS: source .venv/bin/activate
pip install -r requirements.txt
# Initialize database schema and download pretrained ONNX models
python -m app.db.connection
python -m app.utils.download_models
# Start FastAPI Gateway
python run.py
Launch the asynchronous AI Worker in a separate terminal:
cd backend
source .venv/bin/activate
python app/ai_worker.py
cd frontend
npm install
npm run dev
Access the management console at http://localhost:3000 (Default credentials: admin / change_me_immediately).
To orchestrate the complete cluster via Docker Compose:
docker compose build
docker compose up -d
In-depth technical architecture and engineering specifications are organized within dedicated documents in the docs/ directory:
| Document | Topic & Focus Area |
|---|---|
| System Architecture | Distributed event-driven design, Redpanda ingestion, and Redis Pub/Sub topology. |
| AI Inference Pipeline | SCRFD detection, Kalman filter tracking, and Attention Pooling mathematics. |
| Database Schema | PostgreSQL schema definitions, HNSW vector indexing, and RPC procedures. |
| Frontend Architecture | Next.js 14 App Router, Canvas rendering loop, and WebSocket lifecycle management. |
| API Reference | Comprehensive specification of REST endpoints and WebSocket subprotocols. |
| Model Evaluation Guide | Step-by-step reproduction guide and statistical protocols for NIST FRVT and IJB-C evaluation. |
| Production Benchmark Report | Full tabular results and statistical analysis across all 544 YTF video sequences. |
| Maintenance Guide | Operational playbooks, systemd service management, and backup procedures. |
CustomerLens is authored by Ho Trung Truc for academic research and enterprise commercial deployment.
Privacy-first retail analytics: face embedding, customer revisit tracking, VIP recognition, demographic insights, and security alerts — fully self-hosted.
See the code
In high-touch hospitality, dining, and luxury retail environments, operational excellence and customer lifetime value (LTV) hinge on a single operational capability: timely customer recognition. Knowing whether an entering patron is a first-time visitor, a returning casual guest, or a high-value regular dictates the quality of service delivery:
However, traditional Customer Relationship Management (CRM) and loyalty programs suffer from high customer friction:
As a consequence, over 70% of physical guest interactions remain completely anonymous until checkout, leaving service staff uninformed and operational management blind to foot-traffic retention dynamics.
CustomerLens resolves this fundamental disconnect by transforming existing CCTV and security camera feeds into an ambient, zero-friction guest intelligence layer.
Patrons are not required to enroll, download an application, scan a barcode, or present identification. The system autonomously:
To support fast human interpretation during rush hours, CustomerLens classifies patrons into a dynamic 2-letter lifecycle taxonomy that automatically updates based on cumulative visit frequency and monetary transaction records:
stateDiagram-v2
direction LR
[*] --> LN: First Visit (New Guest)
LN --> LC: Visits 2 to 4 (Casual Guest)
LC --> LL: Visits >= 5 (Loyal Regular)
LL --> ML: Cumulative Spend >= 2,000,000 VND (Mass Loyal)
ML --> HL: Cumulative Spend >= 10,000,000 VND or VIP Flag (VIP Loyal)

H (High Tier): High-spending patrons ($\ge 10,000,000$ VND cumulative spend or designated VIP).M (Medium Tier): Mass loyal customers with steady ticket size ($\ge 2,000,000$ VND).L (Low / Standard Tier): Default baseline tier for standard or newly acquired patrons.N (New): First-time visitor (visit count $= 1$).C (Casual): Irregular visitor (visit count between $2$ and $4$).L (Loyal): Committed regular patron (visit count $\ge 5$).HL (High-Loyal) patron enters, enabling immediate host greetings and priority table assignment.CustomerLens is engineered as a distributed, event-driven streaming platform designed for horizontal scaling across multi-camera installations.

halfvec_cosine_ops) with binary parameter binding, backed by an in-memory Redis L1 cache for sub-millisecond retrieval of active patrons. Input Frame ──> [SCRFD 500M INT8] ──> [5-Point Affine Alignment] ──> [EdgeFace 512-D INT8]
│ │
▼ ▼
Kalman Tracking Quality Attention Pooling
(Corner Velocity) (Sharpness & Pose Weighted)
│ │
└──────────────────────┬─────────────────────────────┘
▼
Cancelable Biometrics
(Irreversible Orthogonal Matrix)
│
▼
Supabase HNSW Search
(K=3 Multi-Template)
Face detection is handled by an INT8-quantized SCRFD 500M model capable of localizing 5 facial landmarks (pupils, nose tip, mouth corners) across extreme pitch/yaw angles ($\pm 45^\circ$) down to a minimum bounding box of $16 \times 16$ pixels. Cropped faces are geometrically normalized into canonical ArcFace coordinate space ($112 \times 112 \times 3$) using similarity transformations, ensuring consistent orientation for subsequent feature extraction.
Normalized face crops are mapped into 512-dimensional unit feature embeddings using an INT8-quantized EdgeFace backbone.
To eliminate legal liability and strictly adhere to privacy frameworks (GDPR Article 9 and CCPA), CustomerLens implements distance-preserving Cancelable Biometrics:
Rather than naively averaging noisy video frames, CustomerLens aggregates multi-frame trajectories using an intelligent composite quality weighting mechanism:
The entire system was evaluated on real-world video sequences from the academic YouTube Faces (YTF) benchmark, specifically utilizing the curated Kaggle dataset release:
youtube_faces_with_keypoints_full_1).All video clips were evaluated across four real-world surveillance degradation conditions simulating physical camera distance:
close_1.5m: Native resolution, standard frontal entry camera.medium_3.5m: Optical downscale 0.60x, Gaussian blur $\sigma = 0.6$.far_6.0m: Optical downscale 0.38x, motion blur $\sigma = 1.2$, JPEG quality 55.veryFar_9m: Extreme optical downscale 0.22x, optical distortion $\sigma = 1.8$, JPEG quality 35.
Evaluating all genuine pairs (same identity, different video clips) against balanced impostor pairs (different identities):
| Camera Condition | Pair Count (Gen / Imp) | TAR @ FAR=0.1% | TAR @ FAR=0.01% | Equal Error Rate (EER) | AUC-ROC | Genuine Sim ($\mu \pm \sigma$) | Impostor Sim ($\mu \pm \sigma$) | Separation Margin |
|---|---|---|---|---|---|---|---|---|
close_1.5m | 511 / 1,533 | 93.15% | 92.76% | 4.50% | 0.9851 | $0.6370 \pm 0.1911$ | $0.0240 \pm 0.1042$ | +0.6129 |
medium_3.5m | 511 / 1,533 | 90.80% | 86.69% | 4.31% | 0.9845 | $0.6074 \pm 0.1954$ | $0.0160 \pm 0.1058$ | +0.5914 |
far_6.0m | 502 / 1,506 | 16.73% | 7.37% | 14.38% | 0.9325 | $0.4500 \pm 0.2054$ | $0.0657 \pm 0.1401$ | +0.3843 |
veryFar_9m | 331 / 993 | 2.11% | 2.11% | 32.33% | 0.7377 | $0.4526 \pm 0.2115$ | $0.2641 \pm 0.1990$ | +0.1884 |
At operational retail entry distances ($1.5\text{m} - 3.5\text{m}$), the system achieves an AUC-ROC of 0.985, an Equal Error Rate of 4.31%, and an impostor separation margin of +0.6129, confirming reliable distinction between genuine patrons and distinct individuals.
Evaluating identification across a gallery of $N = 206$ unique individuals (first clip per person), tested against 206 independent probe clips:
| Camera Condition | Gallery Size ($N$) | Rank-1 Identification | Rank-5 Identification | Rank-10 Identification |
|---|---|---|---|---|
close_1.5m | 206 | 90.78% | 92.72% | 93.20% |
medium_3.5m | 206 | 88.83% | 92.23% | 93.20% |
far_6.0m | 203 | 54.19% | 67.98% | 75.37% |
veryFar_9m | 138 | 18.84% | 36.96% | 44.20% |
In a closed gallery of 206 registered individuals, the system correctly identifies the target at position number one (Rank-1) in 90.78% of trials at close range and 88.83% at 3.5m range. Top-5 suggestion accuracy reaches 92.72%.
Simulating an authentic operational store scenario: the gallery contains only 155 registered loyalty members. The probe stream contains both 155 genuine returning members and 51 unregistered strangers (impostors):
| Camera Condition | Operating Threshold ($\theta$) | True Identification (DIR) | False Impostor Accept (FPIR) | False Patron Reject (FNIR) |
|---|---|---|---|---|
close_1.5m | $\theta = 0.50$ | 80.65% | 0.00% | 19.35% |
close_1.5m | $\theta = 0.44$ | 83.87% | 0.00% | 16.13% |
close_1.5m | $\theta = 0.40$ | 85.16% | 3.92% | 14.84% |
close_1.5m | $\theta = 0.35$ | 89.03% | 29.41% | 10.97% |
medium_3.5m | $\theta = 0.46$ | 79.35% | 1.96% | 20.65% |
medium_3.5m | $\theta = 0.44$ | 80.65% | 1.96% | 19.35% |
medium_3.5m | $\theta = 0.40$ | 84.52% | 5.88% | 15.48% |
far_6.0m | $\theta = 0.40$ | 47.06% | 56.86% | 52.94% |
Recommended Production Operating Point: Setting $\theta = 0.44$ yields 83.87% correct identification while maintaining 0.00% False Positive Identification Rate (zero impostors accepted).
Executing 500 consecutive 512-dimensional vector queries against the live Supabase PostgreSQL HNSW index under concurrent load:

| Infrastructure Metric | Observed Result | Production Target SLO | Evaluation Status |
|---|---|---|---|
| P50 Latency (Median) | 58.17 ms | < 60 ms | Compliant |
| P95 Latency | 62.73 ms | < 80 ms | Compliant |
| P99 Latency (Tail) | 73.82 ms | < 100 ms | Compliant (26% safety margin) |
| P99.9 Latency | 110.37 ms | < 150 ms | Compliant |
| Maximum Observed Latency | 142.84 ms | — | Stable |
| Sustained Query Throughput | 16.9 QPS | $\ge$ 10 QPS | Compliant (+69% headroom) |
The complete single-frame inference pipeline (Detection + Alignment + Embedding + Tracking) executes in 32.29 ms (equivalent to 30.34 FPS), fully sustaining real-time processing of standard 25–30 FPS RTSP cameras.
CustomerLens is designed to comply with privacy frameworks including GDPR Article 9 (Special Category Biometric Data) and GDPR Article 17 (Right to be Forgotten):
user_revoked_at:{user_id}) terminate credentials immediately across all cluster nodes upon logout or administrative disablement.| Layer | Technologies & Frameworks |
|---|---|
| Frontend UI | Next.js 14 (App Router), React 18, Tailwind CSS, HTML5 Canvas API |
| API Gateway | FastAPI, Uvicorn, Python 3.12, asyncio, WebSockets |
| Event Messaging | Redpanda (Apache Kafka v2.8+ wire compatible), Redis Pub/Sub |
| AI Inference Engine | ONNX Runtime INT8, EdgeFace, SCRFD 500M, OpenCV, NumPy, SciPy |
| Database & Vector Search | PostgreSQL 15+, Supabase, pgvector (HNSW Index with halfvec_cosine_ops) |
| Security & Cryptography | PyJWT (RS256 2048-bit RSA), Cryptography (AES-256-GCM), Orthogonal Matrix Projection |
| Deployment & DevOps | Docker, Docker Compose, Nginx, AWS EC2 |
git clone https://github.com/hotrungtruc/CustomerLens.git
cd CustomerLens
# Launch Redis cache container
docker run -d --name customerlens-redis -p 6379:6379 redis:alpine
Create backend/.env configured with environment credentials:
USE_SUPABASE=true
SUPABASE_URL="postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres"
REDIS_URL="redis://127.0.0.1:6379/0"
KAFKA_BOOTSTRAP_SERVERS="127.0.0.1:9092"
Initialize the Python environment and launch the API Gateway:
cd backend
python -m venv .venv
# Activate virtual environment
# Windows: .\.venv\Scripts\Activate.ps1
# Linux/macOS: source .venv/bin/activate
pip install -r requirements.txt
# Initialize database schema and download pretrained ONNX models
python -m app.db.connection
python -m app.utils.download_models
# Start FastAPI Gateway
python run.py
Launch the asynchronous AI Worker in a separate terminal:
cd backend
source .venv/bin/activate
python app/ai_worker.py
cd frontend
npm install
npm run dev
Access the management console at http://localhost:3000 (Default credentials: admin / change_me_immediately).
To orchestrate the complete cluster via Docker Compose:
docker compose build
docker compose up -d
In-depth technical architecture and engineering specifications are organized within dedicated documents in the docs/ directory:
| Document | Topic & Focus Area |
|---|---|
| System Architecture | Distributed event-driven design, Redpanda ingestion, and Redis Pub/Sub topology. |
| AI Inference Pipeline | SCRFD detection, Kalman filter tracking, and Attention Pooling mathematics. |
| Database Schema | PostgreSQL schema definitions, HNSW vector indexing, and RPC procedures. |
| Frontend Architecture | Next.js 14 App Router, Canvas rendering loop, and WebSocket lifecycle management. |
| API Reference | Comprehensive specification of REST endpoints and WebSocket subprotocols. |
| Model Evaluation Guide | Step-by-step reproduction guide and statistical protocols for NIST FRVT and IJB-C evaluation. |
| Production Benchmark Report | Full tabular results and statistical analysis across all 544 YTF video sequences. |
| Maintenance Guide | Operational playbooks, systemd service management, and backup procedures. |
CustomerLens is authored by Ho Trung Truc for academic research and enterprise commercial deployment.