import hashlib import numpy as np from PIL import Image import imagehash from skimage.metrics import structural_similarity as ssim import cv2 class AdvancedFeatures: @staticmethod def perceptual_hash(image_path): """Generate perceptual hash for deduplication""" img = Image.open(image_path) return imagehash.phash(img, hash_size=16) @staticmethod def find_similar_images(image_paths, threshold=5): """Group similar images by perceptual hash""" hashes = {} for path in image_paths: try: hashes[path] = AdvancedFeatures.perceptual_hash(path) except: pass # Group images groups = [] processed = set() for path1, hash1 in hashes.items(): if path1 in processed: continue group = [path1] for path2, hash2 in hashes.items(): if path2 != path1 and path2 not in processed: if hash1 - hash2 <= threshold: group.append(path2) processed.add(path2) groups.append(group) processed.add(path1) return groups @staticmethod def calculate_ssim(original_path, compressed_path): """Calculate structural similarity index""" img1 = cv2.imread(str(original_path)) img2 = cv2.imread(str(compressed_path)) # Resize to same dimensions if img1.shape != img2.shape: img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) # Convert to grayscale for SSIM gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) score = ssim(gray1, gray2) return score @staticmethod def recursive_optimize(compressor, img, target_size_kb, max_iterations=10): """Find optimal quality to hit target file size""" low, high = 30, 100 best_result = None best_size_diff = float('inf') for _ in range(max_iterations): mid = (low + high) // 2 # Test at quality 'mid' test_output = io.BytesIO() img.save(test_output, format='WEBP', quality=mid) size_kb = len(test_output.getvalue()) / 1024 diff = abs(size_kb - target_size_kb) if diff < best_size_diff: best_size_diff = diff best_result = (mid, test_output.getvalue()) if size_kb > target_size_kb: high = mid - 1 else: low = mid + 1 if diff < target_size_kb * 0.05: # Within 5% break return best_result