### Linux/macOS Installation Script for WatermarkRemover-AI Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/README.md This shell script facilitates the installation of WatermarkRemover-AI on Linux and macOS systems. It requires Python 3.10+ to be pre-installed. The script clones the repository, makes the setup script executable, and then runs it to prepare the environment for the application. ```bash git clone https://github.com/D-Ogi/WatermarkRemover-AI.git cd WatermarkRemover-AI chmod +x setup.sh ./setup.sh ``` -------------------------------- ### Windows Installation Script for WatermarkRemover-AI Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/README.md This PowerShell script automates the setup process for WatermarkRemover-AI on Windows. It clones the repository and sets up a portable Python environment, eliminating the need for a system-wide Python installation. After execution, the application can be launched via a batch file. ```powershell git clone https://github.com/D-Ogi/WatermarkRemover-AI.git cd WatermarkRemover-AI .\setup.ps1 ``` -------------------------------- ### GUI API: Start Watermark Processing Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Initiates watermark removal processing through the GUI's Python API. It allows for detailed configuration of input/output paths, overwrite behavior, transparency, bounding box settings, format, mode, and detection parameters like prompt and skip frames. Processing runs in a background thread, and the API provides methods to start and stop it. ```python from remwmgui import Api api = Api() # Configure processing settings settings = { 'input': '/path/to/watermarked_image.jpg', 'output': '/path/to/output/', 'overwrite': False, 'transparent': False, 'max_bbox': 15, 'format': 'PNG', # or 'None' to preserve original 'mode': 'single', # or 'batch' 'detection_prompt': 'watermark', 'detection_skip': 3, # for videos: detect every N frames 'fade_in': 0.5, # seconds 'fade_out': 0.5 # seconds } # Start processing (runs in background thread) result = api.start_processing(settings) # Returns: {'status': 'started'} or {'error': 'message'} # Stop processing if needed api.stop_processing() # Returns: {'status': 'stopped'} ``` -------------------------------- ### Get Current Configuration Settings Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html This function retrieves the current configuration settings of the application, including input/output paths, processing options, and theme/language preferences. These settings are intended to be saved or passed to a backend process. ```javascript getConfig() { return { input_path: this.inputPath, output_path: this.outputPath, overwrite: this.overwrite, transparent: this.transparent, max_bbox_percent: this.detection, force_format: this.format, mode: this.mode, detection_prompt: this.detectionPrompt, // Video settings detection_skip: parseInt(this.detectionSkip) || 1, fade_in: parseFloat(this.fadeIn) || 0, fade_out: parseFloat(this.fadeOut) || 0, // Theme & Language theme: this.theme, lang: this.lang }; } ``` -------------------------------- ### JavaScript System Information Loading (pywebview API) Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Asynchronously loads static system information such as CUDA, FFmpeg, and GPU details using the `get_static_info` method from the pywebview API. It includes error handling and retries if the API is not immediately available. ```javascript async loadStaticInfo() { if (window.pywebview) { try { const info = await pywebview.api.get_static_info(); this.systemInfo.cuda = info.cuda; this.systemInfo.gpu = info.gpu_name || 'CPU MODE'; this.systemInfo.ffmpeg = info.ffmpeg; } catch (e) { // API not ready yet, retry setTimeout(() => this.loadStaticInfo(), 500); } } else { setTimeout(() => this.loadStaticInfo(), 500); } } ``` -------------------------------- ### Run Image Preview with Detection Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html This function initiates an image preview by calling the `preview_detection` API. It handles loading states, displays detection results, and logs success or failure messages. ```javascript async runPreview() { if (!this.inputPath) { this.addLogEntry(this.t.logs?.no_input || "No input selected. Please select a file first.", "text-error"); return; } this.previewLoading = true; this.previewError = null; this.previewImage = null; // Clear old preview immediately this.previewDetections = []; this.previewMode = true; if (window.pywebview) { try { const result = await pywebview.api.preview_detection({ input: this.inputPath, detection_prompt: this.detectionPrompt || 'watermark', max_bbox: this.detection }); if (result.error) { this.previewError = result.error; this.previewImage = null; this.previewDetections = []; this.addLogEntry((this.t.logs?.preview_failed || "Preview failed:") + " " + result.error, "text-error"); } else { this.previewImage = result.image; this.previewDetections = result.detections || []; this.previewPromptUsed = result.prompt_used; this.previewSource = result.source; this.previewError = null; const accepted = this.previewDetections.filter(d => d.accepted).length; const total = this.previewDetections.length; const msg = (this.t.logs?.preview_result || "Detected {total} regions, {accepted} will be removed.") .replace('{total}', total) .replace('{accepted}', accepted); this.addLogEntry(msg, "text-neon-cyan"); } } catch (e) { this.previewError = "API error: " + e.message; this.addLogEntry((this.t.logs?.preview_failed || "Preview failed:") + " " + e.message, "text-error"); } } this.previewLoading = false; } ``` -------------------------------- ### GUI API: Configuration Persistence Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Manages user preferences for the watermark removal application, allowing settings to be saved and loaded across sessions using YAML files. The API provides methods to retrieve the current configuration and to save a new set of preferences, including paths, processing options, and UI themes. ```python from remwmgui import Api api = Api() # Get saved configuration config = api.get_config() # Returns dict with saved settings or {} # Save configuration api.save_config({ 'input_path': '/last/used/path', 'output_path': '/last/output/path', 'overwrite': False, 'transparent': False, 'max_bbox_percent': 15, 'force_format': 'PNG', 'mode': 'single', 'detection_prompt': 'watermark', 'theme': 'brainrot', 'lang': 'en' }) # Configuration saved to ui.yml in application directory ``` -------------------------------- ### CLI - Preview Watermark Detections with WatermarkRemover-AI Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Previews detected watermarks on images or videos without processing. Returns JSON output with base64-encoded image showing bounding boxes and detection metadata. Supports custom detection prompts and maximum bounding box percentage. ```bash # Preview detection on single image python remwm.py input.png --preview # Preview with custom detection prompt python remwm.py image.jpg --preview --detection-prompt="Getty Images" # Preview on video (samples middle frame) python remwm.py video.mp4 --preview --max-bbox-percent=20 # Expected JSON output: # { # "image": "iVBORw0KGgoAAAANSUhEU...", # "detections": [ # {"bbox": [10, 20, 150, 80], "area_percent": 2.5, "accepted": true}, # {"bbox": [500, 400, 800, 600], "area_percent": 12.0, "accepted": false} # ], # "source": "input.png", # "source_type": "image", # "prompt_used": "watermark", # "max_bbox_percent": 10.0 # } ``` -------------------------------- ### Preview Mode for Watermark Detection Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/README.md Demonstrates how to use the CLI in preview mode with WatermarkRemover-AI. This mode allows users to detect watermarks without actually processing and removing them, which is useful for verifying detection accuracy before committing to the removal process. ```bash python remwm.py input.png --preview ``` -------------------------------- ### JavaScript Processing Initiation and Validation (pywebview API) Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Initiates the video processing task. It performs preliminary checks, such as validating the input path, warning about ghost mode with videos, and alerting if FFmpeg is not found. It then calls the `start_processing` API method with various parameters. ```javascript async startProcessing() { if (!this.inputPath) { this.addLogEntry(this.t.logs?.no_input || "No input selected. Please select a file first.", "text-error"); return; } // Check for video + transparency warning if (this.isVideoFile(this.inputPath) && this.transparent) { this.addLogEntry(this.t.logs?.ghost_video_warning || "Ghost mode doesn't work with videos. Turning it off.", "text-yellow-400"); this.transparent = false; } // Check for FFmpeg warning if (this.isVideoFile(this.inputPath) && !this.systemInfo.ffmpeg) { this.addLogEntry(this.t.logs?.no_ffmpeg || "FFmpeg not found! Video will have no audio.", "text-yellow-400"); } this.processing = true; this.progress = 0; this.addLogEntry(this.t.logs?.starting || "Starting process...", "text-white"); this.addLogEntry(this.t.logs?.first_run_hint || "(First run may download AI models)", "text-gray-500"); // Update status message randomly const statusInterval = setInterval(() => { if (this.processing && this.t.processing_status?.length > 0) { this.statusMsg = this.t.processing_status[Math.floor(Math.random() * this.t.processing_status.length)]; } else { clearInterval(statusInterval); } }, 2000); if (window.pywebview && window.pywebview.api) { try { const result = await pywebview.api.start_processing({ input: this.inputPath, output: this.outputPath, overwrite: this.overwrite, transparent: this.transparent, max_bbox: this.detection, format: this.format, mode: this.mode, detection_prompt: this.detectionPrompt || 'watermark', // Video settings detection_skip: parseInt(this.detectionSkip) || 1, fade_in: parseFloat(this.fadeIn) || 0, fade_out: parseFloat(this.fadeOut) || 0, // UI settings theme: this.theme, lang: this.lang }); // Check for error response from backend if (result && result.error) { th ``` -------------------------------- ### GUI API: System Information Retrieval Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Queries the system for hardware and software capabilities relevant to the watermark removal process. It provides static information like CUDA and FFmpeg availability, GPU name, and dynamic information such as current RAM and CPU usage percentages. Static info should be fetched once on startup, while dynamic info can be polled periodically. ```python from remwmgui import Api api = Api() # Get static info (call once on startup) static_info = api.get_static_info() # Returns: # { # 'cuda': True, # 'gpu_name': 'NVIDIA GeForce RTX 4090', # 'ffmpeg': True # } # Get dynamic info (call periodically) dynamic_info = api.get_dynamic_info() # Returns: # { # 'ram_percent': 45.2, # 'cpu_percent': 23.5 # } ``` -------------------------------- ### JavaScript Output Path Browsing (pywebview API) Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Allows the user to select an output directory using the pywebview API's `browse_folder` method. If a directory is selected, it updates the output path and triggers a debounced save of the configuration. ```javascript async browseOutput() { if (!window.pywebview?.api?.browse_folder) { this.addLogEntry(this.t.logs?.api_error || "API not available. Please run via run.bat/run.sh", "text-error"); return; } const path = await pywebview.api.browse_folder(); if (path) { this.outputPath = path; this.saveConfigDebounced(); } } ``` -------------------------------- ### Advanced Command-Line Options for Watermark Removal Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/README.md Illustrates advanced CLI options for WatermarkRemover-AI, including overwriting existing files, setting a maximum bounding box percentage for detection, and forcing a specific output format. These options allow for more control over the removal process. ```bash python remwm.py ./images ./output --overwrite --max-bbox-percent=15 --force-format=PNG ``` -------------------------------- ### GUI API: Preview Watermark Detection Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Provides a preview of watermark detection without performing the full removal process. This function takes input image path and detection settings, returning a base64 encoded image with bounding boxes drawn around detected watermarks. It also returns details about the detections, source, and parameters used. ```python from remwmgui import Api api = Api() settings = { 'input': '/path/to/image.jpg', 'detection_prompt': 'watermark', 'max_bbox': 15 } result = api.preview_detection(settings) # Success result: # { # 'image': 'base64_encoded_png...', # 'detections': [ # {'bbox': [10, 20, 150, 80], 'area_percent': 2.5, 'accepted': True} # ], # 'source': '/path/to/image.jpg', # 'source_type': 'image', # 'prompt_used': 'watermark', # 'max_bbox_percent': 15 # } # Error result: # {'error': 'No input path specified'} ``` -------------------------------- ### Command-line: Transparent Mode with Custom Format Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Removes watermarks from an image using the command-line interface. Supports transparent mode, which requires PNG output for alpha channel support. For videos, transparent mode will fill with a white background as video formats do not support alpha channels. ```bash python remwm.py image.jpg ./output/ --transparent --force-format=PNG ``` -------------------------------- ### JavaScript Language Loader (Async) Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Asynchronously loads language JSON files from the 'lang/' directory. It handles potential errors, such as file not found, and includes a fallback mechanism to load the 'brainrot' language if the requested language fails. ```javascript async function loadLanguage(lang) { try { const response = await fetch(`lang/${lang}.json`); if (!response.ok) throw new Error('Language file not found'); return await response.json(); } catch (e) { console.error('Failed to load language:', lang, e); if (lang !== 'brainrot') { return await loadLanguage('brainrot'); } return null; } } ``` -------------------------------- ### JavaScript Input Path Browsing (pywebview API) Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Handles the file or folder browsing functionality for the input path. It dynamically selects the appropriate pywebview API method (`browse_file` or `browse_folder`) based on the current processing mode and updates the input path. Includes error handling for API unavailability. ```javascript async browseInput() { const picker = window.pywebview?.api?.browse_file || (this.mode === 'single' ? window.pywebview?.api?.browse_file : window.pywebview?.api?.browse_folder); if (!picker) { this.addLogEntry(this.t.logs?.api_error || "API not available. Please run via run.bat/run.sh", "text-error"); return; } const path = this.mode === 'single' ? await window.pywebview.api.browse_file() : await window.pywebview.api.browse_folder(); if (path) { this.inputPath = path; this.saveConfigDebounced(); } } ``` -------------------------------- ### JavaScript Dynamic System Information Update (pywebview API) Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Periodically updates dynamic system information, specifically RAM usage percentage, by calling the `get_dynamic_info` method from the pywebview API. This function is intended to be called at regular intervals. ```javascript async updateDynamicInfo() { if (window.pywebview) { try { const info = await pywebview.api.get_dynamic_info(); this.systemInfo.ram = Math.round(info.ram_percent); } catch (e) { // ignore } } } ``` -------------------------------- ### Python API - Complete Pipeline Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Full end-to-end watermark removal combining detection, mask generation, and inpainting in a single workflow. ```APIDOC ## Python API - Complete Pipeline ### Description Full end-to-end watermark removal combining detection, mask generation, and inpainting in a single workflow. ### Method `remove_watermark` function within the `remwm` library. ### Parameters #### Function Parameters - **input_path** (str) - Required - Path to the input image file. - **output_path** (str) - Required - Path to save the cleaned image file. - **detection_prompt** (str) - Optional - The prompt used for watermark detection (default: 'watermark'). - **max_bbox_percent** (float) - Optional - Maximum percentage of image area a bounding box can occupy to be considered during mask generation (default: 10.0). ### Response #### Success Response - **output_path** (str) - The path where the cleaned image has been saved. ### Request Example ```python import torch import numpy as np import cv2 from PIL import Image from transformers import AutoProcessor, Florence2ForConditionalGeneration from remwm import get_watermark_mask, process_image_with_lama, load_lama_model def remove_watermark(input_path, output_path, detection_prompt="watermark", max_bbox_percent=10.0): """Complete watermark removal pipeline.""" device = "cuda" if torch.cuda.is_available() else "cpu" # Load Florence-2 for detection florence_model = Florence2ForConditionalGeneration.from_pretrained( "florence-community/Florence-2-large" ).to(device).eval() florence_processor = AutoProcessor.from_pretrained("florence-community/Florence-2-large") # Load LaMA for inpainting lama_model = load_lama_model(device) # Load and process image image = Image.open(input_path).convert("RGB") # Detect watermarks and create mask mask = get_watermark_mask( image, florence_model, florence_processor, device, max_bbox_percent, detection_prompt ) # Apply inpainting result = process_image_with_lama(np.array(image), np.array(mask), lama_model) # Save result result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) Image.fromarray(result_rgb).save(output_path) return output_path # Example usage: # remove_watermark("watermarked_image.jpg", "cleaned_image.jpg") ``` ``` -------------------------------- ### Basic Command-Line Usage for Watermark Removal Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/README.md Demonstrates the fundamental command-line interface (CLI) usage for WatermarkRemover-AI. This command processes a single input image and saves the output to a specified folder. It's the simplest way to initiate watermark removal via the terminal. ```bash python remwm.py input.png output_folder/ ``` -------------------------------- ### CLI - Custom Detection Prompts for WatermarkRemover-AI Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Uses custom text prompts with Florence-2 to target specific watermark types, including branded watermarks by name. Useful for precise watermark identification. ```bash # Detect Sora watermarks specifically python remwm.py sora_video.mp4 ./output/ --detection-prompt="watermark Sora logo" # Detect Getty Images watermarks python remwm.py stock_photo.jpg ./output/ --detection-prompt="Getty Images" # Detect multiple watermark types python remwm.py image.png ./output/ --detection-prompt="watermark logo text overlay" ``` -------------------------------- ### CLI - Batch Processing Images and Videos with WatermarkRemover-AI Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Processes all files in a directory, handling different file types. Supports overwriting existing files, forcing output format, and setting a maximum bounding box percentage for detections. ```bash # Process all files in a directory python remwm.py ./watermarked_images/ ./output/ --overwrite # Process with format conversion and custom bbox limit python remwm.py ./images/ ./output/ --force-format=PNG --max-bbox-percent=15 # Expected output: # Using device: cuda # Processing files: 100%|██████████| 25/25 [02:15<00:00, 5.42s/it] # input_path:image1.jpg, output_path:./output/image1.png, overall_progress:4% # input_path:image2.jpg, output_path:./output/image2.png, overall_progress:8% # ... ``` -------------------------------- ### Python API - LaMA Inpainting Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Apply LaMA inpainting to fill masked regions with naturally reconstructed content. Requires numpy arrays as input. ```APIDOC ## Python API - LaMA Inpainting ### Description Apply LaMA inpainting to fill masked regions with naturally reconstructed content. Requires numpy arrays as input. ### Method `process_image_with_lama` function within the `remwm` library. ### Parameters #### Function Parameters - **image** (numpy.ndarray) - Required - The input image as a NumPy array (e.g., RGB format). - **mask** (numpy.ndarray) - Required - The inpainting mask as a NumPy array (e.g., grayscale mode 'L'). White pixels (255) indicate regions to inpaint. - **model_manager** (object) - Required - The loaded LaMA model manager obtained from `load_lama_model`. ### Response #### Success Response - **result** (numpy.ndarray) - The inpainted image as a NumPy array in BGR format (compatible with OpenCV). ### Request Example ```python import numpy as np from PIL import Image from remwm import process_image_with_lama, load_lama_model # Load LaMA model (downloads automatically if needed) device = "cuda" model_manager = load_lama_model(device) # Load image and mask as numpy arrays image = np.array(Image.open("watermarked_image.jpg").convert("RGB")) mask = np.array(Image.open("watermark_mask.png").convert("L")) # Apply inpainting result = process_image_with_lama(image, mask, model_manager) # Result is numpy array (BGR format from OpenCV) # Convert to RGB PIL Image for saving import cv2 result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) result_image = Image.fromarray(result_rgb) result_image.save("cleaned_image.jpg") ``` ``` -------------------------------- ### CLI - Video Processing with WatermarkRemover-AI Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Processes videos using a two-pass approach for watermark detection and inpainting. Supports frame skipping for optimization and handling fade in/out effects for animated watermarks. Preserves original audio. ```bash # Basic video processing (detects every frame) python remwm.py video.mp4 ./output/ # Optimized video processing with frame skipping (faster) python remwm.py video.mp4 ./output/ --detection-skip=3 # Handle fade in/out watermarks (extend mask temporally) python remwm.py video.mp4 ./output/ --detection-skip=3 --fade-in=0.5 --fade-out=0.5 # Expected output: # Using device: cuda # Two-pass processing: 1200 frames, skip=3, fade_in=15f, fade_out=15f # Pass 1: Detecting watermarks... # Pass 1: frame 0/1200, overall_progress:0% # Pass 1 complete: found watermarks in 400 detection points # Timeline expanded: 450 frames will have inpainting applied # Pass 2: Applying inpainting... # Pass 2: frame 1200/1200, overall_progress:100% # Merging processed video with original audio... # Audio/video merge completed successfully! ``` -------------------------------- ### Python API: Complete Pipeline Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Provides a full end-to-end watermark removal pipeline by integrating watermark detection, mask generation, and LaMA inpainting into a single, cohesive workflow. This function takes an input image path and an output path, performing all necessary steps to produce a cleaned image. ```python import torch import numpy as np import cv2 from PIL import Image from transformers import AutoProcessor, Florence2ForConditionalGeneration from remwm import get_watermark_mask, process_image_with_lama, load_lama_model def remove_watermark(input_path, output_path, detection_prompt="watermark", max_bbox_percent=10.0): """Complete watermark removal pipeline.""" device = "cuda" if torch.cuda.is_available() else "cpu" # Load Florence-2 for detection florence_model = Florence2ForConditionalGeneration.from_pretrained( "florence-community/Florence-2-large" ).to(device).eval() florence_processor = AutoProcessor.from_pretrained("florence-community/Florence-2-large") # Load LaMA for inpainting lama_model = load_lama_model(device) # Load and process image image = Image.open(input_path).convert("RGB") # Detect watermarks and create mask mask = get_watermark_mask( image, florence_model, florence_processor, device, max_bbox_percent, detection_prompt ) # Apply inpainting result = process_image_with_lama(np.array(image), np.array(mask), lama_model) # Save result result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) Image.fromarray(result_rgb).save(output_path) return output_path ``` -------------------------------- ### Python API - Watermark Detection Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Use the core detection function to identify watermarks in images programmatically. Returns bounding boxes with area percentage and acceptance status. ```APIDOC ## Python API - Watermark Detection ### Description Use the core detection function to identify watermarks in images programmatically. Returns bounding boxes with area percentage and acceptance status. ### Method `detect_only` function within the `remwm` library. ### Parameters #### Function Parameters - **image** (PIL.Image.Image) - Required - The input image to detect watermarks in. - **model** (object) - Required - The loaded Florence-2 model. - **processor** (object) - Required - The Florence-2 processor. - **device** (str) - Required - The device to run the model on ('cuda' or 'cpu'). - **max_bbox_percent** (float) - Optional - Maximum percentage of image area a bounding box can occupy to be considered. - **detection_prompt** (str) - Optional - The prompt used for watermark detection (default: 'watermark'). ### Response #### Success Response - **detections** (list) - A list of dictionaries, where each dictionary contains: - **bbox** (list) - Bounding box coordinates [x1, y1, x2, y2]. - **area_percent** (float) - The percentage of the image area the bounding box occupies. - **accepted** (bool) - Whether the detection meets the `max_bbox_percent` criteria. ### Request Example ```python import torch from PIL import Image from transformers import AutoProcessor, Florence2ForConditionalGeneration from remwm import detect_only # Load models device = "cuda" if torch.cuda.is_available() else "cpu" model = Florence2ForConditionalGeneration.from_pretrained( "florence-community/Florence-2-large" ).to(device).eval() processor = AutoProcessor.from_pretrained("florence-community/Florence-2-large") # Load image image = Image.open("watermarked_image.jpg").convert("RGB") # Detect watermarks (max 10% of image area) detections = detect_only( image=image, model=model, processor=processor, device=device, max_bbox_percent=10.0, detection_prompt="watermark" ) # Result: [{"bbox": [x1, y1, x2, y2], "area_percent": 2.5, "accepted": True}, ...] for det in detections: print(f"Watermark at {det['bbox']}, {det['area_percent']:.1f}% of image") print(f" Accepted: {det['accepted']}") ``` ``` -------------------------------- ### JavaScript Event Listeners for pywebview API Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Sets up event listeners for 'pywebview-log', 'pywebview-progress', and 'pywebview-complete' events. These listeners update the UI with log messages, processing progress, and completion status. It also handles the removal of old listeners to prevent memory leaks. ```javascript if (window.__pywebviewLogHandler) { window.removeEventListener('pywebview-log', window.__pywebviewLogHandler); } window.__pywebviewLogHandler = (e) => { this.addLogEntry(e.detail.msg, e.detail.color); }; window.addEventListener('pywebview-log', window.__pywebviewLogHandler); if (window.__pywebviewProgressHandler) { window.removeEventListener('pywebview-progress', window.__pywebviewProgressHandler); } window.__pywebviewProgressHandler = (e) => { this.progress = e.detail.percent; }; window.addEventListener('pywebview-progress', window.__pywebviewProgressHandler); if (window.__pywebviewCompleteHandler) { window.removeEventListener('pywebview-complete', window.__pywebviewCompleteHandler); } window.__pywebviewCompleteHandler = () => { this.processing = false; this.progress = 100; this.addLogEntry(this.t.logs?.done || "Done! File processed successfully.", "text-neon-pink font-bold"); }; window.addEventListener('pywebview-complete', window.__pywebviewCompleteHandler); ``` -------------------------------- ### Video Processing with Two-Pass Detection and Fade Handling Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/README.md Shows how to use the CLI for video processing with WatermarkRemover-AI, specifically enabling two-pass detection by skipping frames and configuring fade-in/out durations. This is useful for watermarks that appear or disappear gradually over time. ```bash python remwm.py video.mp4 ./output --detection-skip=3 --fade-in=0.5 --fade-out=0.5 ``` -------------------------------- ### JavaScript Global Functions for Python Callbacks Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Provides global JavaScript functions that can be called by Python via pywebview to update the UI. These functions dispatch custom events that Alpine.js can listen to for progress updates, log messages, and completion notifications. ```javascript window.appInstance = null; function updateProgress(percent) { window.dispatchEvent(new CustomEvent('pywebview-progress', { detail: { percent } })); } function addLog(msg, color = 'text-gray-400') { window.dispatchEvent(new CustomEvent('pywebview-log', { detail: { msg, color } })); } function processingComplete() { window.dispatchEvent(new CustomEvent('pywebview-complete')); } ``` -------------------------------- ### JavaScript Configuration Management and Saving Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Handles debounced saving of application configuration. It prevents saving until the configuration is loaded and uses a timeout to limit the frequency of save operations. The actual saving is delegated to the pywebview API. ```javascript // Auto-save config (debounced) _saveTimeout: null, _configLoaded: false, // Block saves until config is loaded saveConfigDebounced() { if (!this._configLoaded) return; // Don't save until config loaded clearTimeout(this._saveTimeout); this._saveTimeout = setTimeout(() => this.saveConfig(), 500); }, async saveConfig() { if (window.pywebview?.api?.save_config) { try { await pywebview.api.save_config(this.getConfig()); } catch (e) { console.log('Config save failed:', e); } } } ``` -------------------------------- ### Utility Functions: Coordinate Conversion for Florence-2 Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Provides utility functions to convert image bounding box coordinates between pixel values and relative/token formats required by the Florence-2 model. It includes functions to convert pixel bounding boxes to relative coordinates (0-999 range) and vice versa, as well as to Florence-2's specific location token format. ```python from PIL import Image from utils import ( convert_bbox_to_relative, convert_relative_to_bbox, convert_bbox_to_loc ) image = Image.open("image.jpg") # Pixel bbox [x1, y1, x2, y2] pixel_bbox = [100, 50, 300, 150] # Convert to relative coordinates (0-999 range) relative = convert_bbox_to_relative(pixel_bbox, image) # Returns: [124.8, 62.4, 374.5, 187.3] (example for 800x800 image) # Convert back to pixel coordinates pixels = convert_relative_to_bbox(relative, image) # Returns: [100.0, 50.0, 300.0, 150.0] # Convert to Florence-2 location tokens loc_tokens = convert_bbox_to_loc(pixel_bbox, image) # Returns: "" ``` -------------------------------- ### Utility Functions: Image Visualization Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Includes functions for drawing visual representations of detection results directly onto images. This is useful for debugging and previewing, allowing users to see segmentation polygons and OCR bounding boxes overlaid on the original image. The functions support options like filling masks for segmentation. ```python from PIL import Image from utils import draw_polygons, draw_ocr_bboxes image = Image.open("image.jpg") # Draw segmentation polygons polygon_prediction = { 'polygons': [[[100, 100, 200, 100, 200, 200, 100, 200]]], 'labels': ['watermark'] } annotated = draw_polygons(image.copy(), polygon_prediction, fill_mask=True) annotated.save("annotated_polygons.jpg") ``` -------------------------------- ### CLI - Basic Image Processing with WatermarkRemover-AI Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Removes watermarks from a single image using Florence-2 detection and LaMA inpainting. Automatically detects and fills watermark regions. Supports specifying output file path. ```bash # Basic single image processing python remwm.py input.png output_folder/ # Process with specific output file python remwm.py watermarked_image.jpg ./cleaned_image.png # Expected output: # Using device: cuda # input_path:watermarked_image.jpg, output_path:./cleaned_image.png, overall_progress:100% ``` -------------------------------- ### Remove Watermark using Python Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Demonstrates the basic usage of the `remove_watermark` function to process an image. It takes input and output file paths and an optional detection prompt. The function returns the path to the saved output file. ```python output = remove_watermark("input.jpg", "output.jpg", detection_prompt="watermark Sora logo") print(f"Saved to: {output}") ``` -------------------------------- ### Alpine.js Application Logic (JavaScript) Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html The main Alpine.js component logic for the WatermarkRemover AI. It manages application state, loads configuration from `config.json` and pywebview, handles theme and language switching, and controls UI elements like loading screens and previews. ```javascript function brainrotApp() { return { isLoading: true, mode: 'single', overwrite: false, transparent: false, detection: 15, format: 'None', inputPath: '', outputPath: '', processing: false, progress: 0, statusMsg: '', theme: 'brainrot', lang: 'en', t: {}, appVersion: '', availableThemes: [], availableLanguages: [], logSeq: Date.now(), logs: [], systemInfo: { cuda: false, ram: 0, gpu: 'Checking...', ffmpeg: false }, detectionPrompt: 'watermark', previewMode: false, previewLoading: false, previewImage: null, previewDetections: [], previewPromptUsed: '', previewSource: '', previewError: null, detectionSkip: 1, fadeIn: 0, fadeOut: 0, async init() { window.appInstance = this; try { const uiConfig = await fetch('config.json').then(r => r.json()); this.appVersion = uiConfig.version || '0.0'; this.availableThemes = uiConfig.themes || []; this.availableLanguages = uiConfig.languages || []; } catch (e) { console.log('Failed to load config.json, using defaults'); this.appVersion = '0.0'; this.availableThemes = [{ id: 'brainrot' }]; this.availableLanguages = [{ id: 'brainrot', randomizable: true }, { id: 'en', randomizable: false }]; } const pickRandom = (arr) => arr[Math.floor(Math.random() * arr.length)]; const randomizableThemes = this.availableThemes.map(t => t.id); const randomizableLangs = this.availableLanguages.filter(l => l.randomizable).map(l => l.id); const loadConfig = async () => { if (!window.pywebview?.api) return; try { const config = await pywebview.api.get_config() || {}; console.log('Config loaded:', config); this.inputPath = config.input_path || ''; this.outputPath = config.output_path || ''; this.overwrite = config.overwrite || false; this.transparent = config.transparent || false; this.detection = config.max_bbox_percent || 15; this.format = config.force_format || 'None'; this.mode = config.mode || 'single'; this.detectionPrompt = config.detection_prompt || 'watermark'; this.detectionSkip = config.detection_skip || 1; this.fadeIn = config.fade_in || 0; this.fadeOut = config.fade_out || 0; this.theme = config.theme || pickRandom(randomizableThemes); this.lang = config.lang || pickRandom(randomizableLangs); switchTheme(this.theme); await this.switchLang(this.lang); this._configLoaded = true; this.isLoading = false; } catch (e) { console.log('Config load failed:', e); this.theme = pickRandom(randomizableThemes); this.lang = pickRandom(randomizableLangs); switchTheme(this.theme); await this.switchLang(this.lang); this.isLoading = false; } }; if (window.pywebview?.api) { await loadConfig(); } else { window.addEventListener('pywebviewready', loadConfig); setTimeout(() => { if (this.isLoading) { console.log('Pywebview timeout, using random config'); this.theme = pickRandom(randomizableThemes); this.lang = pickRandom(randomizableLangs); switchTheme(this.theme); this.switchLang(this.lang); this.isLoading = false; } }, 3000); } if (window.) {} }, async switchLang(lang) { this.lang = lang; this.t = await loadLanguage(lang) || {}; document.documentElement.setAttribute('lang', lang); }, async setConfig(key, value) { if (!window.pywebview?.api) return; await pywebview.api.set_config({ [key]: value }); }, async processVideo() { if (this.processing || !this.inputPath || !this.outputPath) return; this.processing = true; this.progress = 0; this.logs = []; await pywebview.api.process_video({ input_path: this.inputPath, output_path: this.outputPath, mode: this.mode, overwrite: this.overwrite, transparent: this.transparent, max_bbox_percent: this.detection, force_format: this.format, detection_prompt: this.detectionPrompt, detection_skip: this.detectionSkip, fade_in: this.fadeIn, fade_out: this.fadeOut }); }, async selectFolder(type) { if (!window.pywebview?.api) return; const folderPath = await pywebview.api.select_folder(); if (folderPath) { if (type === 'input') this.inputPath = folderPath; if (type === 'output') this.outputPath = folderPath; } }, async getSystemInfo() { if (!window.pywebview?.api) return; try { const info = await pywebview.api.get_system_info(); this.systemInfo = { ...this.systemInfo, ...info }; } catch (e) { console.error('Failed to get system info:', e); } }, async checkPreview() { if (!this.inputPath || !window.pywebview?.api) return; this.previewLoading = true; this.previewError = null; this.previewImage = null; try { const previewData = await pywebview.api.get_preview({ input_path: this.inputPath, detection_prompt: this.detectionPrompt, detection_skip: this.detectionSkip }); this.previewImage = previewData.image; this.previewDetections = previewData.detections; this.previewPromptUsed = previewData.prompt_used; this.previewSource = previewData.source; } catch (e) { console.error('Failed to get preview:', e); this.previewError = e.message; } finally { this.previewLoading = false; } }, togglePreview() { this.previewMode = !this.previewMode; if (this.previewMode && !this.previewImage) { this.checkPreview(); } } }; } ``` -------------------------------- ### CLI - Transparency Mode with WatermarkRemover-AI Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Replaces detected watermark regions with transparent areas instead of inpainting. This feature is useful for manual compositing or preserving the original background. ```bash # Create transparent regions where watermarks were detected python remwm.py logo_image.png ./output/ --transparent ``` -------------------------------- ### Python API: Watermark Detection Source: https://context7.com/d-ogi/watermarkremover-ai/llms.txt Utilizes the core detection function to programmatically identify watermarks in images. This function returns bounding boxes, their area percentage relative to the image, and an acceptance status based on predefined criteria. ```python import torch from PIL import Image from transformers import AutoProcessor, Florence2ForConditionalGeneration from remwm import detect_only # Load models device = "cuda" if torch.cuda.is_available() else "cpu" model = Florence2ForConditionalGeneration.from_pretrained( "florence-community/Florence-2-large" ).to(device).eval() processor = AutoProcessor.from_pretrained("florence-community/Florence-2-large") # Load image image = Image.open("watermarked_image.jpg").convert("RGB") # Detect watermarks (max 10% of image area) detections = detect_only( image=image, model=model, processor=processor, device=device, max_bbox_percent=10.0, detection_prompt="watermark" ) # Result: [{"bbox": [x1, y1, x2, y2], "area_percent": 2.5, "accepted": True}, ...] for det in detections: print(f"Watermark at {det['bbox']}, {det['area_percent']:.1f}% of image") print(f" Accepted: {det['accepted']}") ``` -------------------------------- ### CSS Animation for Loading Bar Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html Implements a 'loadingBar' animation using CSS keyframes. This animation simulates a loading bar that expands and then disappears, creating a visual indicator for processes. It controls the width and margin of an element to achieve the effect. ```css @keyframes loadingBar { 0% { width: 0%; margin-left: 0%; } 50% { width: 60%; margin-left: 20%; } 100% { width: 0%; margin-left: 100%; } } ``` -------------------------------- ### Switch Application Language Source: https://github.com/d-ogi/watermarkremover-ai/blob/main/ui/index.html This function allows switching the application's language by loading new translations. It updates the UI's text content, sets the page title, and initializes the status message and logs. ```javascript async switchLang(langCode) { const translations = await loadLanguage(langCode); if (translations) { this.t = translations; this.lang = langCode; // Update page title document.title = this.t.app?.title || 'WM Remover'; // Set initial status message if (this.t.processing_status?.length > 0) { this.statusMsg = this.t.processing_status[0]; } // Add init log if logs are empty if (this.logs.length === 0) { this.addLogEntry(this.t.logs?.init || 'System initialized.', 'text-gray-400'); } // Auto-save config this.saveConfigDebounced(); } } ```