mirror of
https://github.com/vale46n1/immich_duplicate_finder.git
synced 2025-12-13 20:35:46 +01:00
Code revision
This commit is contained in:
31
api.py
31
api.py
@@ -4,9 +4,10 @@ from PIL import Image, UnidentifiedImageError, ImageFile
|
||||
from io import BytesIO
|
||||
from db import bytes_to_megabytes
|
||||
from pillow_heif import register_heif_opener
|
||||
import os
|
||||
|
||||
@st.cache_data(show_spinner=True)
|
||||
def fetchAssets(immich_server_url, api_key, timeout):
|
||||
def fetchAssets(immich_server_url, api_key, timeout, type):
|
||||
# Initialize messaging and progress
|
||||
if 'fetch_message' not in st.session_state:
|
||||
st.session_state['fetch_message'] = ""
|
||||
@@ -29,7 +30,7 @@ def fetchAssets(immich_server_url, api_key, timeout):
|
||||
if 'application/json' in content_type:
|
||||
if response.text:
|
||||
assets = response.json() # Decode JSON response into a list of assets
|
||||
assets = [asset for asset in assets if asset.get("type") == "IMAGE"]
|
||||
assets = [asset for asset in assets if asset.get("type") == type]
|
||||
st.session_state['fetch_message'] = 'Assets fetched successfully!'
|
||||
else:
|
||||
st.session_state['fetch_message'] = 'Received an empty response.'
|
||||
@@ -53,8 +54,7 @@ def fetchAssets(immich_server_url, api_key, timeout):
|
||||
message_placeholder.text(st.session_state['fetch_message'])
|
||||
return assets
|
||||
|
||||
#@st.cache_data(show_spinner=True)
|
||||
def streamAsset(asset_id, immich_server_url,photo_choice,api_key):
|
||||
def getImage(asset_id, immich_server_url,photo_choice,api_key):
|
||||
# Determine whether to fetch the original or thumbnail based on user selection
|
||||
register_heif_opener()
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
@@ -183,4 +183,25 @@ def updateAsset(immich_server_url, asset_id, api_key, dateTimeOriginal, descript
|
||||
except requests.RequestException as e:
|
||||
st.error(f"Request failed: {str(e)}")
|
||||
print(f"Request failed: {str(e)}")
|
||||
return False
|
||||
return False
|
||||
|
||||
#For video function
|
||||
def getVideoAndSave(asset_id, immich_server_url,api_key,save_directory):
|
||||
# Ensure the directory exists
|
||||
if not os.path.exists(save_directory):
|
||||
os.makedirs(save_directory)
|
||||
|
||||
response = requests.get(f"{immich_server_url}/api/download/asset/{asset_id}", headers={'Accept': 'application/octet-stream', 'x-api-key': api_key}, stream=True)
|
||||
file_path = os.path.join(save_directory, f"{asset_id}.mp4")
|
||||
|
||||
if response.status_code == 200 and 'video/' in response.headers.get('Content-Type', ''):
|
||||
try:
|
||||
with open(file_path, 'wb') as f:
|
||||
f.write(response.content)
|
||||
return file_path
|
||||
except Exception as e:
|
||||
print(f"Failed to save video for asset_id {asset_id}. Error: {e}")
|
||||
return None
|
||||
else:
|
||||
print(f"Failed to retrieve video for asset_id {asset_id}. Status Code: {response.status_code}, Content-Type: {response.headers.get('Content-Type')}")
|
||||
return None
|
||||
3
app.py
3
app.py
@@ -91,13 +91,14 @@ def configure_sidebar():
|
||||
st.markdown(f"**Version:** {program_version}\n\n{additional_data}")
|
||||
|
||||
def main():
|
||||
#print(fetchAssets(immich_server_url, api_key,timeout, 'VIDEO'))
|
||||
setup_session_state()
|
||||
configure_sidebar()
|
||||
assets = None
|
||||
|
||||
# Attempt to fetch assets if any asset-related operation is to be performed
|
||||
if st.session_state['calculate_faiss'] or st.session_state['generate_db_duplicate'] or st.session_state['show_faiss_duplicate']:
|
||||
assets = fetchAssets(immich_server_url, api_key,timeout)
|
||||
assets = fetchAssets(immich_server_url, api_key,timeout, 'IMAGE')
|
||||
if not assets:
|
||||
st.error("No assets found or failed to fetch assets.")
|
||||
return # Stop further execution since there are no assets to process
|
||||
|
||||
@@ -8,7 +8,7 @@ import faiss
|
||||
from torchvision.models import resnet152, ResNet152_Weights
|
||||
from torchvision.transforms import Compose, Resize, ToTensor, Normalize
|
||||
|
||||
from api import streamAsset
|
||||
from api import getImage
|
||||
from utility import display_asset_column
|
||||
from api import getAssetInfo
|
||||
from db import load_duplicate_pairs, is_db_populated, save_duplicate_pair
|
||||
@@ -63,7 +63,7 @@ def update_faiss_index(immich_server_url,api_key, asset_id):
|
||||
if asset_id in existing_metadata:
|
||||
return 'skipped' # Skip processing this image
|
||||
|
||||
image = streamAsset(asset_id, immich_server_url, "Thumbnail (fast)", api_key)
|
||||
image = getImage(asset_id, immich_server_url, "Thumbnail (fast)", api_key)
|
||||
if image is not None:
|
||||
features = extract_features(image)
|
||||
else:
|
||||
@@ -216,9 +216,9 @@ def show_duplicate_photos_faiss(assets, limit, min_threshold, max_threshold,immi
|
||||
progress_bar.progress(progress)
|
||||
|
||||
asset_id_1, asset_id_2 = dup_pair
|
||||
# Assuming `streamAsset` and `getAssetInfo` are defined elsewhere in your code
|
||||
image1 = streamAsset(asset_id_1, immich_server_url, 'Thumbnail (fast)', api_key)
|
||||
image2 = streamAsset(asset_id_2, immich_server_url, 'Thumbnail (fast)', api_key)
|
||||
|
||||
image1 = getImage(asset_id_1, immich_server_url, 'Thumbnail (fast)', api_key)
|
||||
image2 = getImage(asset_id_2, immich_server_url, 'Thumbnail (fast)', api_key)
|
||||
asset1_info = getAssetInfo(asset_id_1, assets)
|
||||
asset2_info = getAssetInfo(asset_id_2, assets)
|
||||
|
||||
|
||||
26
videoDuplicate.py
Normal file
26
videoDuplicate.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import streamlit as st
|
||||
import time
|
||||
import os
|
||||
import torch
|
||||
import numpy as np
|
||||
import faiss
|
||||
from torchvision.models import resnet152, ResNet152_Weights
|
||||
from torchvision.transforms import Compose, Resize, ToTensor, Normalize
|
||||
|
||||
from api import getVideo
|
||||
|
||||
# Set the environment variable to allow multiple OpenMP libraries
|
||||
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
|
||||
|
||||
# Load ResNet152 with pretrained weights
|
||||
model = resnet152(weights=ResNet152_Weights.DEFAULT)
|
||||
model.eval() # Set model to evaluation mode
|
||||
transform = Compose([
|
||||
Resize((224, 224)), # Standard size for ImageNet-trained models
|
||||
ToTensor(),
|
||||
Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
|
||||
])
|
||||
|
||||
# Global variables for paths
|
||||
index_path = 'video_faiss_index.bin'
|
||||
metadata_path = 'video_metadata.npy'
|
||||
Reference in New Issue
Block a user