Data model classes for storing face embeddings, person records, and recognition performance metrics.
FaceImageRecord
Entity class for storing face embeddings with vector search indexing.
@Entity
data class FaceImageRecord(
@Id var recordID: Long = 0,
@Index var personID: Long = 0,
var personName: String = "",
@HnswIndex(
dimensions = 512,
distanceType = VectorDistanceType.COSINE
) var faceEmbedding: FloatArray = floatArrayOf()
)
Fields
Primary key of the face image record, auto-generated by ObjectBox
Foreign key reference to PersonRecord. Indexed for efficient queries by person
Name of the person for quick access without joining PersonRecord
faceEmbedding
FloatArray
default:"floatArrayOf()"
512-dimensional face embedding vector from FaceNet model. Indexed with HNSW for efficient vector similarity search using cosine distance
Vector indexing
The faceEmbedding field uses HNSW (Hierarchical Navigable Small World) indexing:
Vector dimensionality matching FaceNet-512 model output
distanceType
VectorDistanceType
default:"COSINE"
Cosine distance metric for measuring similarity between embeddings
Usage example
// Create and store a face record
val embedding = faceNet.getFaceEmbedding(croppedFaceBitmap)
val record = FaceImageRecord(
personID = 123,
personName = "John Doe",
faceEmbedding = embedding
)
imagesVectorDB.addFaceImageRecord(record)
// Query by person ID
val personFaces = imagesBox
.query(FaceImageRecord_.personID.equal(personID))
.build()
.find()
PersonRecord
Entity class for storing person metadata and tracking enrolled faces.
@Entity
data class PersonRecord(
@Id var personID: Long = 0,
var personName: String = "",
var numImages: Long = 0,
var addTime: Long = 0
)
Fields
Primary key of the person record, auto-generated by ObjectBox
Number of face images enrolled for this person. Used for tracking enrollment completeness
Timestamp (in milliseconds) when the person was added to the database
Usage example
// Create a new person
val person = PersonRecord(
personName = "John Doe",
numImages = 0,
addTime = System.currentTimeMillis()
)
val personID = personBox.put(person)
// Update image count after enrolling faces
person.numImages = 5
personBox.put(person)
// Query all persons sorted by name
val allPersons = personBox
.query()
.order(PersonRecord_.personName)
.build()
.find()
RecognitionMetrics
Data class for tracking face recognition pipeline performance metrics.
data class RecognitionMetrics(
val timeFaceDetection: Long,
val timeVectorSearch: Long,
val timeFaceEmbedding: Long,
val timeFaceSpoofDetection: Long
)
Fields
Time in milliseconds for face detection step
Time in milliseconds for vector database nearest neighbor search
Time in milliseconds for FaceNet embedding generation
Time in milliseconds for face spoof/liveness detection
Usage example
// Metrics are automatically collected during recognition
val (metrics, results) = imageVectorUseCase.getNearestPersonName(
frameBitmap = cameraBitmap,
flatSearch = false
)
if (metrics != null) {
println("Face Detection: ${metrics.timeFaceDetection}ms")
println("Embedding Generation: ${metrics.timeFaceEmbedding}ms")
println("Vector Search: ${metrics.timeVectorSearch}ms")
println("Spoof Detection: ${metrics.timeFaceSpoofDetection}ms")
val totalTime = metrics.timeFaceDetection +
metrics.timeFaceEmbedding +
metrics.timeVectorSearch +
metrics.timeFaceSpoofDetection
println("Total: ${totalTime}ms")
}
Pipeline stages
The metrics correspond to the face recognition pipeline stages:
- Face detection: Detect and crop faces from camera frame
- Face embedding: Generate 512-dimensional vectors using FaceNet
- Vector search: Find nearest neighbor in database
- Spoof detection: Detect presentation attacks
Metrics are averaged when multiple faces are detected in a frame:
val metrics = RecognitionMetrics(
timeFaceDetection = t1.toLong(DurationUnit.MILLISECONDS),
timeFaceEmbedding = avgT2 / faceDetectionResult.size,
timeVectorSearch = avgT3 / faceDetectionResult.size,
timeFaceSpoofDetection = avgT4 / faceDetectionResult.size
)
Source: data/DataModels.kt