Skip to content

Feat: Allow Manual Deletion of Face Clusters #1177

@codex-yv

Description

@codex-yv

Describe the feature

Description

Inside the AI Tagging section of PictoPy, there should be an option to delete specific Face Clusters so that users can remove unwanted Face Clusters. Currently, no such option is available.

Current Problem

  • No option to delete or hide specific automatically generated face clusters.
  • In my previous attempts of deletion (setting cluster_id to NULL) would have been resulted in re-discover and re-display the same unwanted group during the next 24-hour full reclustering cycle.

Expected Solution

  • Users should be able to remove Face Clusters.
  • A Delete button should be visible when a user opens any Face Cluster.
  • Concept of Soft Deletion.

Implementation

Backend

1. Database Schema Enhancements

Added a column is_deleted to both tables face_clusters and faces to enable "Soft Delete" logic.

  • face_clusters table: Added is_deleted BOOLEAN DEFAULT FALSE.
  • faces table: Added is_deleted BOOLEAN DEFAULT FALSE.

2. Implementation Logic

Soft Delete Operation

The system now executes a transaction-safe update rather than deleting rows permanently. This hides it from the user while maintaining the internal grouping data for the AI.

# Updated deletion logic in db_delete_cluster_by_cluster_id
cursor.execute("UPDATE faces SET is_deleted = TRUE WHERE cluster_id = ?")
cursor.execute("UPDATE face_clusters SET is_deleted = TRUE WHERE cluster_id = ?")

Majority Voting (Reclustering Logic)

This is the main concept. When full reclustering occurs (every 24 hours):

  1. The system creates brand new clusters for all faces.
  2. For each new cluster, it checks the previous is_deleted status of its constituent faces.
  3. Inheritance: If a majority of faces in a new cluster were previously marked as deleted, the new cluster automatically inherits is_deleted = TRUE.
  4. This ensures that manually hidden people stay hidden even if the underlying cluster_id changes.

When fetching clusters

The retrieval endpoints are updated to automatically exclude clusters marked with the is_deleted flag:

# API Logic
clusters = [c for c in clusters_data if not c.get("is_deleted", False)]
  • Frontend
    • UI: Added Delete Button and defined handleDeleteCluster

      import { Check, Pencil, ArrowLeft, Trash2 } from 'lucide-react';
      <Button
          variant="outline"
          onClick={handleDeleteCluster}
          className="flex cursor-pointer items-center gap-2 border-red-200 text-red-600 hover:bg-red-50 hover:text-red-700"
      >
          <Trash2 className="h-4 w-4" />
          Delete Cluster
      </Button>
    • API Route: Added DELETE /face-clusters/delete-cluster/${clusterId} in apiEndpoint.ts

    • Response Handling: The message from the backend is displayed regardless of the success status, ensuring the user sees the specific feedback provided by the server.

    • Lint Fix: Ensured the mutation call is type-safe by passing undefined for operations requiring no payload.

Add ScreenShots

Screenshots

Delete Endpoint working properly.

Image

Delete Button not available (Before)

Image

Delete Button now available (After)

Image

Demo video (After)

demo1.mp4

Tests Performed

test_face_clusters.py

Image

test_albums.py

Image

test_folders.py

Image

test_user_preferences.py

Image

Record

  • I agree to follow this project's Code of Conduct
  • I want to work on this issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions