From 33b2e68d7d814d9967e187ab6a263ec2db578399 Mon Sep 17 00:00:00 2001 From: fernando_jacob Date: Fri, 13 Mar 2026 12:51:07 +0800 Subject: [PATCH 1/2] Add visible watermark detection and upgrade invisible watermark confidence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement two key improvements: 1. Visible watermark detection: New detector analyzes image corners for bright text overlays characteristic of Chinese AI disclosure badges (e.g., "AI生成" on Dreamina images). Uses luminance clustering and text-run analysis to identify watermarks with MEDIUM confidence for known AI positions. 2. Invisible watermark confidence upgrade: Invisible watermark signals now report MEDIUM confidence when indicators are exceptionally strong (bit agreement > 0.90, energy spread > 1.0) or when all 3 indicators fire, instead of always reporting LOW confidence. Changes: - New module: src/detector/visible_watermark.rs (bottom-up text detection via corner region analysis) - Enhanced: src/detector/watermark.rs (confidence escalation logic, video frame confidence passthrough) - Enhanced: src/detector/mod.rs (integration of visible watermark detection) - Enhanced: src/known_tools.rs (added "dreamina" pattern) - Added: i18n strings in all 7 locale files - Added: 3 integration tests for visible watermark detection - Added: test fixture (Dreamina image with visible watermarks) Results: - Dreamina image: LOW → MEDIUM (now detects both invisible + visible watermarks) - Sora video: LOW → MEDIUM (exceptionally strong invisible watermark signals) - No false positives on clean images All 67 tests passing. Co-Authored-By: Claude Haiku 4.5 --- locales/de.yml | 2 + locales/en.yml | 2 + locales/es.yml | 2 + locales/hi.yml | 2 + locales/ja.yml | 2 + locales/ko.yml | 2 + locales/zh-CN.yml | 2 + src/detector/mod.rs | 10 + src/detector/visible_watermark.rs | 609 +++++++++++++++++++++++++ src/detector/watermark.rs | 44 +- src/known_tools.rs | 2 + tests/fixtures/dreamina_visible_wm.jpg | Bin 0 -> 97405 bytes tests/watermark_detection.rs | 44 ++ 13 files changed, 720 insertions(+), 3 deletions(-) create mode 100644 src/detector/visible_watermark.rs create mode 100644 tests/fixtures/dreamina_visible_wm.jpg diff --git a/locales/de.yml b/locales/de.yml index 09a551a..f0cca84 100644 --- a/locales/de.yml +++ b/locales/de.yml @@ -66,3 +66,5 @@ signal_audio_flatness: "Spektrale Flachheit %{value} deutet auf synthetisches Au signal_wav_info_tool: "WAV INFO %{key} stimmt mit KI-Tool überein: %{value}" signal_wav_tts_heuristic: "Audioeigenschaften deuten auf TTS hin: Mono %{rate}Hz %{bits}bit" signal_video_frame_watermark: "Wasserzeichen-Indikatoren in Videobild erkannt (bei %{frame}): %{indicators}" +signal_visible_watermark_badge: "Sichtbares KI-Wasserzeichen-Badge in %{corner} Ecke erkannt (%{indicators})" +signal_visible_watermark_generic: "Sichtbare Textüberlagerung in %{corner} Ecke erkannt (möglicherweise Wasserzeichen)" diff --git a/locales/en.yml b/locales/en.yml index 918ee10..9b8f020 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -66,3 +66,5 @@ signal_audio_flatness: "Spectral flatness %{value} suggests synthetic audio (nat signal_wav_info_tool: "WAV INFO %{key} matches AI tool: %{value}" signal_wav_tts_heuristic: "Audio characteristics suggest TTS: mono %{rate}Hz %{bits}bit" signal_video_frame_watermark: "Video frame watermark indicators detected (at %{frame}): %{indicators}" +signal_visible_watermark_badge: "Visible AI watermark badge detected in %{corner} corner (%{indicators})" +signal_visible_watermark_generic: "Visible text overlay detected in %{corner} corner (possible watermark)" diff --git a/locales/es.yml b/locales/es.yml index 9d08fdf..3732fb3 100644 --- a/locales/es.yml +++ b/locales/es.yml @@ -66,3 +66,5 @@ signal_audio_flatness: "Planitud espectral %{value} sugiere audio sintético (el signal_wav_info_tool: "WAV INFO %{key} coincide con herramienta de IA: %{value}" signal_wav_tts_heuristic: "Características de audio sugieren TTS: mono %{rate}Hz %{bits}bit" signal_video_frame_watermark: "Indicadores de marca de agua detectados en fotograma de video (en %{frame}): %{indicators}" +signal_visible_watermark_badge: "Insignia de marca de agua de IA visible detectada en esquina %{corner} (%{indicators})" +signal_visible_watermark_generic: "Superposición de texto visible detectada en esquina %{corner} (posible marca de agua)" diff --git a/locales/hi.yml b/locales/hi.yml index 625475e..527d5da 100644 --- a/locales/hi.yml +++ b/locales/hi.yml @@ -66,3 +66,5 @@ signal_audio_flatness: "स्पेक्ट्रल समतलता %{valu signal_wav_info_tool: "WAV INFO %{key} AI टूल से मेल खाता है: %{value}" signal_wav_tts_heuristic: "ऑडियो विशेषताएँ TTS का संकेत देती हैं: मोनो %{rate}Hz %{bits}bit" signal_video_frame_watermark: "वीडियो फ़्रेम वॉटरमार्क संकेतक पाए गए (%{frame} पर): %{indicators}" +signal_visible_watermark_badge: "%{corner} कोने में दृश्य AI वॉटरमार्क बैज पाया गया (%{indicators})" +signal_visible_watermark_generic: "%{corner} कोने में दृश्य टेक्स्ट ओवरले पाया गया (वॉटरमार्क हो सकता है)" diff --git a/locales/ja.yml b/locales/ja.yml index 4694de5..6c10dd9 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -66,3 +66,5 @@ signal_audio_flatness: "スペクトル平坦度 %{value} は合成音声を示 signal_wav_info_tool: "WAV INFO %{key} がAIツールに一致:%{value}" signal_wav_tts_heuristic: "音声特性がTTSを示唆:モノラル %{rate}Hz %{bits}bit" signal_video_frame_watermark: "動画フレームの電子透かし指標を検出(%{frame}時点):%{indicators}" +signal_visible_watermark_badge: "%{corner}コーナーに可視AIウォーターマークバッジを検出(%{indicators})" +signal_visible_watermark_generic: "%{corner}コーナーに可視テキストオーバーレイを検出(ウォーターマークの可能性)" diff --git a/locales/ko.yml b/locales/ko.yml index bda6a47..5282115 100644 --- a/locales/ko.yml +++ b/locales/ko.yml @@ -66,3 +66,5 @@ signal_audio_flatness: "스펙트럼 평탄도 %{value}는 합성 오디오를 signal_wav_info_tool: "WAV INFO %{key}이(가) AI 도구와 일치: %{value}" signal_wav_tts_heuristic: "오디오 특성이 TTS를 시사: 모노 %{rate}Hz %{bits}bit" signal_video_frame_watermark: "비디오 프레임 워터마크 지표 감지 (%{frame} 위치): %{indicators}" +signal_visible_watermark_badge: "%{corner} 모서리에서 가시적 AI 워터마크 배지 감지 (%{indicators})" +signal_visible_watermark_generic: "%{corner} 모서리에서 가시적 텍스트 오버레이 감지 (워터마크 가능성)" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 02d8a8c..b997ecb 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -66,3 +66,5 @@ signal_audio_flatness: "频谱平坦度 %{value} 表明为合成音频(自然 signal_wav_info_tool: "WAV INFO %{key} 匹配 AI 工具:%{value}" signal_wav_tts_heuristic: "音频特征表明为 TTS:单声道 %{rate}Hz %{bits}bit" signal_video_frame_watermark: "视频帧水印指标检测到(位于 %{frame}):%{indicators}" +signal_visible_watermark_badge: "在%{corner}角检测到可见AI水印标识(%{indicators})" +signal_visible_watermark_generic: "在%{corner}角检测到可见文字覆盖层(可能为水印)" diff --git a/src/detector/mod.rs b/src/detector/mod.rs index 71e2f2b..253d21f 100644 --- a/src/detector/mod.rs +++ b/src/detector/mod.rs @@ -5,6 +5,7 @@ pub mod filename; pub mod id3_metadata; pub mod mp4_metadata; pub mod png_text; +pub mod visible_watermark; pub mod watermark; pub mod wav_metadata; pub mod xmp; @@ -351,6 +352,15 @@ pub fn run_all_detectors(path: &Path, deep: bool) -> FileReport { } } } + // Visible watermark detection (corner badge analysis) + match visible_watermark::detect(path) { + Ok(sigs) => signals.extend(sigs), + Err(e) => { + if std::env::var("AIC_DEBUG").is_ok() { + eprintln!(" [debug] Visible watermark: {}", e); + } + } + } } } diff --git a/src/detector/visible_watermark.rs b/src/detector/visible_watermark.rs new file mode 100644 index 0000000..f49eb9e --- /dev/null +++ b/src/detector/visible_watermark.rs @@ -0,0 +1,609 @@ +use anyhow::{Context, Result}; +use std::path::Path; + +use super::{Confidence, Signal, SignalBuilder, SignalSource}; + +/// Maximum image dimension — higher than invisible watermark detector since we need spatial detail. +const MAX_DIM: u32 = 2048; +/// Images smaller than this are unlikely to have meaningful visible watermarks. +const MIN_DIM: u32 = 200; + +// Corner region sizing (fraction of image dimensions) +const CORNER_WIDTH_FRAC: f64 = 0.22; +const CORNER_HEIGHT_FRAC: f64 = 0.12; +const CORNER_MIN_WIDTH_PX: u32 = 80; +const CORNER_MIN_HEIGHT_PX: u32 = 50; + +// Text detection thresholds +/// Bright pixels must be this many luminance units above the corner region mean. +const BRIGHT_DELTA: f64 = 35.0; +/// Minimum valid horizontal run length for text-like patterns. +const MIN_RUN_LENGTH: u32 = 3; +/// Maximum valid horizontal run length for text-like patterns. +const MAX_RUN_LENGTH: u32 = 60; +/// A row needs at least this many valid bright runs to count as a "text row". +const MIN_RUNS_PER_ROW: u32 = 2; +/// Minimum fraction of rows within the text bounding box that must be text rows. +const MIN_TEXT_ROWS_FRACTION: f64 = 0.12; +/// Maximum bbox height as fraction of corner region height. Rejects non-compact matches. +const MAX_BBOX_HEIGHT_FRAC: f64 = 0.50; +/// Maximum gap (in rows) between consecutive text rows within a cluster. +const MAX_CLUSTER_GAP: u32 = 3; +/// Minimum bright pixel ratio within the text bounding box. +const MIN_BRIGHT_RATIO: f64 = 0.03; +/// Maximum bright pixel ratio within the text bounding box. +const MAX_BRIGHT_RATIO: f64 = 0.50; +/// Minimum number of text rows to consider a cluster valid. +const MIN_TEXT_ROW_COUNT: u32 = 3; +/// Minimum bounding box dimensions for a valid text cluster. +const MIN_BBOX_WIDTH: u32 = 30; +const MIN_BBOX_HEIGHT: u32 = 12; +/// Bimodal luminance check: minimum difference between cluster centers. +const BIMODAL_CENTER_DIFF: f64 = 50.0; + +/// Minimum indicators required to report a detection. +const MIN_INDICATORS: usize = 2; + +#[derive(Debug, Clone, Copy, PartialEq)] +enum Corner { + TopLeft, + TopRight, + BottomLeft, + BottomRight, +} + +impl Corner { + fn name(&self) -> &'static str { + match self { + Corner::TopLeft => "top-left", + Corner::TopRight => "top-right", + Corner::BottomLeft => "bottom-left", + Corner::BottomRight => "bottom-right", + } + } + + /// Top-left and bottom-right are known positions for Chinese AI disclosure watermarks. + fn is_known_ai_position(&self) -> bool { + matches!(self, Corner::TopLeft | Corner::BottomRight) + } +} + +/// Bounding box of detected text cluster within a corner region. +struct TextBbox { + x0: u32, + y0: u32, + x1: u32, + y1: u32, +} + +struct TextCluster { + start_row: u32, + end_row: u32, +} + +struct TextAnalysis { + bright_ratio: f64, + text_row_fraction: f64, + is_bimodal: bool, + mean_lum: f64, +} + +/// Detect visible AI watermark badges in image corner regions. +/// +/// Looks for the characteristic pattern of Chinese AI regulatory watermarks: +/// bright text overlay in corners (e.g., "AI生成", "即梦AI"). +/// Uses a bottom-up approach: finds bright text clusters first, then validates. +pub fn detect(path: &Path) -> Result> { + let img = image::open(path).context("Failed to open image for visible watermark analysis")?; + let img = if img.width() > MAX_DIM || img.height() > MAX_DIM { + img.resize(MAX_DIM, MAX_DIM, image::imageops::FilterType::Lanczos3) + } else { + img + }; + + let (w, h) = (img.width(), img.height()); + if w < MIN_DIM || h < MIN_DIM { + return Ok(vec![]); + } + + let gray = img.to_luma8(); + let debug = std::env::var("AIC_DEBUG").is_ok(); + + // Corner region dimensions + let region_w = ((w as f64 * CORNER_WIDTH_FRAC) as u32) + .max(CORNER_MIN_WIDTH_PX) + .min(w / 2); + let region_h = ((h as f64 * CORNER_HEIGHT_FRAC) as u32) + .max(CORNER_MIN_HEIGHT_PX) + .min(h / 2); + + let corners = [ + Corner::TopLeft, + Corner::TopRight, + Corner::BottomLeft, + Corner::BottomRight, + ]; + + let mut signals = Vec::new(); + + for &corner in &corners { + let (ox, oy) = corner_offset(corner, w, h, region_w, region_h); + let region = extract_region(&gray, ox, oy, region_w, region_h); + + let region_mean = compute_mean(®ion); + let bright_threshold = (region_mean + BRIGHT_DELTA).min(255.0) as u8; + + // Step 1: Find text rows (rows with multiple bright pixel runs) + let text_rows = find_text_rows(®ion, region_w, region_h, bright_threshold); + + let total_text_rows = text_rows.iter().filter(|&&v| v).count() as u32; + if total_text_rows < MIN_TEXT_ROW_COUNT { + if debug { + eprintln!( + " [debug] Visible watermark {}: region_mean={:.1} bright_thr={} text_rows={}", + corner.name(), + region_mean, + bright_threshold, + total_text_rows + ); + } + continue; + } + + // Step 2: Split text rows into compact clusters (groups separated by gaps) + let clusters = find_text_clusters(&text_rows); + + for cluster in &clusters { + let cluster_h = cluster.end_row - cluster.start_row; + if cluster_h < MIN_BBOX_HEIGHT + || cluster_h as f64 > region_h as f64 * MAX_BBOX_HEIGHT_FRAC + { + continue; + } + + // Find bounding box of bright pixels within this cluster's row range + let bbox = match find_cluster_bbox( + ®ion, + region_w, + cluster.start_row, + cluster.end_row, + bright_threshold, + ) { + Some(b) => b, + None => continue, + }; + + if bbox.x1 - bbox.x0 < MIN_BBOX_WIDTH { + continue; + } + + // Step 3: Analyze text characteristics within bounding box + let analysis = analyze_text_cluster(®ion, region_w, &bbox, bright_threshold); + + let mut indicator_count = 0usize; + let mut indicators = Vec::new(); + + if analysis.bright_ratio >= MIN_BRIGHT_RATIO + && analysis.bright_ratio <= MAX_BRIGHT_RATIO + { + indicator_count += 1; + indicators.push(format!( + "bright pixel ratio {:.0}%", + analysis.bright_ratio * 100.0 + )); + } + + if analysis.text_row_fraction >= MIN_TEXT_ROWS_FRACTION { + indicator_count += 1; + indicators.push("horizontal text runs".to_string()); + } + + if analysis.is_bimodal { + indicator_count += 1; + indicators.push("bimodal luminance".to_string()); + } + + if debug { + eprintln!( + " [debug] Visible watermark {}: region_mean={:.1} bbox=({},{})..({},{}) bright_ratio={:.3} text_rows={:.3} bimodal={} indicators={}", + corner.name(), + region_mean, + bbox.x0 + ox, bbox.y0 + oy, bbox.x1 + ox, bbox.y1 + oy, + analysis.bright_ratio, + analysis.text_row_fraction, + analysis.is_bimodal, + indicator_count + ); + } + + if indicator_count < MIN_INDICATORS { + continue; + } + + let (confidence, msg_key) = if corner.is_known_ai_position() && indicator_count >= 3 { + (Confidence::Medium, "signal_visible_watermark_badge") + } else { + (Confidence::Low, "signal_visible_watermark_generic") + }; + + let indicators_str = indicators.join("; "); + + signals.push( + SignalBuilder::new(SignalSource::Watermark, confidence, msg_key) + .param("corner", corner.name()) + .param("indicators", &indicators_str) + .detail("corner", corner.name()) + .detail("region_mean_luminance", format!("{:.1}", analysis.mean_lum)) + .detail( + "bright_pixel_ratio", + format!("{:.3}", analysis.bright_ratio), + ) + .detail( + "text_row_fraction", + format!("{:.3}", analysis.text_row_fraction), + ) + .detail("indicator_count", indicator_count.to_string()) + .build(), + ); + + // One detection per corner is enough + break; + } + } + + Ok(signals) +} + +/// Compute the top-left origin of a corner region. +fn corner_offset(corner: Corner, w: u32, h: u32, rw: u32, rh: u32) -> (u32, u32) { + match corner { + Corner::TopLeft => (0, 0), + Corner::TopRight => (w.saturating_sub(rw), 0), + Corner::BottomLeft => (0, h.saturating_sub(rh)), + Corner::BottomRight => (w.saturating_sub(rw), h.saturating_sub(rh)), + } +} + +/// Extract a rectangular region of grayscale pixels. +fn extract_region(gray: &image::GrayImage, ox: u32, oy: u32, rw: u32, rh: u32) -> Vec { + let mut region = Vec::with_capacity((rw * rh) as usize); + for y in oy..oy + rh { + for x in ox..ox + rw { + region.push(gray.get_pixel(x, y).0[0]); + } + } + region +} + +/// Compute mean luminance of a region. +fn compute_mean(region: &[u8]) -> f64 { + if region.is_empty() { + return 128.0; + } + let sum: u64 = region.iter().map(|&v| v as u64).sum(); + sum as f64 / region.len() as f64 +} + +/// Identify which rows contain text-like bright pixel runs. +/// Returns a boolean per row. +fn find_text_rows(region: &[u8], rw: u32, rh: u32, bright_threshold: u8) -> Vec { + let mut text_rows = Vec::with_capacity(rh as usize); + for y in 0..rh { + let mut run_len = 0u32; + let mut runs_in_row = 0u32; + for x in 0..rw { + if region[(y * rw + x) as usize] >= bright_threshold { + run_len += 1; + } else { + if run_len >= MIN_RUN_LENGTH && run_len <= MAX_RUN_LENGTH { + runs_in_row += 1; + } + run_len = 0; + } + } + // Check final run + if run_len >= MIN_RUN_LENGTH && run_len <= MAX_RUN_LENGTH { + runs_in_row += 1; + } + text_rows.push(runs_in_row >= MIN_RUNS_PER_ROW); + } + text_rows +} + +/// Split text rows into compact clusters separated by gaps of non-text rows. +/// Each cluster is a contiguous (or near-contiguous) group of text rows. +fn find_text_clusters(text_rows: &[bool]) -> Vec { + let mut clusters = Vec::new(); + let mut start: Option = None; + let mut gap = 0u32; + + for (y, &is_text) in text_rows.iter().enumerate() { + let y = y as u32; + if is_text { + if start.is_none() { + start = Some(y); + } + gap = 0; + } else if let Some(s) = start { + gap += 1; + if gap > MAX_CLUSTER_GAP { + let end = y - gap; + if end > s + MIN_TEXT_ROW_COUNT { + clusters.push(TextCluster { + start_row: s, + end_row: end, + }); + } + start = None; + gap = 0; + } + } + } + + // Final cluster + if let Some(s) = start { + let end = text_rows.len() as u32 - gap; + if end > s + MIN_TEXT_ROW_COUNT { + clusters.push(TextCluster { + start_row: s, + end_row: end, + }); + } + } + + // Sort by size (largest first — most likely to be the real watermark) + clusters.sort_by(|a, b| { + let a_size = a.end_row - a.start_row; + let b_size = b.end_row - b.start_row; + b_size.cmp(&a_size) + }); + + clusters +} + +/// Find the bounding box of bright pixels within a row range. +fn find_cluster_bbox( + region: &[u8], + rw: u32, + start_row: u32, + end_row: u32, + bright_threshold: u8, +) -> Option { + let mut min_x = rw; + let mut max_x = 0u32; + + for y in start_row..end_row { + for x in 0..rw { + if region[(y * rw + x) as usize] >= bright_threshold { + min_x = min_x.min(x); + max_x = max_x.max(x); + } + } + } + + if max_x > min_x { + let pad_x = ((max_x - min_x) / 10).max(2); + let pad_y = ((end_row - start_row) / 10).max(1); + Some(TextBbox { + x0: min_x.saturating_sub(pad_x), + y0: start_row.saturating_sub(pad_y), + x1: (max_x + pad_x).min(rw), + y1: (end_row + pad_y).min(region.len() as u32 / rw), + }) + } else { + None + } +} + +/// Analyze text characteristics within the text cluster bounding box. +fn analyze_text_cluster( + region: &[u8], + rw: u32, + bbox: &TextBbox, + bright_threshold: u8, +) -> TextAnalysis { + let bw = bbox.x1 - bbox.x0; + let bh = bbox.y1 - bbox.y0; + + // Bright pixel ratio within bbox + let mut bright_count = 0u32; + let mut sum_lum = 0u64; + let total = bw * bh; + for y in bbox.y0..bbox.y1 { + for x in bbox.x0..bbox.x1 { + let v = region[(y * rw + x) as usize]; + sum_lum += v as u64; + if v >= bright_threshold { + bright_count += 1; + } + } + } + let bright_ratio = if total > 0 { + bright_count as f64 / total as f64 + } else { + 0.0 + }; + let mean_lum = if total > 0 { + sum_lum as f64 / total as f64 + } else { + 0.0 + }; + + // Text row fraction within bbox + let mut text_rows_in_bbox = 0u32; + for y in bbox.y0..bbox.y1 { + let mut run_len = 0u32; + let mut runs = 0u32; + for x in bbox.x0..bbox.x1 { + if region[(y * rw + x) as usize] >= bright_threshold { + run_len += 1; + } else { + if run_len >= MIN_RUN_LENGTH && run_len <= MAX_RUN_LENGTH { + runs += 1; + } + run_len = 0; + } + } + if run_len >= MIN_RUN_LENGTH && run_len <= MAX_RUN_LENGTH { + runs += 1; + } + if runs >= MIN_RUNS_PER_ROW { + text_rows_in_bbox += 1; + } + } + let text_row_fraction = if bh > 0 { + text_rows_in_bbox as f64 / bh as f64 + } else { + 0.0 + }; + + // Bimodal luminance check + let is_bimodal = check_bimodal(region, rw, bbox, bright_threshold); + + TextAnalysis { + bright_ratio, + text_row_fraction, + is_bimodal, + mean_lum, + } +} + +/// Check if the bounding box has a bimodal luminance distribution (background + text). +fn check_bimodal(region: &[u8], rw: u32, bbox: &TextBbox, threshold: u8) -> bool { + let mut dark_sum = 0u64; + let mut dark_count = 0u64; + let mut bright_sum = 0u64; + let mut bright_count = 0u64; + + for y in bbox.y0..bbox.y1 { + for x in bbox.x0..bbox.x1 { + let v = region[(y * rw + x) as usize] as u64; + if v >= threshold as u64 { + bright_sum += v; + bright_count += 1; + } else { + dark_sum += v; + dark_count += 1; + } + } + } + + if dark_count == 0 || bright_count == 0 { + return false; + } + + let dark_mean = dark_sum as f64 / dark_count as f64; + let bright_mean = bright_sum as f64 / bright_count as f64; + let total = (dark_count + bright_count) as f64; + let smaller = dark_count.min(bright_count) as f64; + + // Two clusters far apart, smaller cluster is 3-50% of total + (bright_mean - dark_mean) > BIMODAL_CENTER_DIFF + && smaller / total >= 0.03 + && smaller / total <= 0.50 +} + +#[cfg(test)] +mod tests { + use super::*; + use image::{GrayImage, Luma}; + + /// Save image to a temp file with .png extension so image::open() can detect the format. + fn save_tmp_png(img: &GrayImage) -> tempfile::TempDir { + let dir = tempfile::tempdir().unwrap(); + let path = dir.path().join("test.png"); + img.save(&path).unwrap(); + dir + } + + /// Create a test image with bright "text" runs in a corner. + fn make_image_with_text_overlay( + width: u32, + height: u32, + bg_lum: u8, + text_lum: u8, + text_x: u32, + text_y: u32, + text_w: u32, + text_h: u32, + ) -> GrayImage { + let mut img = GrayImage::from_pixel(width, height, Luma([bg_lum])); + + // Simulate text runs (alternating bright/dark horizontal segments) + for y in text_y..text_y + text_h { + if y >= height { + break; + } + let mut x = text_x + 2; + while x + 5 < text_x + text_w && x + 5 < width { + // Bright run of ~4px + for dx in 0..4 { + img.put_pixel(x + dx, y, Luma([text_lum])); + } + x += 7; // Gap between runs + } + } + + img + } + + #[test] + fn test_detects_text_in_top_left() { + // 800x600 image, gray background, white text overlay in top-left + let img = make_image_with_text_overlay(800, 600, 100, 220, 10, 10, 100, 30); + let dir = save_tmp_png(&img); + + let signals = detect(&dir.path().join("test.png")).unwrap(); + assert!( + !signals.is_empty(), + "Expected visible watermark detection for text in top-left" + ); + let desc = &signals[0].description; + assert!( + desc.contains("top-left"), + "Expected top-left corner, got: {}", + desc + ); + } + + #[test] + fn test_detects_text_in_bottom_right() { + // Bright text in bottom-right corner + let img = make_image_with_text_overlay(800, 600, 80, 230, 690, 565, 100, 25); + let dir = save_tmp_png(&img); + + let signals = detect(&dir.path().join("test.png")).unwrap(); + assert!( + !signals.is_empty(), + "Expected visible watermark detection for text in bottom-right" + ); + } + + #[test] + fn test_no_detection_on_uniform_image() { + let img = GrayImage::from_pixel(800, 600, Luma([128])); + let dir = save_tmp_png(&img); + + let signals = detect(&dir.path().join("test.png")).unwrap(); + assert!( + signals.is_empty(), + "Uniform image should not trigger detection" + ); + } + + #[test] + fn test_no_detection_on_small_image() { + let img = GrayImage::from_pixel(100, 100, Luma([128])); + let dir = save_tmp_png(&img); + + let signals = detect(&dir.path().join("test.png")).unwrap(); + assert!(signals.is_empty(), "Small image should be skipped"); + } + + #[test] + fn test_mean_computation() { + let data = vec![100u8; 100]; + let mean = compute_mean(&data); + assert!((mean - 100.0).abs() < 0.01); + } +} diff --git a/src/detector/watermark.rs b/src/detector/watermark.rs index 4248f82..f4d23cc 100644 --- a/src/detector/watermark.rs +++ b/src/detector/watermark.rs @@ -15,6 +15,12 @@ const MIN_INDICATORS: usize = 2; const NOISE_ASYMMETRY_THRESHOLD: f64 = 0.08; const BIT_AGREEMENT_THRESHOLD: f64 = 0.62; +// "Exceptionally strong" thresholds — when individual indicators far exceed their +// base thresholds, we upgrade confidence even with only 2/3 indicators firing. +const STRONG_BIT_AGREEMENT: f64 = 0.90; +const STRONG_ENERGY_SPREAD: f64 = 1.0; +const STRONG_NOISE_ASYMMETRY: f64 = 0.25; + pub fn detect(path: &Path) -> Result> { let img = image::open(path).context("Failed to open image for watermark analysis")?; let img = if img.width() > MAX_DIM || img.height() > MAX_DIM { @@ -33,6 +39,7 @@ pub fn detect(path: &Path) -> Result> { let debug = std::env::var("AIC_DEBUG").is_ok(); let mut indicators: Vec<&str> = Vec::new(); let mut details = Vec::new(); + let mut has_exceptionally_strong = false; let channels = extract_rgb_channels(&rgba, w, h); let cw = w - (w % 2); @@ -79,6 +86,9 @@ pub fn detect(path: &Path) -> Result> { details.push(("noise_asymmetry".to_string(), format!("{:.3}", asymmetry))); if asymmetry > NOISE_ASYMMETRY_THRESHOLD { indicators.push("channel noise asymmetry"); + if asymmetry > STRONG_NOISE_ASYMMETRY { + has_exceptionally_strong = true; + } } } @@ -135,6 +145,9 @@ pub fn detect(path: &Path) -> Result> { if best_agreement > BIT_AGREEMENT_THRESHOLD { indicators.push("cross-channel bit consistency"); details.push(("best_quant_step".to_string(), format!("{:.0}", best_q))); + if best_agreement > STRONG_BIT_AGREEMENT { + has_exceptionally_strong = true; + } } // Analysis 3: DWT residual energy ratio @@ -174,23 +187,33 @@ pub fn detect(path: &Path) -> Result> { } if ratio_spread > 0.25 { indicators.push("asymmetric DWT energy distribution"); + if ratio_spread > STRONG_ENERGY_SPREAD { + has_exceptionally_strong = true; + } } } } // Emit signal if indicators.len() >= MIN_INDICATORS { - let strength_key = if indicators.len() >= 3 { + let strong = indicators.len() >= 3 + || (indicators.len() >= 2 && has_exceptionally_strong); + let strength_key = if strong { "signal_watermark_strong" } else { "signal_watermark_moderate" }; + let confidence = if strong { + Confidence::Medium + } else { + Confidence::Low + }; let strength = i18n::t(strength_key, &[]); let indicators_str = indicators.join("; "); Ok(vec![SignalBuilder::new( SignalSource::Watermark, - Confidence::Low, + confidence, "signal_watermark_detected", ) .param("strength", &strength) @@ -418,10 +441,12 @@ pub fn detect_video(path: &Path) -> Result> { i, timestamp ); } + // Invisible watermark analysis match detect(&frame_path) { Ok(signals) if !signals.is_empty() => { // Re-wrap signals with video frame context for signal in signals { + let frame_confidence = signal.confidence; let indicators = signal .details .iter() @@ -431,7 +456,7 @@ pub fn detect_video(path: &Path) -> Result> { all_signals.push( SignalBuilder::new( SignalSource::Watermark, - Confidence::Low, + frame_confidence, "signal_video_frame_watermark", ) .param("frame", format!("{:.1}s", timestamp)) @@ -457,6 +482,19 @@ pub fn detect_video(path: &Path) -> Result> { } } } + + // Visible watermark analysis on the same frame + match super::visible_watermark::detect(&frame_path) { + Ok(signals) if !signals.is_empty() => { + all_signals.extend(signals); + } + Ok(_) => {} + Err(e) => { + if debug { + eprintln!(" [debug] Visible watermark video frame {}: {}", i, e); + } + } + } } } } diff --git a/src/known_tools.rs b/src/known_tools.rs index 29573d8..549db70 100644 --- a/src/known_tools.rs +++ b/src/known_tools.rs @@ -64,6 +64,7 @@ pub const AI_TOOL_PATTERNS: &[&str] = &[ "gemini", "jimeng", "即梦", + "dreamina", // New video generation tools "luma", "hailuo", @@ -97,5 +98,6 @@ mod tests { assert_eq!(match_ai_tool("Canon EOS R5"), None); assert_eq!(match_ai_tool("ComfyUI v1.2"), Some("comfyui")); assert_eq!(match_ai_tool("Midjourney v6"), Some("midjourney")); + assert_eq!(match_ai_tool("Dreamina by ByteDance"), Some("dreamina")); } } diff --git a/tests/fixtures/dreamina_visible_wm.jpg b/tests/fixtures/dreamina_visible_wm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..976a3fe97a4514cfb5d8edbedb442051c4d1d23a GIT binary patch literal 97405 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%0A2(*l8i5J>p@*a)v{gk(~&o_uItlQENimE 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 Pfv1EjQ(pgF5MJv_Y`KMH literal 0 HcmV?d00001 diff --git a/tests/watermark_detection.rs b/tests/watermark_detection.rs index 34bd606..dfc1de2 100644 --- a/tests/watermark_detection.rs +++ b/tests/watermark_detection.rs @@ -96,3 +96,47 @@ fn watermark_info_command() { .success() .stdout(predicate::str::contains("Watermark Analysis")); } + +#[test] +fn visible_watermark_dreamina_detected_with_deep() { + cargo_bin_cmd!("aic") + .args([ + "--lang", + "en", + "check", + "--deep", + "tests/fixtures/dreamina_visible_wm.jpg", + ]) + .assert() + .success() + .stdout(predicate::str::contains("MEDIUM")) + .stdout(predicate::str::contains("Visible AI watermark badge")); +} + +#[test] +fn visible_watermark_not_on_clean_image() { + cargo_bin_cmd!("aic") + .args([ + "--lang", + "en", + "check", + "--deep", + "tests/fixtures/clean_synthetic.png", + ]) + .assert() + .stdout(predicate::str::contains("Visible").not()); +} + +#[test] +fn visible_watermark_not_on_invisible_watermarked() { + cargo_bin_cmd!("aic") + .args([ + "--lang", + "en", + "check", + "--deep", + "tests/fixtures/watermarked_dwtdct.png", + ]) + .assert() + .stdout(predicate::str::contains("Visible").not()); +} From f9a7a2e4af496117c69bd08cbf616b5d57f57cb0 Mon Sep 17 00:00:00 2001 From: fernando_jacob Date: Fri, 13 Mar 2026 12:57:59 +0800 Subject: [PATCH 2/2] Fix CI: resolve rustfmt and clippy lint errors Co-Authored-By: Claude Opus 4.6 --- src/detector/visible_watermark.rs | 8 ++++---- src/detector/watermark.rs | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/detector/visible_watermark.rs b/src/detector/visible_watermark.rs index f49eb9e..f905f1f 100644 --- a/src/detector/visible_watermark.rs +++ b/src/detector/visible_watermark.rs @@ -295,14 +295,14 @@ fn find_text_rows(region: &[u8], rw: u32, rh: u32, bright_threshold: u8) -> Vec< if region[(y * rw + x) as usize] >= bright_threshold { run_len += 1; } else { - if run_len >= MIN_RUN_LENGTH && run_len <= MAX_RUN_LENGTH { + if (MIN_RUN_LENGTH..=MAX_RUN_LENGTH).contains(&run_len) { runs_in_row += 1; } run_len = 0; } } // Check final run - if run_len >= MIN_RUN_LENGTH && run_len <= MAX_RUN_LENGTH { + if (MIN_RUN_LENGTH..=MAX_RUN_LENGTH).contains(&run_len) { runs_in_row += 1; } text_rows.push(runs_in_row >= MIN_RUNS_PER_ROW); @@ -438,13 +438,13 @@ fn analyze_text_cluster( if region[(y * rw + x) as usize] >= bright_threshold { run_len += 1; } else { - if run_len >= MIN_RUN_LENGTH && run_len <= MAX_RUN_LENGTH { + if (MIN_RUN_LENGTH..=MAX_RUN_LENGTH).contains(&run_len) { runs += 1; } run_len = 0; } } - if run_len >= MIN_RUN_LENGTH && run_len <= MAX_RUN_LENGTH { + if (MIN_RUN_LENGTH..=MAX_RUN_LENGTH).contains(&run_len) { runs += 1; } if runs >= MIN_RUNS_PER_ROW { diff --git a/src/detector/watermark.rs b/src/detector/watermark.rs index f4d23cc..7acfe01 100644 --- a/src/detector/watermark.rs +++ b/src/detector/watermark.rs @@ -196,8 +196,7 @@ pub fn detect(path: &Path) -> Result> { // Emit signal if indicators.len() >= MIN_INDICATORS { - let strong = indicators.len() >= 3 - || (indicators.len() >= 2 && has_exceptionally_strong); + let strong = indicators.len() >= 3 || (indicators.len() >= 2 && has_exceptionally_strong); let strength_key = if strong { "signal_watermark_strong" } else {