Skip to content

Feature identity recognition 2100793612207388938#155

Closed
harrydbarnes wants to merge 13 commits into
mainfrom
feature-identity-recognition-2100793612207388938
Closed

Feature identity recognition 2100793612207388938#155
harrydbarnes wants to merge 13 commits into
mainfrom
feature-identity-recognition-2100793612207388938

Conversation

@harrydbarnes

Copy link
Copy Markdown
Owner

No description provided.

google-labs-jules Bot and others added 13 commits January 27, 2026 13:56
This change introduces face recognition capabilities to track specific people across project photos.
- Added TensorFlow Lite dependencies and a dummy MobileFaceNet model.
- Created `FaceRecognitionHelper` to generate face embeddings.
- Updated `ProjectEntity` and database schema to store target embeddings.
- Enhanced `ProjectViewModel` to support "Track This Person" and smart re-alignment using cosine similarity.
- Updated UI to expose the new tracking feature.
- Optimized threading (Dispatchers.Default/IO) and memory management (Bitmap recycling) for heavy TFLite operations.

Co-authored-by: harrydbarnes <145344818+harrydbarnes@users.noreply.github.com>
This change introduces face recognition capabilities to track specific people across project photos.
- Added TensorFlow Lite dependencies and a dummy MobileFaceNet model.
- Created `FaceRecognitionHelper` to generate face embeddings.
- Updated `ProjectEntity` and database schema to store target embeddings.
- Enhanced `ProjectViewModel` to support "Track This Person" and smart re-alignment using cosine similarity.
- Updated UI to expose the new tracking feature.
- Optimized threading (Dispatchers.Default/IO) and memory management (Bitmap recycling, single load per photo) for heavy TFLite operations.
- Refactored `FaceDetectorHelper` to support bitmap input for efficiency.

Co-authored-by: harrydbarnes <145344818+harrydbarnes@users.noreply.github.com>
This change addresses review feedback by fixing a syntax error, preventing memory leaks, optimizing embedding storage, and improving code readability.
- Fixed syntax error in `ProjectViewModel.kt` (extra brace).
- Implemented `close()` in `FaceRecognitionHelper` and ensured `GpuDelegate` is closed to prevent memory leaks.
- Optimized embedding storage: Changed `targetEmbedding` from String to BLOB (ByteArray) in Entity and Database, using `ByteBuffer` for efficient FloatArray conversion. Updated `MIGRATION_4_5`.
- Refactored `ProjectViewModel.kt`: Split `processFacesInternal` into `processFacesWithTarget` and `processFacesSpatial` for better readability and maintainability.
- Updated `Project` domain model to use `FloatArray` for embeddings.

Co-authored-by: harrydbarnes <145344818+harrydbarnes@users.noreply.github.com>
This update addresses critical review feedback by fixing syntax errors, optimizing performance, and ensuring thread safety.
- Fixed `ProjectViewModel` syntax (removed extra brace).
- Refactored `FaceRecognitionHelper` to include a thread-safe `suspend fun close()` using `Mutex` for proper cleanup of TFLite resources.
- Optimized database storage by switching `targetEmbedding` to `BLOB` (ByteArray) using `ByteBuffer`, replacing inefficient String storage. Updated migrations and mappers.
- Parallelized face processing in `ProjectViewModel` using `coroutineScope` and `async/awaitAll` for improved performance on large datasets.
- Refactored logic into `processFacesWithTarget` and `processFacesSpatial` for better readability.
- Corrected status handling to ensure failed photo loads do not mark photos as processed.

Co-authored-by: harrydbarnes <145344818+harrydbarnes@users.noreply.github.com>
This update addresses critical review feedback by fixing syntax errors, optimizing performance, and ensuring thread safety.
- Fixed `ProjectViewModel` syntax (removed extra brace).
- Refactored `FaceRecognitionHelper` to include a thread-safe `suspend fun close()` using `Mutex` for proper cleanup of TFLite resources.
- Optimized database storage by switching `targetEmbedding` to `BLOB` (ByteArray) using `ByteBuffer`, replacing inefficient String storage. Updated migrations and mappers.
- Parallelized face processing in `ProjectViewModel` using `coroutineScope` and `async/awaitAll` with a `Semaphore(4)` to improve performance on large datasets while preventing OOM.
- Refactored logic into `processFacesWithTarget` and `processFacesSpatial` for better readability.
- Corrected status handling to ensure failed photo loads do not mark photos as processed.
- Removed `@Singleton` from `FaceRecognitionHelper` and implemented cleanup in `ProjectViewModel.onCleared()`.

Co-authored-by: harrydbarnes <145344818+harrydbarnes@users.noreply.github.com>
This update addresses critical review feedback by fixing syntax errors, optimizing performance, and ensuring thread safety.
- Fixed `ProjectViewModel` syntax (removed extra brace).
- Refactored `FaceRecognitionHelper` to include a thread-safe `suspend fun close()` using `Mutex` for proper cleanup of TFLite resources.
- Optimized database storage by switching `targetEmbedding` to `BLOB` (ByteArray) using `ByteBuffer`, replacing inefficient String storage. Updated migrations and mappers.
- Parallelized face processing in `ProjectViewModel` using `coroutineScope` and `async/awaitAll` with a `Semaphore(4)` to improve performance on large datasets while preventing OOM.
- Refactored logic into `processFacesWithTarget` and `processFacesSpatial` for better readability.
- Corrected status handling to ensure failed photo loads do not mark photos as processed.
- Removed `@Singleton` from `FaceRecognitionHelper` and implemented cleanup in `ProjectViewModel.onCleared()`.
- Replaced `semaphore.withPermit` with `acquire`/`release` to support suspending calls.
- Fixed `processFacesSpatial` loop compilation error.

Co-authored-by: harrydbarnes <145344818+harrydbarnes@users.noreply.github.com>
This update addresses critical review feedback by fixing syntax errors, optimizing performance, and ensuring thread safety.
- Fixed `ProjectViewModel` syntax (removed extra brace).
- Refactored `FaceRecognitionHelper` to include a thread-safe `suspend fun close()` using `Mutex` for proper cleanup of TFLite resources.
- Optimized database storage by switching `targetEmbedding` to `BLOB` (ByteArray) using `ByteBuffer`, replacing inefficient String storage. Updated migrations and mappers.
- Parallelized face processing in `ProjectViewModel` using `coroutineScope` and `async/awaitAll` with a `Semaphore(4)` to improve performance on large datasets while preventing OOM.
- Refactored logic into `processFacesWithTarget` and `processFacesSpatial` for better readability.
- Corrected status handling to ensure failed photo loads do not mark photos as processed.
- Removed `@Singleton` from `FaceRecognitionHelper` and implemented cleanup in `ProjectViewModel.onCleared()`.
- Replaced `semaphore.withPermit` with `acquire`/`release` to support suspending calls.
- Fixed `processFacesSpatial` loop compilation error.
- Fixed initialization race condition in `FaceRecognitionHelper`.
- Used `runBlocking` in `onCleared` to ensure TFLite cleanup.
- Ensured loading state is reset when project data is missing.

Co-authored-by: harrydbarnes <145344818+harrydbarnes@users.noreply.github.com>
…l.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…l.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…l.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…reen.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…er.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This update fixes the specific build errors reported in the previous run:
- Defined `NUM_CPU_THREADS` in `FaceRecognitionHelper.kt` and used it.
- Defined `MAX_CONCURRENT_FACE_PROCESSING` in `ProjectViewModel.kt` and used it.
- Added `action_re_align_smart` to `strings.xml` and updated `ProjectDetailScreen.kt` to use it.
- Verified compilation with `./gradlew assembleDebug`.

This builds upon previous optimizations for memory, concurrency, and storage.

Co-authored-by: harrydbarnes <145344818+harrydbarnes@users.noreply.github.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @harrydbarnes, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the face alignment feature by introducing identity recognition capabilities. By leveraging TensorFlow Lite, users can now select a specific face to track, ensuring that the alignment process focuses on that individual throughout a project. This provides a more accurate and user-controlled method for generating time-lapse videos, moving beyond simple spatial face detection to intelligent person tracking.

Highlights

  • TensorFlow Lite Integration: Integrated TensorFlow Lite dependencies and a dummy model (mobilefacenet.tflite) to enable on-device face recognition capabilities.
  • Face Recognition Helper: Introduced a new FaceRecognitionHelper class responsible for initializing the TFLite interpreter, generating face embeddings from detected faces, and calculating cosine similarity between embeddings. It supports GPU delegation for performance.
  • Target Person Tracking: Implemented the ability to select a 'target person' from a photo. The embedding of this selected face is stored, allowing subsequent face alignment processes to prioritize tracking this specific individual across all project photos.
  • Dynamic Face Alignment Logic: Refactored the face processing logic in ProjectViewModel to dynamically choose between two alignment strategies: the existing spatial tracking (largest face or closest to previous frame) or a new identity-based tracking using the target person's embedding and cosine similarity.
  • Database and UI Updates: Updated the ProjectEntity and Project models to include a targetEmbedding field, along with a Room database migration (4->5) to persist this data. The UI now reflects the new 'Track Person' option and dynamically changes the 'Align Faces' button to 'Re-align (Smart)' when a target is set.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces identity recognition for face tracking, leveraging TensorFlow Lite for on-device inference and a new FaceRecognitionHelper to generate embeddings, alongside updates to the database schema and view model logic. While the changes are well-structured, there are critical security and stability concerns: the unencrypted storage of biometric data (face embeddings) and a potential app crash due to improper bitmap recycling logic. Additionally, a logic issue exists in the updated spatial processing, and unnecessary files are included in the pull request.

val aspectRatio: String = Project.DEFAULT_ASPECT_RATIO
)
val aspectRatio: String = Project.DEFAULT_ASPECT_RATIO,
val targetEmbedding: ByteArray? = null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The application stores face embeddings (biometric data) in the targetEmbedding field, which is persisted in a local Room database. Biometric templates are sensitive personal data. Storing them unencrypted poses a privacy risk if the device's storage is accessed by an unauthorized party. Consider using an encrypted database like SQLCipher or encrypting this specific field before storage.

Comment on lines +95 to +97
}
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Potential app crash due to improper bitmap recycling. Bitmap.createBitmap may return the source bitmap instance if the requested subset matches the source dimensions. In such cases, calling cropped.recycle() will also recycle the source bitmap, leading to an IllegalStateException when the source bitmap is accessed again (e.g., in the processing loop in ProjectViewModel).

if (cropped != null && cropped != bitmap && !cropped.isRecycled) {
    cropped.recycle()
}

@@ -0,0 +1 @@
dummy model No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This appears to be a dummy placeholder file for the TFLite model. Committing a text file with the content "dummy model" instead of a binary .tflite file can cause issues with asset packaging and loading at runtime. It's recommended to either remove this placeholder and add the real model in a subsequent PR, or replace it with a minimal but valid TFLite model file. If this file is for local testing only, it should be added to .gitignore.

Comment on lines +393 to 395
if (!photo.isProcessed) {
repository.updatePhoto(photo.copy(isProcessed = false))
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for handling cases where no face is found in processFacesSpatial seems inconsistent and inefficient.

  1. If photo.isProcessed is false, this code results in a redundant database write, updating the photo with isProcessed = false when that's already its state.
  2. If photo.isProcessed is true (e.g., from a manual selection), this block does nothing, leaving the photo marked as processed even though the algorithm didn't find a face.

This is inconsistent with processFacesWithTarget, which correctly marks the photo as unprocessed in this scenario. To ensure consistent behavior and avoid unnecessary database operations, it would be better to unconditionally set isProcessed to false when no face is found.

                    repository.updatePhoto(photo.copy(isProcessed = false))


override fun onCleared() {
super.onCleared()
kotlinx.coroutines.runBlocking {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using runBlocking in onCleared is acceptable for running suspend functions during ViewModel cleanup. However, using the fully qualified name kotlinx.coroutines.runBlocking is a bit verbose. It would be cleaner to add import kotlinx.coroutines.runBlocking at the top of the file.

        runBlocking {

Comment thread build_output.txt
@@ -0,0 +1,51 @@
Configuration on demand is an incubating feature.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Build output files should not be committed to the version control system. These files are generated locally and can vary between machines and builds, leading to unnecessary merge conflicts and repository bloat. Please remove this file from the pull request and add *.txt (or a more specific pattern like build_output*.txt) to your .gitignore file.

Comment thread build_output_2.txt
@@ -0,0 +1,51 @@
Configuration on demand is an incubating feature.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Build output files should not be committed to the version control system. These files are generated locally and can vary between machines and builds, leading to unnecessary merge conflicts and repository bloat. Please remove this file from the pull request and ensure your .gitignore file is configured to exclude them.

Comment thread build_output_3.txt
@@ -0,0 +1,51 @@
Configuration on demand is an incubating feature.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Build output files should not be committed to the version control system. These files are generated locally and can vary between machines and builds, leading to unnecessary merge conflicts and repository bloat. Please remove this file from the pull request and ensure your .gitignore file is configured to exclude them.

Comment thread build_output_final.txt
@@ -0,0 +1,51 @@
Configuration on demand is an incubating feature.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Build output files should not be committed to the version control system. These files are generated locally and can vary between machines and builds, leading to unnecessary merge conflicts and repository bloat. Please remove this file from the pull request and ensure your .gitignore file is configured to exclude them.

Comment thread count_braces.py
@@ -0,0 +1,17 @@
with open('app/src/main/java/com/facelapse/app/ui/project/ProjectViewModel.kt', 'r') as f:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This Python script appears to be a temporary debugging or utility tool. Such files should generally not be part of the main application's source history. If it's a one-off script, please remove it. If it's a tool that other developers might find useful, consider moving it to a dedicated scripts/ or tools/ directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant