Spaces:
Running
Running
| import cv2 | |
| import numpy as np | |
| from typing import Union | |
| from PIL import Image | |
| from io import BytesIO | |
| import imghdr | |
| from fastapi import HTTPException | |
| from app.utils.file_utils import get_file_content | |
| def preprocess_image(image: Union[str, np.ndarray, Image.Image], hash_size: int = 32) -> np.ndarray: | |
| if isinstance(image, str): | |
| content = get_file_content(image) | |
| img = Image.open(BytesIO(content)) | |
| img = strip_metadata(img) | |
| image = np.array(img) | |
| elif isinstance(image, Image.Image): | |
| image = strip_metadata(image) | |
| image = np.array(image) | |
| if len(image.shape) == 3: | |
| image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) | |
| image = cv2.resize(image, (hash_size, hash_size), interpolation=cv2.INTER_AREA) | |
| image = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX) | |
| return image | |
| def strip_metadata(img: Image.Image) -> Image.Image: | |
| data = list(img.getdata()) | |
| img_without_exif = Image.new(img.mode, img.size) | |
| img_without_exif.putdata(data) | |
| return img_without_exif | |
| def perceptual_image_hash(image: Union[str, np.ndarray, Image.Image], hash_size: int = 32) -> str: | |
| processed_image = preprocess_image(image, hash_size) | |
| dct = cv2.dct(np.float32(processed_image)) | |
| dct_low = dct[:8, :8] | |
| median = np.median(dct_low[1:]) | |
| hash_value = '' | |
| for i in range(8): | |
| for j in range(8): | |
| hash_value += '1' if dct_low[i, j] > median else '0' | |
| return hash_value | |
| def hamming_distance(hash1: str, hash2: str) -> int: | |
| return sum(c1 != c2 for c1, c2 in zip(hash1, hash2)) | |
| def are_images_similar(hash1: str, hash2: str, threshold: int = 5) -> bool: | |
| distance = hamming_distance(hash1, hash2) | |
| return distance <= threshold | |
| def process_image(filename: str): | |
| try: | |
| content = get_file_content(filename) | |
| img = Image.open(BytesIO(content)) | |
| image_hash = perceptual_image_hash(img) | |
| return image_hash | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Error processing image: {str(e)}") | |
| def compare_images(filename1: str, filename2: str): | |
| try: | |
| content1 = get_file_content(filename1) | |
| content2 = get_file_content(filename2) | |
| img1 = Image.open(BytesIO(content1)) | |
| img2 = Image.open(BytesIO(content2)) | |
| hash1 = perceptual_image_hash(img1) | |
| hash2 = perceptual_image_hash(img2) | |
| are_similar = are_images_similar(hash1, hash2) | |
| distance = hamming_distance(hash1, hash2) | |
| return { | |
| "image1_hash": hash1, | |
| "image2_hash": hash2, | |
| "are_similar": are_similar, | |
| "hamming_distance": distance | |
| } | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Error comparing images: {str(e)}") | |