# File: app.py import streamlit as st from PIL import Image, ImageDraw, ImageFont, ExifTags import requests from io import BytesIO import cv2 import numpy as np import pandas as pd from skimage.metrics import structural_similarity as ssim import fitz # PyMuPDF for PDF handling import docx # For handling Word documents from difflib import HtmlDiff, SequenceMatcher # For text comparison import os import logging import base64 import zipfile from typing import Dict from deepface import DeepFace # For deepfake detection import pytesseract # For OCR in watermark detection # Page configuration with custom theme st.set_page_config( page_title="Centurion", # Title of the web app page_icon="https://raw.githubusercontent.com/noumanjavaid96/ai-as-an-api/refs/heads/master/image%20(39).png", # Icon displayed in the browser tab layout="wide", # Layout of the app# Initial state of the sidebar ) # Apply custom theme using CSS st.markdown( """ """, unsafe_allow_html=True # Allow HTML in markdown ) # Display the title with the icon st.markdown( """
Icon
Centurion
""", unsafe_allow_html=True # Allow HTML in markdown ) # Configure logging logging.basicConfig(level=logging.INFO) # Set logging level to INFO logger = logging.getLogger(__name__) # Create a logger UPLOAD_DIR = "uploaded_files" # Directory to store uploaded files NVIDIA_API_KEY = "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" # Store API key securely # Create upload directory if it doesn't exist if not os.path.exists(UPLOAD_DIR): os.makedirs(UPLOAD_DIR) # Create the directory class NVIDIAOCRHandler: def __init__(self): self.api_key = NVIDIA_API_KEY # Initialize API key self.nvai_url = "https://ai.api.nvidia.com/v1/cv/nvidia/ocdrnet" # NVIDIA OCR API URL self.headers = {"Authorization": f"Bearer {self.api_key}"} # Set headers for API requests def process_image(self, file_path: str) -> str: try: with open(file_path, "rb") as image_file: # Open the image file files = {'image': image_file} # Prepare file for upload response = requests.post(self.nvai_url, headers=self.headers, files=files) # Send POST request response.raise_for_status() # Raise an error for bad responses result = response.json() # Parse JSON response return result.get("text", "") # Return extracted text except Exception as e: st.error(f"Error processing image: {str(e)}") # Display error message return "" # Return empty string on error def save_uploaded_file(uploaded_file): file_path = os.path.join(UPLOAD_DIR, uploaded_file.name) # Create file path with open(file_path, "wb") as f: # Open file for writing f.write(uploaded_file.getbuffer()) # Write uploaded file to disk return file_path # Return the file path def upload_asset(input_data: bytes, description: str) -> str: try: assets_url = "https://api.nvcf.nvidia.com/v2/nvcf/assets" # NVIDIA asset upload URL headers = { "Authorization": f"Bearer {NVIDIA_API_KEY}", # Set authorization header "Content-Type": "application/json", # Set content type "accept": "application/json", # Accept JSON response } payload = {"contentType": "image/jpeg", "description": description} # Prepare payload for upload response = requests.post(assets_url, headers=headers, json=payload) response.raise_for_status() asset_url = response.json()["uploadUrl"] asset_id = response.json()["assetId"] response = requests.put( asset_url, data=input_data, headers={"x-amz-meta-nvcf-asset-description": description, "content-type": "image/jpeg"}, timeout=300, ) response.raise_for_status() return asset_id except Exception as e: st.error(f"Error uploading asset: {str(e)}") return "" def extract_text_pdf(file_path): doc = fitz.open(file_path) text = "" for page in doc: text += page.get_text() return text def extract_text_word(file_path): doc = docx.Document(file_path) text = "\n".join([para.text for para in doc.paragraphs]) return text def compare_texts(text1, text2): differ = HtmlDiff() return differ.make_file( text1.splitlines(), text2.splitlines(), fromdesc="Original", todesc="Modified", context=True, numlines=2 ) def calculate_similarity(text1, text2): matcher = SequenceMatcher(None, text1, text2) return matcher.ratio() logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s' ) logger = logging.getLogger(__name__) class NvidiaDeepfakeDetector: def __init__(self): """ Initialize Deepfake Detection with configuration """ self.api_key = f"Bearer NVIDIA_API_KEY" self.upload_dir = os.getenv('UPLOAD_DIR', '/tmp') self.max_image_size = 5 * 1024 * 1024 # 5MB self.invoke_url = "https://ai.api.nvidia.com/v1/cv/hive/deepfake-image-detection" # Validate critical configurations self._validate_config() def _validate_config(self): """ Validate critical configuration parameters """ if not self.api_key: raise ValueError("NVIDIA API Key is not configured") if not os.path.exists(self.upload_dir): os.makedirs(self.upload_dir, exist_ok=True) def validate_image(self, image_bytes: bytes) -> bool: """ Validate image before processing Args: image_bytes (bytes): Image data Returns: bool: Image validation status """ try: # Check image size if len(image_bytes) > self.max_image_size: st.error(f"Image exceeds maximum size of {self.max_image_size} bytes") return False # Try opening image Image.open(BytesIO(image_bytes)) return True except Exception as e: st.error(f"Image validation failed: {e}") return False def upload_asset(self, path: str, desc: str) -> str: """ Upload asset to NVIDIA's asset management system Args: path (str): Image file path desc (str): Asset description Returns: str: Asset ID """ try: assets_url = "https://api.nvcf.nvidia.com/v2/nvcf/assets" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {self.api_key}", "accept": "application/json", } # Create asset payload = { "contentType": "image/png", "description": desc } response = requests.post(assets_url, headers=headers, json=payload, timeout=30) response.raise_for_status() upload_url = response.json()["uploadUrl"] asset_id = response.json()["assetId"] # Upload image with open(path, "rb") as input_data: upload_response = requests.put( upload_url, data=input_data, headers={"Content-Type": "image/png"}, timeout=300 ) upload_response.raise_for_status() return asset_id except requests.exceptions.RequestException as e: logger.error(f"Asset upload failed: {e}") st.error("Failed to upload image asset") return "" """ Detect deepfake using NVIDIA API Args: image_bytes (bytes): Image data Returns: Optional[Dict]: Detection results """ # Validate image if not self.validate_image(image_bytes): return None try: # Temporary image path temp_path = os.path.join(self.upload_dir, "temp_deepfake_image.png") with open(temp_path, "wb") as f: f.write(image_bytes) # Encode image image_b64 = base64.b64encode(image_bytes).decode() # Payload preparation if len(image_b64) < 180_000: payload = {"input": [f"data:image/png;base64,{image_b64}"]} headers = { "Content-Type": "application/json", "Authorization": f"Bearer {self.api_key}", "Accept": "application/json", } else: # Large image asset upload asset_id = self.upload_asset(temp_path, "Deepfake Detection") payload = {"input": [f"data:image/png;asset_id,{asset_id}"]} headers = { "Content-Type": "application/json", "NVCF-INPUT-ASSET-REFERENCES": asset_id, "Authorization": f"Bearer {self.api_key}", } # API Call response = requests.post(self.invoke_url, headers=headers, json=payload) response.raise_for_status() # Clean up temporary file os.remove(temp_path) return response.json() except requests.exceptions.RequestException as e: logger.error(f"Deepfake detection error: {e}") st.error("Deepfake detection failed") return None except Exception as e: logger.error(f"Unexpected error: {e}") st.error("An unexpected error occurred") return None # Streamlit Integration Function def nvidia_deepfake_detection_app(): st.header("🕵️ Deepfake Detection") # Initialize detector detector = NvidiaDeepfakeDetector() # File uploader uploaded_file = st.file_uploader( "Upload an image", type=["jpg", "jpeg", "png"], key="deepfake_nvidia" ) if uploaded_file is not None: # Read image image_bytes = uploaded_file.getvalue() image = Image.open(BytesIO(image_bytes)) # Layout col1, col2 = st.columns([2, 1]) with col1: st.image(image, caption="Uploaded Image", use_column_width=True) with col2: st.write("### Detection Results") # Detect deepfake with st.spinner("Analyzing image..."): result = detector.detect_deepfake(image_bytes) # Process and display results if result and 'data' in result and result['data']: # Check data list too deepfake_data = result['data'][0] # Access the data list inside the 'data' key is_deepfake = deepfake_data.get('isDeepfake', False) # Access isDeepfake from deepfake_data confidence = deepfake_data.get('confidence', 0.0) with col2: # Confidence metrics st.metric( label="Deepfake Probability", value=f"{confidence:.2f}%", delta="High Risk" if confidence >= 70 else "Low Risk" ) # Risk assessment if is_deepfake > 90: st.error("🚨 HIGH RISK: Likely a Deepfake") elif confidence > 70: st.warning("⚠️ MODERATE RISK: Potential Deepfake") else: st.success("✅ LOW RISK: Likely Authentic") else: st.error("Unable to perform deepfake detection") # Main execution def detect_watermark(image, text): try: gray_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY) detected_text = pytesseract.image_to_string(gray_image) return text.strip().lower() in detected_text.strip().lower() except Exception as e: st.error(f"Error in watermark detection: {str(e)}") return False def get_metadata(image): exif_data = {} info = image.getexif() if info: for tag, value in info.items(): decoded = ExifTags.TAGS.get(tag, tag) exif_data[decoded] = value return exif_data def compare_metadata(meta1, meta2): keys = set(meta1.keys()).union(set(meta2.keys())) data = [] for key in keys: value1 = meta1.get(key, "Not Available") value2 = meta2.get(key, "Not Available") if value1 != value2: data.append({"Metadata Field": key, "Original Image": value1, "Compared Image": value2}) if data: df = pd.DataFrame(data) return df else: return None def detect_deepfake(image): try: analysis = DeepFace.analyze(img_path=np.array(image), actions=['emotion'], enforce_detection=False) if analysis and 'emotion' in analysis: return "Real Face Detected", 0.99 else: return "No Face Detected", 0.0 except Exception as e: st.error(f"Error in deepfake detection: {str(e)}") return "Error", 0.0 def image_comparison_app(): st.header("🔍 Image Analysis for Differences") st.write("Upload two images to compare them and find differences.") col1, col2 = st.columns(2) with col1: st.subheader("Original Image") uploaded_file1 = st.file_uploader("Choose the original image", type=["png", "jpg", "jpeg"], key="comp1") with col2: st.subheader("Image to Compare") uploaded_file2 = st.file_uploader("Choose the image to compare", type=["png", "jpg", "jpeg"], key="comp2") if uploaded_file1 and uploaded_file2: image1 = Image.open(uploaded_file1) image2 = Image.open(uploaded_file2) img1 = cv2.cvtColor(np.array(image1), cv2.COLOR_RGB2BGR) img2 = cv2.cvtColor(np.array(image2), cv2.COLOR_RGB2BGR) if img1.shape != img2.shape: st.warning("Images are not the same size. Resizing the second image to match the first.") img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) score, diff = ssim(gray1, gray2, full=True) st.write(f"**Structural Similarity Index (SSIM): {score:.4f}**") diff = (diff * 255).astype("uint8") thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) img1_diff = img1.copy() img2_diff = img2.copy() for cnt in contours: x, y, w, h = cv2.boundingRect(cnt) cv2.rectangle(img1_diff, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.rectangle(img2_diff, (x, y), (x + w, y + h), (0, 0, 255), 2) img1_display = cv2.cvtColor(img1_diff, cv2.COLOR_BGR2RGB) img2_display = cv2.cvtColor(img2_diff, cv2.COLOR_BGR2RGB) diff_display = cv2.cvtColor(diff, cv2.COLOR_GRAY2RGB) thresh_display = cv2.cvtColor(thresh, cv2.COLOR_GRAY2RGB) st.write("## Results") st.write("Differences are highlighted in red boxes.") st.image([img1_display, img2_display], caption=["Original Image with Differences", "Compared Image with Differences"], width=300) st.write("## Difference Image") st.image(diff_display, caption="Difference Image", width=300) st.write("## Thresholded Difference Image") st.image(thresh_display, caption="Thresholded Difference Image", width=300) else: st.info("Please upload both images.") def image_comparison_and_watermarking_app(): st.header("💧 Watermark Adding and Detecting") st.write("Upload an image to add a watermark, and detect if a watermark is present.") def add_watermark(image, text): txt = Image.new('RGBA', image.size, (255, 255, 255, 0)) draw = ImageDraw.Draw(txt) font_size = max(20, image.size[0] // 20) try: font = ImageFont.truetype("arial.ttf", font_size) except IOError: font = ImageFont.load_default() # Fallback if font not found bbox = font.getbbox(text) textwidth = bbox[2] - bbox[0] textheight = bbox[3] - bbox[1] x = image.size[0] - textwidth - 10 y = image.size[1] - textheight - 10 draw.text((x, y), text, font=font, fill=(255, 255, 255, 128)) watermarked = Image.alpha_composite(image.convert('RGBA'), txt) return watermarked.convert('RGB') uploaded_file = st.file_uploader("Choose an image", type=["png", "jpg", "jpeg"], key="wm1") watermark_text = st.text_input("Enter watermark text:", value="Sample Watermark") if uploaded_file: image = Image.open(uploaded_file).convert("RGB") st.image(image, caption="Original Image", width=300) st.write("### Watermarked Image") watermarked_image = add_watermark(image, watermark_text) st.image(watermarked_image, caption="Watermarked Image", width=300) st.write("### Watermark Detection") if detect_watermark(watermarked_image, watermark_text): st.success("Watermark detected in the image.") else: st.warning("Watermark not detected in the image.") st.write("### Metadata") metadata = get_metadata(image) st.write(metadata if metadata else "No metadata available.") else: st.info("Please upload an image.") def process_deepfake_detection_nvidia(image_bytes): header_auth = f"Bearer {NVIDIA_API_KEY}" invoke_url = "https://ai.api.nvidia.com/v1/cv/hive/deepfake-image-detection" try: if image_bytes is not None: image_b64 = base64.b64encode(image_bytes).decode() payload = {"input": [f"data:image/jpeg;base64,{image_b64}"]} headers = { "Content-Type": "application/json", "Authorization": header_auth, "Accept": "application/json", } response = requests.post(invoke_url, headers=headers, json= payload) response.raise_for_status() response_json = response.json() return response_json # Return the result except requests.exceptions.RequestException as e: st.error(f"Error with NVIDIA API: {e}") return None def nvidia_deepfake_detection_app(): st.header("NVIDIA Deepfake Detection") uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"], key="deepfake_nvidia") if uploaded_file is not None: image_bytes = uploaded_file.getvalue() image = Image.open(BytesIO(image_bytes)) st.image(image, caption="Uploaded Image", use_container_width=True) col1, col2 = st.columns([2, 1]) with col1: # Display original image st.image(image, caption="Uploaded Image", use_container_width=True) with col2: # Placeholder for detection results st.write("### Detection Results") # Perform deepfake detection with st.spinner("Analyzing image for deepfake..."): result = process_deepfake_detection_nvidia(image_bytes) if result and 'data' in result and result['data']: deepfake_data = result['data'][0] # Deepfake confidence is_deepfake = deepfake_data.get('isDeepfake', 0) deepfake_confidence = is_deepfake * 100 # Face detection confidence face_confidence = deepfake_data.get('confidence', 0) * 100 # Update the second column with detailed results with col2: # Deepfake Probability Card st.markdown("""

Deepfake Analysis

""", unsafe_allow_html=True) # Deepfake Confidence Metric st.metric( label="Deepfake Probability", value=f"{deepfake_confidence:.1f}%", delta="High Risk" if deepfake_confidence > 70 else "Low Risk" ) # Face Detection Confidence Metric st.metric( label="Face Detection Confidence", value=f"{face_confidence:.1f}%" ) # Risk Assessment if deepfake_confidence > 90: st.error("🚨 HIGH RISK: Likely a Deepfake") elif deepfake_confidence > 70: st.warning("⚠️ MODERATE RISK: Potential Deepfake") else: st.success("✅ LOW RISK: Likely Authentic") st.markdown("
", unsafe_allow_html=True) # Detailed Explanation st.markdown("### Detailed Analysis") # Create expandable sections for more information with st.expander("Deepfake Detection Explanation"): st.write(""" - **Deepfake Probability**: Indicates the likelihood of the image being artificially generated. - **Face Detection Confidence**: Measures the model's confidence in detecting a face in the image. - High probabilities suggest potential manipulation. """) # Raw JSON for technical users with st.expander("Technical Details"): if result: st.json(result) else: st.error("Unable to perform deepfake detection. Please try another image.") else: st.info("Please upload an image to perform deepfake detection.") def document_comparison_tool(): st.header("📄 Document In-Depth Comparison") st.markdown("Compare documents and detect changes with OCR highlighting.") col1, col2 = st.columns(2) with col1: st.markdown("### Original Document") original_file = st.file_uploader( "Upload original document", type=["pdf", "docx", "jpg", "jpeg", "png"], key='doc_original_file', help="Supported formats: PDF, DOCX, JPG, PNG" ) with col2: st.markdown("### Modified Document") modified_file = st.file_uploader( "Upload modified document", type=["pdf", "docx", "jpg", "jpeg", "png"], key='doc_modified_file', help="Supported formats: PDF, DOCX, JPG, PNG" ) if original_file and modified_file: ocr_handler = NVIDIAOCRHandler() original_file_path = save_uploaded_file(original_file) modified_file_path = save_uploaded_file(modified_file) original_ext = os.path.splitext(original_file.name)[1].lower() modified_ext = os.path.splitext(modified_file.name)[1].lower() if original_ext in ['.jpg', '.jpeg', '.png']: original_text = ocr_handler.process_image(original_file_path) elif original_ext == '.pdf': original_text = extract_text_pdf(original_file_path) else: original_text = extract_text_word(original_file_path) if modified_ext in ['.jpg', '.jpeg', '.png']: modified_text = ocr_handler.process_image(modified_file_path) elif modified_ext == '.pdf': modified_text = extract_text_pdf(modified_file_path) else: modified_text = extract_text_word(modified_file_path) similarity_score = calculate_similarity(original_text, modified_text) st.markdown("### 📊 Analysis Results") metrics_col1, metrics_col2 = st.columns(2) with metrics_col1: st.metric("Similarity Score", f"{similarity_score:.2%}") with metrics_col2: st.metric("Changes Detected", "Yes" if similarity_score < 1 else "No") st.markdown("### 🔍 Detailed Comparison") diff_html = compare_texts(original_text, modified_text) st.components.v1.html(diff_html, height=600, scrolling=True) st.markdown("### 💾 Download Results") if st.button("Generate Report"): st.success("Report generated successfully!") st.download_button( label="Download Report", data=diff_html, file_name="comparison_report.html", mime="text/html" ) else: st.info("Please upload both documents to begin comparison.") def main(): st.write(""" """) tabs = st.tabs([ "Image Comparison" ]) with tabs[0]: image_comparison_app() if __name__ == "__main__": main()