| | """ |
| | FLUX Detector Model |
| | =================== |
| | |
| | Vision Transformer-based model for detecting FLUX.1-dev generated images. |
| | |
| | This model is a binary classifier that detects whether an image |
| | was generated by FLUX.1-dev (Black Forest Labs). |
| | |
| | ⚠️ IMPORTANT: This model ONLY detects FLUX images! |
| | - FLUX images → Classified as "Fake" |
| | - Real images → Classified as "Real" |
| | - SDXL/Midjourney/other AI → Classified as "Real" (not trained on these!) |
| | |
| | For comprehensive AI detection, use this as part of an ensemble with |
| | other specialized detectors. |
| | |
| | Architecture: |
| | - Base: Vision Transformer (ViT-base-patch16-224) |
| | - Classifier: Dropout + Linear (768 → 2) |
| | - Output: Binary (0=Real, 1=FLUX-Fake) |
| | |
| | Quick Start: |
| | from transformers import ViTForImageClassification, ViTImageProcessor |
| | from PIL import Image |
| | |
| | # Load model |
| | model = ViTForImageClassification.from_pretrained( |
| | "ash12321/flux-detector-vit" |
| | ) |
| | processor = ViTImageProcessor.from_pretrained( |
| | "google/vit-base-patch16-224" |
| | ) |
| | |
| | # Process image |
| | image = Image.open("test.jpg") |
| | inputs = processor(images=image, return_tensors="pt") |
| | |
| | # Get prediction |
| | outputs = model(**inputs) |
| | probs = torch.softmax(outputs.logits, dim=1) |
| | |
| | if probs[0][1] > 0.5: |
| | print(f"FLUX-Generated: {probs[0][1]:.2%}") |
| | else: |
| | print(f"Not FLUX: {probs[0][0]:.2%}") |
| | |
| | Performance: |
| | Test Accuracy: 99.85% |
| | Precision: 100.00% (PERFECT - Zero false positives!) |
| | Recall: 99.70% |
| | False Positive Rate: 0.00% |
| | False Negative Rate: 0.30% |
| | """ |
| |
|
| | import torch |
| | import torch.nn as nn |
| | from transformers import ViTForImageClassification, ViTImageProcessor |
| | from PIL import Image |
| | from typing import Dict, Union, Optional |
| | from pathlib import Path |
| |
|
| |
|
| | class FLUXDetector: |
| | """ |
| | FLUX Image Detector |
| | |
| | Easy-to-use wrapper for detecting FLUX.1-dev generated images. |
| | """ |
| | |
| | def __init__( |
| | self, |
| | model_path: str = "ash12321/flux-detector-vit", |
| | device: str = None |
| | ): |
| | """ |
| | Initialize FLUX detector |
| | |
| | Args: |
| | model_path: HuggingFace model repo or local path |
| | device: Device to use ('cuda', 'cpu', or None for auto) |
| | """ |
| | if device is None: |
| | device = "cuda" if torch.cuda.is_available() else "cpu" |
| | |
| | self.device = device |
| | self.model_path = model_path |
| | |
| | |
| | self.model = ViTForImageClassification.from_pretrained(model_path) |
| | self.model.to(device) |
| | self.model.eval() |
| | |
| | self.processor = ViTImageProcessor.from_pretrained( |
| | "google/vit-base-patch16-224" |
| | ) |
| | |
| | print(f"✅ FLUX Detector loaded on {device}") |
| | |
| | def detect( |
| | self, |
| | image: Union[str, Path, Image.Image], |
| | threshold: float = 0.5 |
| | ) -> Dict[str, Union[bool, float]]: |
| | """ |
| | Detect if image is FLUX-generated |
| | |
| | Args: |
| | image: Image path or PIL Image |
| | threshold: Classification threshold (default 0.5) |
| | |
| | Returns: |
| | dict with keys: |
| | - is_flux: bool - True if FLUX-generated |
| | - confidence: float - Confidence in prediction |
| | - flux_probability: float - Probability of being FLUX |
| | - real_probability: float - Probability of being real |
| | - label: str - Human-readable label |
| | """ |
| | |
| | if isinstance(image, (str, Path)): |
| | image = Image.open(image).convert('RGB') |
| | |
| | |
| | inputs = self.processor(images=image, return_tensors="pt") |
| | inputs = {k: v.to(self.device) for k, v in inputs.items()} |
| | |
| | |
| | with torch.no_grad(): |
| | outputs = self.model(**inputs) |
| | probs = torch.softmax(outputs.logits, dim=1) |
| | flux_prob = probs[0][1].item() |
| | real_prob = probs[0][0].item() |
| | |
| | is_flux = flux_prob > threshold |
| | |
| | return { |
| | 'is_flux': is_flux, |
| | 'confidence': flux_prob if is_flux else real_prob, |
| | 'flux_probability': flux_prob, |
| | 'real_probability': real_prob, |
| | 'label': 'FLUX-Generated' if is_flux else 'Not FLUX' |
| | } |
| | |
| | def batch_detect( |
| | self, |
| | images: list, |
| | threshold: float = 0.5 |
| | ) -> list: |
| | """ |
| | Detect FLUX on multiple images |
| | |
| | Args: |
| | images: List of image paths or PIL Images |
| | threshold: Classification threshold |
| | |
| | Returns: |
| | List of detection results |
| | """ |
| | return [self.detect(img, threshold) for img in images] |
| |
|
| |
|
| | def detect_flux( |
| | image_path: str, |
| | threshold: float = 0.5, |
| | device: str = None |
| | ) -> Dict[str, Union[bool, float]]: |
| | """ |
| | Quick function to detect FLUX image |
| | |
| | Args: |
| | image_path: Path to image |
| | threshold: Classification threshold |
| | device: Device to use |
| | |
| | Returns: |
| | Detection results dictionary |
| | |
| | Example: |
| | >>> result = detect_flux("image.jpg") |
| | >>> print(f"Is FLUX: {result['is_flux']}") |
| | >>> print(f"Confidence: {result['confidence']:.2%}") |
| | """ |
| | detector = FLUXDetector(device=device) |
| | return detector.detect(image_path, threshold) |
| |
|
| |
|
| | |
| | MODEL_INFO = { |
| | 'name': 'FLUX Detector', |
| | 'version': '1.0', |
| | 'type': 'Binary Classifier', |
| | 'detects': 'FLUX.1-dev images (Black Forest Labs)', |
| | 'does_not_detect': [ |
| | 'SDXL images', |
| | 'Midjourney images', |
| | 'DALL-E images', |
| | 'FLUX.1-schnell (4-step variant)', |
| | 'FLUX 2 (newer version)', |
| | 'Other AI generators' |
| | ], |
| | 'architecture': 'Vision Transformer (ViT-base-patch16-224)', |
| | 'input_size': (224, 224), |
| | 'classes': { |
| | 0: 'Real / Not FLUX', |
| | 1: 'FLUX-Generated' |
| | }, |
| | 'performance': { |
| | 'test_accuracy': 0.9985, |
| | 'precision': 1.0000, |
| | 'recall': 0.9970, |
| | 'f1_score': 0.9985, |
| | 'false_positive_rate': 0.0000, |
| | 'false_negative_rate': 0.0030 |
| | }, |
| | 'training': { |
| | 'real_images': 8000, |
| | 'flux_images': 8000, |
| | 'epochs': 9, |
| | 'best_epoch': 6 |
| | } |
| | } |
| |
|
| |
|
| | if __name__ == "__main__": |
| | print("="*60) |
| | print("FLUX Detector - Model Information") |
| | print("="*60) |
| | print(f"\nModel: {MODEL_INFO['name']}") |
| | print(f"Detects: {MODEL_INFO['detects']}") |
| | print(f"\n⚠️ Does NOT detect:") |
| | for item in MODEL_INFO['does_not_detect']: |
| | print(f" - {item}") |
| | print(f"\n📊 Performance:") |
| | print(f" Accuracy: {MODEL_INFO['performance']['test_accuracy']:.2%}") |
| | print(f" Precision: {MODEL_INFO['performance']['precision']:.2%} ⭐ PERFECT!") |
| | print(f" Recall: {MODEL_INFO['performance']['recall']:.2%}") |
| | print(f" FPR: {MODEL_INFO['performance']['false_positive_rate']:.2%} ⭐ ZERO!") |
| | print(f" FNR: {MODEL_INFO['performance']['false_negative_rate']:.2%}") |
| | |
| | print("\n🎯 Key Feature:") |
| | print(" This model has ZERO false positives!") |
| | print(" It will NEVER incorrectly flag a real image as fake.") |
| | |
| | print("\n" + "="*60) |
| | print("Example Usage:") |
| | print("="*60) |
| | print(""" |
| | from model import FLUXDetector |
| | |
| | # Initialize detector |
| | detector = FLUXDetector() |
| | |
| | # Detect single image |
| | result = detector.detect("image.jpg") |
| | print(f"Is FLUX: {result['is_flux']}") |
| | print(f"Confidence: {result['confidence']:.2%}") |
| | |
| | # Or use quick function |
| | from model import detect_flux |
| | result = detect_flux("image.jpg") |
| | """) |