This commit is contained in:
2025-07-01 17:42:33 +08:00
commit 6f59cd3c28
13 changed files with 1055 additions and 0 deletions

121
analyzer.py Normal file
View File

@ -0,0 +1,121 @@
import cv2
import numpy as np
import json
from datetime import datetime
class WatermarkAnalyzer:
def __init__(self, config_path="config/default_config.json"):
self.watermark_regions = []
self.selected_regions = []
self.config_path = config_path
self.load_config()
self._check_opencv_version()
def _check_opencv_version(self):
"""检查OpenCV版本确定是否支持显著性检测"""
self.has_saliency = hasattr(cv2, 'saliency')
if not self.has_saliency:
print("警告: 当前OpenCV版本不支持显著性检测将使用替代方法")
def load_config(self):
try:
with open(self.config_path, 'r') as f:
config = json.load(f)
self.inpaint_radius = config.get("inpaint_radius", 5)
self.inpaint_algorithm = config.get("inpaint_algorithm", cv2.INPAINT_TELEA)
self.dilate_size = config.get("dilate_size", 3)
self.use_adaptive_mask = config.get("use_adaptive_mask", True)
self.text_threshold = config.get("text_threshold", 180)
self.min_text_area = config.get("min_text_area", 100)
self.text_color_range = tuple(
tuple(c) for c in config.get("text_color_range", ((50, 50, 50), (180, 180, 180))))
self.stamp_color_range = tuple(
tuple(c) for c in config.get("stamp_color_range", ((0, 0, 100), (100, 100, 255))))
self.saliency_threshold = config.get("saliency_threshold", 0.5)
self.edge_threshold = config.get("edge_threshold", 100)
self.use_mser = config.get("use_mser", True)
self.use_color_filter = config.get("use_color_filter", True)
self.use_texture_analysis = config.get("use_texture_analysis", True)
except Exception as e:
print(f"加载配置失败: {e}")
self.reset_to_defaults()
# ... 其他方法保持不变 ...
def _detect_by_saliency(self, img):
"""基于显著性检测水印 - 兼容旧版OpenCV"""
if self.has_saliency:
# 使用标准显著性检测(如果支持)
try:
saliency = cv2.saliency.StaticSaliencySpectralResidual_create()
_, saliency_map = saliency.computeSaliency(img)
# 阈值处理
_, saliency_mask = cv2.threshold(saliency_map * 255, self.saliency_threshold * 255, 255,
cv2.THRESH_BINARY)
saliency_mask = saliency_mask.astype(np.uint8)
# 形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
closed = cv2.morphologyEx(saliency_mask, cv2.MORPH_CLOSE, kernel)
# 查找轮廓
contours, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
regions = []
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
area = w * h
if area > self.min_text_area * 2 and area < img.shape[0] * img.shape[1] * 0.1:
regions.append({
'type': 'saliency',
'position': (x, y, w, h),
'confidence': 0.7,
'contour': contour
})
return regions
except Exception as e:
print(f"显著性检测失败: {e}")
self.has_saliency = False # 标记为不支持,下次使用替代方法
# 替代方法:使用亮度变化检测
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯模糊减少噪声
blurred = cv2.GaussianBlur(gray, (15, 15), 0)
# 计算拉普拉斯算子检测边缘
laplacian = cv2.Laplacian(blurred, cv2.CV2.CV_64F)
laplacian = np.uint8(np.absolute(laplacian))
# 阈值处理
_, threshold = cv2.threshold(laplacian, 30, 255, cv2.THRESH_BINARY)
# 形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
closed = cv2.morphologyEx(threshold, cv2.MORPH_CLOSE, kernel)
# 查找轮廓
contours, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
regions = []
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
area = w * h
if area > self.min_text_area * 2 and area < img.shape[0] * img.shape[1] * 0.1:
# 计算轮廓的紧致度
perimeter = cv2.arcLength(contour, True)
compactness = 4 * np.pi * area / (perimeter * perimeter) if perimeter > 0 else 0
# 水印通常具有中等紧致度
if 0.1 < compactness < 0.9:
regions.append({
'type': 'contrast',
'position': (x, y, w, h),
'confidence': 0.6,
'contour': contour
})
return regions