<jupyter_start><jupyter_text>**Follow these Steps to reach the Streamlit Web App (with this google colab notebook as the backend)** :>  **1)** *In the above Menu bar, choose Runtime -> Change Runtime type -> Hardware Accelerator -> GPU -> Save*>  **2)** *Run the below 3 cells sequentially. A reminder appears as the notebook is located in a GitHub Repository instead of your Drive, Click on "Run Anyway".*>  **3)** *Click on the URL (eg: ...loca.it) produced as output by the last cell while the last cell continues to run here.*>  **4)** *On opening the URL, a Friendly Reminder is shown informing that this website is being hosted by a localtunnel; click on "Click to Continue" because we know exactly who is hosting the website: our own Google Colab notebook.*>  **5)** *And... you have landed on the Streamlit App; sometimes it might show "Please Wait..." for a long time before the app comes live... just wait and keep this collab notebook and the web app running.* **OR**, download the notebook code and run the Streamlit Web App on your local machine.**Feel free to interact with the web app... Upload images of several faces (make sure to upload atleast 3 images containing the same face)... or you can choose to use the *Unlabelled_test_images* by downloading the folder and then uploading the images to the Web App to experience how the project works.**<jupyter_code>!pip install face_recognition
!pip install -q streamlit
# If ipykernel & ipython version related warnings are shown while installing streamlit: IGNORE
%%writefile streamlit-app.py

import os
import time
import shutil
import tempfile
import numpy as np
import streamlit as st

import cv2
import face_recognition
from sklearn.cluster import DBSCAN
from imutils import build_montages

flag1 = 0

st.set_page_config(layout = 'wide')

#st.title("Any Face Clustering")
st.markdown("<h1 style='text-align: center; color: grey;'>Any Face Clustering</h1>", unsafe_allow_html=True)

st.text(" ")
st.text("Upload Images of Multiple Faces (with AT LEAST 3 images of a particular face).")
st.text("Please wait a while after uploading the images until you see a dialog box stating that the images were uploaded successfully.")
st.text("Sometimes Streamlit takes unusually more time to upload the images... if failed, try compressing the images before uploading.")

uploaded_files = st.file_uploader("", type = ["png","jpg","jpeg"], accept_multiple_files = True)

no_of_files = len(uploaded_files)

if no_of_files > 0:
  placeholder = st.empty()
  placeholder.success("{} Images uploaded successfully!".format(no_of_files))
  time.sleep(3)
  placeholder.empty()
  data = []
  
  for f in uploaded_files:
    tfile = tempfile.NamedTemporaryFile(delete = False)
    tfile.write(f.read())
    image = cv2.imread(tfile.name)
    rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    boxes = face_recognition.face_locations(rgb, model = "cnn")
    encodings = face_recognition.face_encodings(rgb, boxes)
    d = [{"imagePath": tfile.name, "loc": box, "encoding": enc} for (box, enc) in zip(boxes, encodings)]
    data.extend(d)
  
  # converting the data into a numpy array
  data_arr = np.array(data)
  # extracting the 128-d facial encodings and placing them in a list
  encodings_arr = [item["encoding"] for item in data_arr]

  # initializing and fitting the clustering model on the encoded data
  cluster = DBSCAN(min_samples = 3)
  cluster.fit(encodings_arr)
  st.balloons()
  
  labelIDs = np.unique(cluster.labels_)
  numUniqueFaces = len(np.where(labelIDs > -1)[0])
  
  st.subheader("Number of unique faces identified (excluding the unknown faces) is: " + str(numUniqueFaces))

  if flag1 == 0:
    cols1 = st.columns(numUniqueFaces + 1)
    flag1 = 1

  # loop over the unique face integers
  for labelID in labelIDs:
    idxs = np.where(cluster.labels_ == labelID)[0]
    idxs = np.random.choice(idxs, size = min(15, len(idxs)), replace = False)
    # initializing the list of faces to include in the montage
    faces = []
    # initializing the list of whole_images to include in the zip files of each faces, to be downloaded by the user
    whole_images = []
    
    if labelID != -1:
      dir_name = 'face#{}'.format(labelID + 1)
      os.mkdir(dir_name)

    for i in idxs:
      current_image = cv2.imread(data_arr[i]["imagePath"])
      rgb_current_image = cv2.cvtColor(current_image, cv2.COLOR_BGR2RGB)
      (top, right, bottom, left) = data_arr[i]["loc"]
      current_face = rgb_current_image[top:bottom, left:right]
      current_face = cv2.resize(current_face, (96, 96))
      whole_images.append(rgb_current_image)
      faces.append(current_face)

      if labelID != -1:
        face_image_name = 'image{}.jpg'.format(i)
        cv2.imwrite(os.path.join(dir_name, face_image_name), current_image)
    
    if labelID != -1:
      shutil.make_archive('zip_face#{}'.format(labelID + 1), 'zip', dir_name)
      # deleting the directory and image files contained in it as we need only the zip file which has been created already
      shutil.rmtree('face#{}'.format(labelID + 1))
      
    montage = build_montages(faces, (96, 96), (3, 3))[0]

    current_title = "Face #{}:".format(labelID + 1)
    expander_caption = "Images with Face #{}:".format(labelID + 1)
    current_title = "Unknown:" if labelID == -1 else current_title

    with cols1[labelID + 1]:
      st.write(current_title)
      st.image(montage)
    if labelID != -1:
      with st.expander(expander_caption):
        # displaying the images of the current face
        cols2 = st.columns(3)
        for j in range(len(whole_images)):
          with cols2[j%3]:
            st.image(whole_images[j], use_column_width = 'always')
        # providing an option for the user to download folders with images of particular faces after clustering as zip files
        with open("zip_face#{}.zip".format(labelID + 1), "rb") as fp:
          btn = st.download_button(
              label="Download ZIP of Clustered Images with Face #{}".format(labelID + 1),
              data=fp,
              file_name="clustered_faces#{}.zip".format(labelID + 1),
              mime="application/zip"
          )
        fp.close()
!streamlit run streamlit-app.py & npx localtunnel --port 8501 --server.enableCORS=false --server.enableXsrfProtection=false<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10583016476552598, 'fraction_numerical': 0.011723700887198986, 'mean_word_length': 3.711194029850746, 'pattern_counts': {'":': 3, '<': 7, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '288254', 'license': 'MIT', 'n_tokens_mistral': 1982, 'n_tokens_neox': 1898, 'n_words': 678, 'path': 'Any_Face_Clustering_Streamlit_app.ipynb', 'repo_name': 'souvikmajumder26/Any-Face-Clustering', 'size': '6312'}