抗哈希方法,低效
This commit is contained in:
parent
276518f7de
commit
49f6deeec0
@ -10,6 +10,7 @@ import numpy as np
|
||||
from PIL import ImageEnhance, ImageFilter
|
||||
from .output_handler import OutputHandler
|
||||
import io
|
||||
import math
|
||||
|
||||
# 尝试导入 scipy,如果失败则标记
|
||||
try:
|
||||
@ -456,7 +457,7 @@ class PosterNotesCreator:
|
||||
|
||||
def apply_smart_crop_resize(self, image: Image.Image, strength: str = "medium") -> Image.Image:
|
||||
"""
|
||||
应用智能裁剪和重缩放来抵抗哈希算法
|
||||
应用智能裁剪和重缩放来抵抗哈希算法 (增强版)
|
||||
|
||||
Args:
|
||||
image: 输入图像
|
||||
@ -469,13 +470,15 @@ class PosterNotesCreator:
|
||||
original_width, original_height = image.size
|
||||
logger.debug(f"应用智能裁剪+重缩放 (强度: {strength}), 原始尺寸: {original_width}x{original_height}")
|
||||
|
||||
# 根据强度决定裁剪量 (0-3 像素)
|
||||
# 根据强度决定裁剪量 (增强)
|
||||
if strength == "low":
|
||||
max_crop = 1
|
||||
max_crop = 3 # 原为 1
|
||||
elif strength == "high":
|
||||
max_crop = 3
|
||||
max_crop = 10 # 原为 3
|
||||
else: # medium
|
||||
max_crop = 2
|
||||
max_crop = 6 # 原为 2
|
||||
|
||||
logger.debug(f"增强型智能裁剪: max_crop = {max_crop} 像素")
|
||||
|
||||
# 随机决定每边的裁剪量
|
||||
crop_left = random.randint(0, max_crop)
|
||||
@ -491,7 +494,19 @@ class PosterNotesCreator:
|
||||
|
||||
# 确保裁剪后尺寸至少为1x1
|
||||
if left >= right or top >= bottom:
|
||||
logger.warning("智能裁剪计算无效,跳过此步骤。")
|
||||
logger.warning("智能裁剪计算无效(裁剪过多),尝试使用较小裁剪量。")
|
||||
# 尝试减小裁剪量再次计算
|
||||
safe_max_crop = min(original_width // 4, original_height // 4, max_crop) # 保证不裁掉整个图
|
||||
crop_left = random.randint(0, safe_max_crop)
|
||||
crop_top = random.randint(0, safe_max_crop)
|
||||
crop_right = random.randint(0, safe_max_crop)
|
||||
crop_bottom = random.randint(0, safe_max_crop)
|
||||
left = crop_left
|
||||
top = crop_top
|
||||
right = original_width - crop_right
|
||||
bottom = original_height - crop_bottom
|
||||
if left >= right or top >= bottom: # 再次失败则跳过
|
||||
logger.error("智能裁剪再次失败,跳过此步骤。")
|
||||
return image
|
||||
|
||||
logger.debug(f" 裁剪参数: L={crop_left}, T={crop_top}, R={crop_right}, B={crop_bottom}")
|
||||
@ -575,40 +590,40 @@ class PosterNotesCreator:
|
||||
"""
|
||||
logger.debug("移除图像元数据...")
|
||||
try:
|
||||
# 从当前图像对象的像素数据创建一个新的Image对象
|
||||
# 这确保我们使用的是内存中修改后的数据
|
||||
# 保留原始格式信息,如果可用
|
||||
img_format = image.format if hasattr(image, 'format') else 'PNG'
|
||||
|
||||
# 如果图像有alpha通道,需要正确处理
|
||||
# 确保图像处于适合保存的模式(例如RGB)
|
||||
if image.mode == 'RGBA':
|
||||
# 创建一个白色背景,然后粘贴带有alpha的图像
|
||||
background = Image.new("RGB", image.size, (255, 255, 255))
|
||||
background.paste(image, mask=image.split()[3]) # 3 is the alpha channel
|
||||
image_to_save = background
|
||||
img_format = 'JPEG' # 通常去除alpha后存为JPEG
|
||||
elif image.mode == 'P':
|
||||
# 带调色板的图像转换为RGB
|
||||
image_to_save = image.convert('RGB')
|
||||
img_format = 'JPEG'
|
||||
else:
|
||||
elif image.mode == 'L':
|
||||
# 灰度图通常可以保存为JPEG或PNG
|
||||
image_to_save = image
|
||||
|
||||
# 保存到内存缓冲区
|
||||
data = io.BytesIO()
|
||||
# 确保保存时指定质量参数,避免默认压缩导致意外变化
|
||||
if img_format == 'JPEG':
|
||||
image_to_save.save(data, format='JPEG', quality=95) # 使用高质量JPEG
|
||||
elif image.mode == 'RGB':
|
||||
image_to_save = image # 已经是RGB,直接使用
|
||||
else:
|
||||
# 对于PNG等无损格式,不需要质量参数
|
||||
image_to_save.save(data, format=img_format)
|
||||
logger.warning(f"未知的图像模式 {image.mode},尝试转换为RGB进行元数据剥离。")
|
||||
image_to_save = image.convert('RGB')
|
||||
|
||||
# 保存到内存缓冲区,强制使用JPEG格式以剥离元数据
|
||||
data = io.BytesIO()
|
||||
# --- FIX: 强制使用JPEG格式保存到缓冲区 ---
|
||||
save_format = 'JPEG'
|
||||
logger.debug(f"强制使用 {save_format} 格式保存以剥离元数据")
|
||||
image_to_save.save(data, format=save_format, quality=95) # 使用高质量JPEG
|
||||
# --- END FIX ---
|
||||
|
||||
data.seek(0) # 重置缓冲区指针
|
||||
reloaded_image = Image.open(data)
|
||||
logger.debug("元数据移除成功。")
|
||||
return reloaded_image
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"移除元数据时出错: {e}")
|
||||
logger.error(traceback.format_exc()) # 打印详细错误
|
||||
return image # 出错时返回原图
|
||||
|
||||
def apply_overlay_noise(self, image: Image.Image, alpha: int = 10, noise_type: str = 'uniform') -> Image.Image:
|
||||
@ -664,66 +679,561 @@ class PosterNotesCreator:
|
||||
logger.error(traceback.format_exc()) # 打印详细错误
|
||||
return image # 出错时返回原图
|
||||
|
||||
def optimize_anti_hash_methods(self, image: Image.Image, strength: str = "medium") -> Image.Image:
|
||||
"""优化后的哈希对抗方法,策略: 裁剪缩放 + DCT噪声 + 叠加噪声"""
|
||||
logger.info(f"--- 开始优化抗哈希方法 (强度: {strength}) - 叠加噪声策略 ---")
|
||||
def apply_ahash_specific_disruption(self, image: Image.Image, strength: str = "medium") -> Image.Image:
|
||||
"""
|
||||
专门针对aHash的干扰方法:插入亮度带 (增强版)
|
||||
Args:
|
||||
image: 输入图像
|
||||
strength: 处理强度 ('low', 'medium', 'high')
|
||||
Returns:
|
||||
处理后的图像
|
||||
"""
|
||||
try:
|
||||
# 设定强度相关参数 (增强)
|
||||
if strength == "low":
|
||||
intensity = 0.08 # 原为 0.02
|
||||
bands = 2
|
||||
elif strength == "high":
|
||||
intensity = 0.18 # 原为 0.04
|
||||
bands = 4
|
||||
else: # medium
|
||||
intensity = 0.12 # 原为 0.03
|
||||
bands = 3
|
||||
|
||||
logger.debug(f"应用aHash特定干扰 (亮度带) (增强版), 强度:{strength}, 条带数:{bands}, 强度因子:{intensity:.3f}")
|
||||
|
||||
# ... (其余逻辑不变) ...
|
||||
result = image.copy()
|
||||
width, height = result.size
|
||||
pixels = result.load()
|
||||
|
||||
is_horizontal = random.choice([True, False])
|
||||
band_positions = []
|
||||
if is_horizontal:
|
||||
for _ in range(bands):
|
||||
base_pos = random.randint(0, height - 1)
|
||||
band_positions.append(base_pos)
|
||||
else:
|
||||
for _ in range(bands):
|
||||
base_pos = random.randint(0, width - 1)
|
||||
band_positions.append(base_pos)
|
||||
|
||||
for y_idx in range(height): # Renamed y to y_idx to avoid conflict
|
||||
for x_idx in range(width): # Renamed x to x_idx to avoid conflict
|
||||
is_on_band = False
|
||||
if is_horizontal:
|
||||
for pos in band_positions:
|
||||
if abs(y_idx - pos) <= 1:
|
||||
is_on_band = True
|
||||
break
|
||||
else:
|
||||
for pos in band_positions:
|
||||
if abs(x_idx - pos) <= 1:
|
||||
is_on_band = True
|
||||
break
|
||||
|
||||
if is_on_band:
|
||||
pixel = pixels[x_idx, y_idx]
|
||||
if isinstance(pixel, int):
|
||||
r_val = g_val = b_val = pixel # Renamed r,g,b to r_val, g_val, b_val
|
||||
is_rgb = False
|
||||
else:
|
||||
if len(pixel) >= 3:
|
||||
r_val, g_val, b_val = pixel[0], pixel[1], pixel[2]
|
||||
is_rgb = True
|
||||
else:
|
||||
continue
|
||||
|
||||
factor = 1.0 + intensity * (1 if random.random() > 0.5 else -1)
|
||||
r_val, g_val, b_val = int(r_val * factor), int(g_val * factor), int(b_val * factor)
|
||||
r_val, g_val, b_val = max(0, min(255, r_val)), max(0, min(255, g_val)), max(0, min(255, b_val))
|
||||
|
||||
if is_rgb:
|
||||
if len(pixel) == 4:
|
||||
pixels[x_idx, y_idx] = (r_val, g_val, b_val, pixel[3])
|
||||
else:
|
||||
pixels[x_idx, y_idx] = (r_val, g_val, b_val)
|
||||
else:
|
||||
pixels[x_idx, y_idx] = r_val
|
||||
|
||||
logger.debug(f"aHash特定干扰完成: {'水平' if is_horizontal else '垂直'}亮度带")
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"应用aHash特定干扰时出错: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return image
|
||||
|
||||
def apply_dhash_specific_disruption(self, image: Image.Image, strength: str = "medium") -> Image.Image:
|
||||
"""
|
||||
专门针对dHash的干扰方法:梯度反向模式 (增强版)
|
||||
Args:
|
||||
image: 输入图像
|
||||
strength: 处理强度 ('low', 'medium', 'high')
|
||||
Returns:
|
||||
处理后的图像
|
||||
"""
|
||||
try:
|
||||
# 设定强度相关参数 (增强)
|
||||
if strength == "low":
|
||||
gradient_strength = 0.08 # 原为 0.02
|
||||
regions = 2
|
||||
elif strength == "high":
|
||||
gradient_strength = 0.18 # 原为 0.04
|
||||
regions = 4
|
||||
else: # medium
|
||||
gradient_strength = 0.12 # 原为 0.03
|
||||
regions = 3
|
||||
|
||||
logger.debug(f"应用dHash特定干扰 (梯度反向) (增强版), 强度:{strength}, 区域数:{regions}, 梯度强度:{gradient_strength:.3f}")
|
||||
|
||||
# ... (其余逻辑不变, 确保使用增强的 gradient_strength) ...
|
||||
result = image.copy()
|
||||
width, height = result.size
|
||||
|
||||
for _ in range(regions):
|
||||
region_w = random.randint(width//12, width//8) # Renamed region_width to region_w
|
||||
region_h = random.randint(height//12, height//8) # Renamed region_height to region_h
|
||||
region_x_coord = random.randint(0, width - region_w) # Renamed region_x to region_x_coord
|
||||
region_y_coord = random.randint(0, height - region_h) # Renamed region_y to region_y_coord
|
||||
|
||||
region = result.crop((region_x_coord, region_y_coord, region_x_coord + region_w, region_y_coord + region_h))
|
||||
region_array = np.array(region)
|
||||
is_rgb = len(region_array.shape) == 3
|
||||
|
||||
if is_rgb:
|
||||
gray_region = np.mean(region_array, axis=2).astype(np.uint8)
|
||||
else:
|
||||
gray_region = region_array
|
||||
|
||||
h_gradients = np.zeros_like(gray_region, dtype=np.int16)
|
||||
v_gradients = np.zeros_like(gray_region, dtype=np.int16)
|
||||
|
||||
for y_idx in range(region_h): # Renamed y to y_idx
|
||||
for x_idx in range(region_w-1): # Renamed x to x_idx
|
||||
h_gradients[y_idx, x_idx] = int(gray_region[y_idx, x_idx+1]) - int(gray_region[y_idx, x_idx])
|
||||
|
||||
for y_idx in range(region_h-1): # Renamed y to y_idx
|
||||
for x_idx in range(region_w): # Renamed x to x_idx
|
||||
v_gradients[y_idx, x_idx] = int(gray_region[y_idx+1, x_idx]) - int(gray_region[y_idx, x_idx])
|
||||
|
||||
modified_region = region_array.astype(np.float32)
|
||||
for y_idx in range(region_h): # Renamed y to y_idx
|
||||
for x_idx in range(region_w): # Renamed x to x_idx
|
||||
if x_idx < region_w-1 and abs(h_gradients[y_idx, x_idx]) > 5:
|
||||
h_change = -h_gradients[y_idx, x_idx] * gradient_strength
|
||||
if is_rgb:
|
||||
for c_channel in range(3): # Renamed c to c_channel
|
||||
modified_region[y_idx, x_idx+1, c_channel] = np.clip(
|
||||
modified_region[y_idx, x_idx+1, c_channel] + h_change/2, 0, 255)
|
||||
modified_region[y_idx, x_idx, c_channel] = np.clip(
|
||||
modified_region[y_idx, x_idx, c_channel] - h_change/2, 0, 255)
|
||||
else:
|
||||
modified_region[y_idx, x_idx+1] = np.clip(
|
||||
modified_region[y_idx, x_idx+1] + h_change/2, 0, 255)
|
||||
modified_region[y_idx, x_idx] = np.clip(
|
||||
modified_region[y_idx, x_idx] - h_change/2, 0, 255)
|
||||
|
||||
if y_idx < region_h-1 and abs(v_gradients[y_idx, x_idx]) > 5:
|
||||
v_change = -v_gradients[y_idx, x_idx] * gradient_strength
|
||||
if is_rgb:
|
||||
for c_channel in range(3): # Renamed c to c_channel
|
||||
modified_region[y_idx+1, x_idx, c_channel] = np.clip(
|
||||
modified_region[y_idx+1, x_idx, c_channel] + v_change/2, 0, 255)
|
||||
modified_region[y_idx, x_idx, c_channel] = np.clip(
|
||||
modified_region[y_idx, x_idx, c_channel] - v_change/2, 0, 255)
|
||||
else:
|
||||
modified_region[y_idx+1, x_idx] = np.clip(
|
||||
modified_region[y_idx+1, x_idx] + v_change/2, 0, 255)
|
||||
modified_region[y_idx, x_idx] = np.clip(
|
||||
modified_region[y_idx, x_idx] - v_change/2, 0, 255)
|
||||
|
||||
modified_region = modified_region.astype(np.uint8)
|
||||
modified_region_image = Image.fromarray(modified_region)
|
||||
result.paste(modified_region_image, (region_x_coord, region_y_coord))
|
||||
|
||||
logger.debug(f"dHash特定干扰完成: 在{regions}个区域应用梯度反向")
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"应用dHash特定干扰时出错: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return image
|
||||
|
||||
def apply_phash_specific_disruption(self, image: Image.Image, strength: str = "medium") -> Image.Image:
|
||||
"""
|
||||
专门针对pHash的干扰方法:定向DCT系数修改 (增强版)
|
||||
Args:
|
||||
image: 输入图像
|
||||
strength: 处理强度 ('low', 'medium', 'high')
|
||||
Returns:
|
||||
处理后的图像
|
||||
"""
|
||||
if not SCIPY_AVAILABLE:
|
||||
logger.warning("Scipy 未安装,无法执行pHash专用干扰。请运行 'pip install scipy'")
|
||||
return image
|
||||
|
||||
try:
|
||||
# 设定强度相关参数 (增强)
|
||||
if strength == "low":
|
||||
intensity = 0.20 # 原为 0.10
|
||||
key_positions_count = 4
|
||||
elif strength == "high":
|
||||
intensity = 0.40 # 原为 0.20
|
||||
key_positions_count = 8
|
||||
else: # medium
|
||||
intensity = 0.30 # 原为 0.15
|
||||
key_positions_count = 6
|
||||
|
||||
logger.debug(f"应用pHash特定干扰 (定向DCT干扰) (增强版), 强度:{strength}, 密度:{key_positions_count}, 强度因子:{intensity:.2f}")
|
||||
|
||||
# ... (其余逻辑不变, 确保使用增强的 intensity) ...
|
||||
gray_image = image.convert('L')
|
||||
img_array_np = np.array(gray_image) # Renamed img_array to img_array_np
|
||||
h_img, w_img = img_array_np.shape # Renamed h,w to h_img,w_img
|
||||
|
||||
resized_array = np.array(gray_image.resize((32, 32), Image.LANCZOS))
|
||||
dct_array = dct(dct(resized_array.T, norm='ortho').T, norm='ortho')
|
||||
|
||||
key_positions = []
|
||||
for i_pos in range(1, 8): # Renamed i to i_pos
|
||||
for j_pos in range(1, 8): # Renamed j to j_pos
|
||||
key_positions.append((i_pos, j_pos))
|
||||
|
||||
selected_positions = random.sample(key_positions, k=min(len(key_positions), key_positions_count))
|
||||
|
||||
block_h_size, block_w_size = h_img // 32, w_img // 32 # Renamed block_height, block_width
|
||||
|
||||
for dct_y_coord, dct_x_coord in selected_positions: # Renamed dct_y, dct_x
|
||||
orig_y_coord = dct_y_coord * block_h_size # Renamed orig_y to orig_y_coord
|
||||
orig_x_coord = dct_x_coord * block_w_size # Renamed orig_x to orig_x_coord
|
||||
|
||||
pattern_s = min(block_h_size, block_w_size) # Renamed pattern_size to pattern_s
|
||||
for y_off in range(pattern_s): # Renamed y_offset to y_off
|
||||
for x_off in range(pattern_s): # Renamed x_offset to x_off
|
||||
y_val = orig_y_coord + y_off # Renamed y to y_val
|
||||
x_val = orig_x_coord + x_off # Renamed x to x_val
|
||||
if 0 <= y_val < h_img and 0 <= x_val < w_img:
|
||||
offset_val = intensity * 20 * math.sin(2 * math.pi * (y_off / pattern_s)) * \
|
||||
math.cos(2 * math.pi * (x_off / pattern_s)) # Renamed offset to offset_val
|
||||
img_array_np[y_val, x_val] = np.clip(img_array_np[y_val, x_val] + offset_val, 0, 255)
|
||||
|
||||
result_img = Image.fromarray(img_array_np.astype(np.uint8)) # Renamed result to result_img
|
||||
|
||||
if image.mode != 'L':
|
||||
r_channel, g_channel, b_channel = image.split()[:3] # Renamed r,g,b to r_channel, g_channel, b_channel
|
||||
|
||||
diff_img = ImageChops.difference(gray_image, result_img) # Renamed diff to diff_img
|
||||
diff_array_np = np.array(diff_img) # Renamed diff_array to diff_array_np
|
||||
|
||||
r_array_np = np.array(r_channel) # Renamed r_array to r_array_np
|
||||
g_array_np = np.array(g_channel) # Renamed g_array to g_array_np
|
||||
b_array_np = np.array(b_channel) # Renamed b_array to b_array_np
|
||||
|
||||
transfer_factor = 0.8
|
||||
r_array_np = np.clip(r_array_np + diff_array_np * transfer_factor, 0, 255).astype(np.uint8)
|
||||
g_array_np = np.clip(g_array_np + diff_array_np * transfer_factor, 0, 255).astype(np.uint8)
|
||||
b_array_np = np.clip(b_array_np + diff_array_np * transfer_factor, 0, 255).astype(np.uint8)
|
||||
|
||||
r_new_img = Image.fromarray(r_array_np) # Renamed r_new to r_new_img
|
||||
g_new_img = Image.fromarray(g_array_np) # Renamed g_new to g_new_img
|
||||
b_new_img = Image.fromarray(b_array_np) # Renamed b_new to b_new_img
|
||||
|
||||
if image.mode == 'RGBA':
|
||||
alpha_channel = image.split()[3] # Renamed a to alpha_channel
|
||||
result_img = Image.merge('RGBA', (r_new_img, g_new_img, b_new_img, alpha_channel))
|
||||
else:
|
||||
result_img = Image.merge('RGB', (r_new_img, g_new_img, b_new_img))
|
||||
|
||||
logger.debug(f"pHash特定干扰完成: 修改了{len(selected_positions)}个DCT关键位置")
|
||||
return result_img
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"应用pHash特定干扰时出错: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return image
|
||||
|
||||
def apply_block_based_perturbations(self, image: Image.Image, block_size: int = 16, strength: str = "medium") -> Image.Image:
|
||||
"""
|
||||
对图像各个块应用不同的、独立的干扰策略 (增强版)
|
||||
Args:
|
||||
image: 输入图像
|
||||
block_size: 块大小
|
||||
strength: 处理强度 ('low', 'medium', 'high')
|
||||
Returns:
|
||||
处理后的图像
|
||||
"""
|
||||
try:
|
||||
# 设定强度相关参数 (增强)
|
||||
if strength == "low":
|
||||
factor_range = 0.08 # 原为 0.03
|
||||
skip_prob = 0.5
|
||||
elif strength == "high":
|
||||
factor_range = 0.18 # 原为 0.06
|
||||
skip_prob = 0.2
|
||||
else: # medium
|
||||
factor_range = 0.12 # 原为 0.045
|
||||
skip_prob = 0.35
|
||||
|
||||
logger.debug(f"应用块级混合干扰 (增强版), 块大小:{block_size}, 强度:{strength}, 因子范围:{factor_range:.3f}")
|
||||
|
||||
# ... (其余逻辑不变, 确保使用增强的 factor_range) ...
|
||||
result = image.copy() # Renamed result_img to result
|
||||
width, height = image.size
|
||||
img_array = np.array(result)
|
||||
is_rgb = len(img_array.shape) == 3
|
||||
|
||||
strategies = ['brightness', 'contrast', 'hue_shift', 'gradient_flip', 'micro_pattern', 'skip']
|
||||
processed_blocks = 0
|
||||
skipped_blocks = 0
|
||||
|
||||
for y_coord in range(0, height, block_size): # Renamed y to y_coord
|
||||
for x_coord in range(0, width, block_size): # Renamed x to x_coord
|
||||
block_w = min(block_size, width - x_coord)
|
||||
block_h = min(block_size, height - y_coord)
|
||||
|
||||
if block_w < 4 or block_h < 4:
|
||||
continue
|
||||
|
||||
current_strategy = 'skip' if random.random() < skip_prob else random.choice([s for s in strategies if s != 'skip']) # Renamed strategy to current_strategy
|
||||
|
||||
if is_rgb:
|
||||
current_block = img_array[y_coord:y_coord+block_h, x_coord:x_coord+block_w, :] # Renamed block to current_block
|
||||
else:
|
||||
current_block = img_array[y_coord:y_coord+block_h, x_coord:x_coord+block_w]
|
||||
|
||||
if current_strategy == 'skip':
|
||||
skipped_blocks +=1
|
||||
elif current_strategy == 'brightness':
|
||||
factor = 1.0 + random.uniform(-factor_range, factor_range)
|
||||
current_block = (current_block.astype(float) * factor).clip(0, 255).astype(np.uint8)
|
||||
processed_blocks += 1
|
||||
elif current_strategy == 'contrast':
|
||||
factor = 1.0 + random.uniform(-factor_range, factor_range)
|
||||
if is_rgb:
|
||||
mean_val = np.mean(current_block, axis=(0, 1), keepdims=True)
|
||||
current_block = (((current_block.astype(float) - mean_val) * factor) + mean_val).clip(0, 255).astype(np.uint8)
|
||||
else:
|
||||
mean_val = np.mean(current_block)
|
||||
current_block = (((current_block.astype(float) - mean_val) * factor) + mean_val).clip(0, 255).astype(np.uint8)
|
||||
processed_blocks += 1
|
||||
elif current_strategy == 'hue_shift' and is_rgb:
|
||||
r_factor = 1.0 - random.uniform(0, factor_range/2)
|
||||
g_factor = 1.0 - random.uniform(0, factor_range/2)
|
||||
b_factor = 1.0 - random.uniform(0, factor_range/2)
|
||||
r_ch, g_ch, b_ch = current_block[:,:,0], current_block[:,:,1], current_block[:,:,2] # Renamed r,g,b to r_ch,g_ch,b_ch
|
||||
current_block[:,:,0] = (r_ch * r_factor + g_ch * (1-r_factor)).clip(0, 255).astype(np.uint8)
|
||||
current_block[:,:,1] = (g_ch * g_factor + b_ch * (1-g_factor)).clip(0, 255).astype(np.uint8)
|
||||
current_block[:,:,2] = (b_ch * b_factor + r_ch * (1-b_factor)).clip(0, 255).astype(np.uint8)
|
||||
processed_blocks += 1
|
||||
elif current_strategy == 'gradient_flip':
|
||||
if block_w > 2 and block_h > 2:
|
||||
mid_w, mid_h = block_w // 2, block_h // 2
|
||||
pattern_s = min(mid_w, mid_h) # Renamed pattern_size to pattern_s
|
||||
for by_idx in range(1, pattern_s-1): # Renamed by to by_idx
|
||||
for bx_idx in range(1, pattern_s-1): # Renamed bx to bx_idx
|
||||
if is_rgb:
|
||||
curr_val = np.mean(current_block[by_idx, bx_idx, :]) # Renamed curr to curr_val
|
||||
right_val = np.mean(current_block[by_idx, bx_idx+1, :]) # Renamed right to right_val
|
||||
below_val = np.mean(current_block[by_idx+1, bx_idx, :]) # Renamed below to below_val
|
||||
if abs(curr_val - right_val) > 5:
|
||||
diff_val = (curr_val - right_val) * factor_range # Renamed diff to diff_val
|
||||
current_block[by_idx, bx_idx, :] = np.clip(current_block[by_idx, bx_idx, :] - diff_val/2, 0, 255).astype(np.uint8)
|
||||
current_block[by_idx, bx_idx+1, :] = np.clip(current_block[by_idx, bx_idx+1, :] + diff_val/2, 0, 255).astype(np.uint8)
|
||||
if abs(curr_val - below_val) > 5:
|
||||
diff_val = (curr_val - below_val) * factor_range
|
||||
current_block[by_idx, bx_idx, :] = np.clip(current_block[by_idx, bx_idx, :] - diff_val/2, 0, 255).astype(np.uint8)
|
||||
current_block[by_idx+1, bx_idx, :] = np.clip(current_block[by_idx+1, bx_idx, :] + diff_val/2, 0, 255).astype(np.uint8)
|
||||
else:
|
||||
curr_val = float(current_block[by_idx, bx_idx])
|
||||
right_val = float(current_block[by_idx, bx_idx+1])
|
||||
below_val = float(current_block[by_idx+1, bx_idx])
|
||||
if abs(curr_val - right_val) > 5:
|
||||
diff_val = (curr_val - right_val) * factor_range
|
||||
current_block[by_idx, bx_idx] = np.clip(current_block[by_idx, bx_idx] - diff_val/2, 0, 255).astype(np.uint8)
|
||||
current_block[by_idx, bx_idx+1] = np.clip(current_block[by_idx, bx_idx+1] + diff_val/2, 0, 255).astype(np.uint8)
|
||||
if abs(curr_val - below_val) > 5:
|
||||
diff_val = (curr_val - below_val) * factor_range
|
||||
current_block[by_idx, bx_idx] = np.clip(current_block[by_idx, bx_idx] - diff_val/2, 0, 255).astype(np.uint8)
|
||||
current_block[by_idx+1, bx_idx] = np.clip(current_block[by_idx+1, bx_idx] + diff_val/2, 0, 255).astype(np.uint8)
|
||||
processed_blocks += 1
|
||||
elif current_strategy == 'micro_pattern':
|
||||
pattern_type = random.choice(['dot', 'line', 'cross'])
|
||||
center_y_coord, center_x_coord = block_h // 2, block_w // 2 # Renamed center_y, center_x
|
||||
pattern_coords = []
|
||||
if pattern_type == 'dot':
|
||||
pattern_coords = [(center_y_coord, center_x_coord)]
|
||||
elif pattern_type == 'line':
|
||||
if random.choice([True, False]):
|
||||
pattern_coords = [(center_y_coord, cx_val) for cx_val in range(center_x_coord-1, center_x_coord+2)] # Renamed cx to cx_val
|
||||
else:
|
||||
pattern_coords = [(cy_val, center_x_coord) for cy_val in range(center_y_coord-1, center_y_coord+2)] # Renamed cy to cy_val
|
||||
else:
|
||||
pattern_coords.extend([(center_y_coord, cx_val) for cx_val in range(center_x_coord-1, center_x_coord+2)])
|
||||
pattern_coords.extend([(cy_val, center_x_coord) for cy_val in range(center_y_coord-1, center_y_coord+2) if (cy_val, center_x_coord) not in pattern_coords])
|
||||
|
||||
pattern_strength = random.uniform(factor_range*50, factor_range*100)
|
||||
for py_coord, px_coord in pattern_coords: # Renamed py,px to py_coord,px_coord
|
||||
if 0 <= py_coord < block_h and 0 <= px_coord < block_w:
|
||||
if is_rgb:
|
||||
target_channel = random.randint(0, 2) # Renamed channel to target_channel
|
||||
if random.choice([True, False]):
|
||||
current_block[py_coord, px_coord, target_channel] = np.clip(current_block[py_coord, px_coord, target_channel] + pattern_strength, 0, 255).astype(np.uint8)
|
||||
else:
|
||||
current_block[py_coord, px_coord, target_channel] = np.clip(current_block[py_coord, px_coord, target_channel] - pattern_strength, 0, 255).astype(np.uint8)
|
||||
else:
|
||||
if random.choice([True, False]):
|
||||
current_block[py_coord, px_coord] = np.clip(current_block[py_coord, px_coord] + pattern_strength, 0, 255).astype(np.uint8)
|
||||
else:
|
||||
current_block[py_coord, px_coord] = np.clip(current_block[py_coord, px_coord] - pattern_strength, 0, 255).astype(np.uint8)
|
||||
processed_blocks += 1
|
||||
|
||||
if is_rgb:
|
||||
img_array[y_coord:y_coord+block_h, x_coord:x_coord+block_w, :] = current_block
|
||||
else:
|
||||
img_array[y_coord:y_coord+block_h, x_coord:x_coord+block_w] = current_block
|
||||
|
||||
result = Image.fromarray(img_array) # Result was already defined
|
||||
|
||||
logger.debug(f"块级混合干扰完成: 处理了{processed_blocks}个块, 跳过了{skipped_blocks}个块")
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"应用块级混合干扰时出错: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return image
|
||||
|
||||
def apply_strategic_hash_disruption(self, image: Image.Image, strength: str = "medium") -> Image.Image:
|
||||
"""
|
||||
战略性哈希干扰:对各种哈希算法进行有针对性的干扰
|
||||
|
||||
整合了多种针对性干扰策略,包括块级混合干扰和针对特定哈希算法的干扰。
|
||||
|
||||
Args:
|
||||
image: 输入图像
|
||||
strength: 处理强度 ('low', 'medium', 'high')
|
||||
|
||||
Returns:
|
||||
处理后的图像
|
||||
"""
|
||||
try:
|
||||
logger.info(f"开始战略性哈希干扰 (强度: {strength})")
|
||||
original_image_for_logging = image.copy()
|
||||
|
||||
# --- 参数定义 ---
|
||||
# 设定策略应用概率
|
||||
if strength == "low":
|
||||
phash_intensity = 0.06 # 轻微DCT噪声
|
||||
color_hist_strength = 0.02 # 轻微颜色扰动
|
||||
apply_crop_resize = True # 应用裁剪缩放
|
||||
noise_alpha = random.randint(5, 8) # 低透明度噪声
|
||||
ahash_prob = 0.7
|
||||
dhash_prob = 0.7
|
||||
phash_prob = 0.9
|
||||
block_prob = 0.6
|
||||
block_size = 24
|
||||
elif strength == "high":
|
||||
phash_intensity = 0.20 # 较强DCT噪声
|
||||
color_hist_strength = 0.06 # 较强颜色扰动
|
||||
apply_crop_resize = True # 应用裁剪缩放
|
||||
noise_alpha = random.randint(12, 18) # 较高透明度噪声
|
||||
ahash_prob = 0.9
|
||||
dhash_prob = 0.9
|
||||
phash_prob = 0.95
|
||||
block_prob = 0.8
|
||||
block_size = 16
|
||||
else: # medium
|
||||
phash_intensity = 0.12 # 中等DCT噪声
|
||||
color_hist_strength = 0.04 # 中等颜色扰动
|
||||
apply_crop_resize = True # 应用裁剪缩放
|
||||
noise_alpha = random.randint(8, 12) # 中等透明度噪声
|
||||
ahash_prob = 0.8
|
||||
dhash_prob = 0.8
|
||||
phash_prob = 0.9
|
||||
block_prob = 0.7
|
||||
block_size = 20
|
||||
|
||||
logger.debug(f"参数: pHash强度={phash_intensity:.2f}, 颜色强度={color_hist_strength:.2f}, 应用裁剪缩放={apply_crop_resize}, 噪声Alpha={noise_alpha}")
|
||||
logger.debug(f"策略概率: aHash={ahash_prob:.1f}, dHash={dhash_prob:.1f}, pHash={phash_prob:.1f}, 块级={block_prob:.1f}")
|
||||
|
||||
processed_image = image # 从原图开始
|
||||
# 保存原图
|
||||
result = image.copy()
|
||||
applied_strategies = []
|
||||
|
||||
# 1. 智能裁剪 + 重缩放 (策略C)
|
||||
if apply_crop_resize:
|
||||
processed_image = self.apply_smart_crop_resize(processed_image, strength)
|
||||
# 1. 应用块级混合干扰
|
||||
if random.random() < block_prob:
|
||||
result = self.apply_block_based_perturbations(result, block_size=block_size, strength=strength)
|
||||
applied_strategies.append(f"BlockBased({block_size})")
|
||||
|
||||
# 2. 强化的pHash对抗方法 (策略A)
|
||||
logger.debug(f"应用 pHash 对抗 (强化DCT噪声), 强度={phash_intensity:.2f}")
|
||||
processed_image = self.add_phash_noise(processed_image, intensity=phash_intensity)
|
||||
# 2. 应用针对特定哈希算法的干扰
|
||||
# 2.1 aHash特定干扰
|
||||
if random.random() < ahash_prob:
|
||||
result = self.apply_ahash_specific_disruption(result, strength)
|
||||
applied_strategies.append("aHash")
|
||||
|
||||
# 3. 保留轻微的颜色直方图扰动
|
||||
if color_hist_strength > 0:
|
||||
logger.debug(f"应用颜色直方图扰动, 强度={color_hist_strength:.3f}")
|
||||
processed_image = self.perturb_color_histogram(processed_image, strength=color_hist_strength)
|
||||
# 2.2 dHash特定干扰
|
||||
if random.random() < dhash_prob:
|
||||
result = self.apply_dhash_specific_disruption(result, strength)
|
||||
applied_strategies.append("dHash")
|
||||
|
||||
# 4. 应用低透明度噪声叠加 (新策略核心)
|
||||
if noise_alpha > 0:
|
||||
processed_image = self.apply_overlay_noise(processed_image, alpha=noise_alpha, noise_type='uniform') # 先用 uniform 试试
|
||||
# 内部已有日志
|
||||
# 2.3 pHash特定干扰(最重要的一个)
|
||||
if random.random() < phash_prob:
|
||||
result = self.apply_phash_specific_disruption(result, strength)
|
||||
applied_strategies.append("pHash")
|
||||
|
||||
# --- 移除之前的 aHash块, dHash线, 区域变换, 高斯噪声等 ---
|
||||
logger.debug("已移除 aHash/dHash特定对抗、区域变换、高斯噪声等。")
|
||||
logger.info(f"已应用战略干扰: {', '.join(applied_strategies)}")
|
||||
|
||||
# 对比修改前后
|
||||
try:
|
||||
diff = ImageChops.difference(original_image_for_logging.convert('RGB'), processed_image.convert('RGB')).getbbox() # 确保模式一致
|
||||
diff = ImageChops.difference(original_image_for_logging.convert('RGB'), result.convert('RGB')).getbbox()
|
||||
if diff:
|
||||
logger.info(f"图像已修改。差异区域: {diff}")
|
||||
else:
|
||||
logger.warning("!!!优化方法似乎未修改图像!!!")
|
||||
except ValueError:
|
||||
logger.warning("无法比较图像差异:模式可能不同或错误。")
|
||||
logger.warning("!!!战略干扰似乎未修改图像!!!")
|
||||
except Exception as log_e:
|
||||
logger.warning(f"无法比较图像差异: {log_e}")
|
||||
|
||||
logger.info(f"--- 完成优化抗哈希方法 (强度: {strength}) - 叠加噪声策略 ---")
|
||||
logger.info(f"战略性哈希干扰完成 (强度: {strength})")
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"应用战略性哈希干扰时出错: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return image # 出错时返回原图
|
||||
|
||||
def optimize_anti_hash_methods(self, image: Image.Image, strength: str = "medium") -> Image.Image:
|
||||
"""优化后的哈希对抗方法,使用新的分层增强策略"""
|
||||
logger.info(f"--- 开始优化抗哈希方法 (强度: {strength}) - 分层增强策略 ---")
|
||||
processed_image = image.copy()
|
||||
|
||||
# 定义各阶段强度参数
|
||||
global_max_crop: int
|
||||
global_overlay_alpha: int
|
||||
global_color_hist_strength: float
|
||||
|
||||
if strength == "low":
|
||||
global_max_crop = 3
|
||||
global_overlay_alpha = random.randint(8, 12)
|
||||
global_color_hist_strength = 0.03
|
||||
elif strength == "high":
|
||||
global_max_crop = 10
|
||||
global_overlay_alpha = random.randint(18, 25)
|
||||
global_color_hist_strength = 0.08
|
||||
else: # medium
|
||||
global_max_crop = 6
|
||||
global_overlay_alpha = random.randint(12, 18)
|
||||
global_color_hist_strength = 0.05
|
||||
|
||||
logger.debug(f"分层策略 - 全局扰动参数: strength_for_crop='{strength}' (内部max_crop将按新标准), overlay_alpha={global_overlay_alpha}, color_hist_strength={global_color_hist_strength:.3f}")
|
||||
|
||||
# --- 层 1: 基础全局扰动 ---
|
||||
logger.info("应用基础全局扰动...")
|
||||
|
||||
# 1.1 智能裁剪 + 重缩放 (现在 apply_smart_crop_resize 内部已增强)
|
||||
processed_image = self.apply_smart_crop_resize(processed_image, strength)
|
||||
|
||||
# 1.2 低透明度噪声叠加
|
||||
processed_image = self.apply_overlay_noise(processed_image, alpha=global_overlay_alpha, noise_type='uniform')
|
||||
|
||||
# 1.3 颜色直方图扰动
|
||||
if global_color_hist_strength > 0: # 确保强度大于0才应用
|
||||
processed_image = self.perturb_color_histogram(processed_image, strength=global_color_hist_strength)
|
||||
|
||||
# --- 层 2: 战略性哈希干扰 (在基础扰动之上) ---
|
||||
# apply_strategic_hash_disruption 内部调用的各 specific 和 block_based 方法已增强
|
||||
logger.info("应用战略性哈希干扰 (各子方法已增强)...")
|
||||
processed_image = self.apply_strategic_hash_disruption(processed_image, strength)
|
||||
|
||||
# --- 清除元数据 ---
|
||||
processed_image = self.strip_metadata(processed_image)
|
||||
|
||||
logger.info(f"--- 完成优化抗哈希方法 (强度: {strength}) - 分层增强策略 ---")
|
||||
return processed_image
|
||||
|
||||
def optimized_process_image(
|
||||
@ -741,28 +1251,32 @@ class PosterNotesCreator:
|
||||
random.seed(seed)
|
||||
np.random.seed(seed)
|
||||
|
||||
# 根据微调强度设置参数
|
||||
# 根据微调强度设置参数 (保留变化因子等)
|
||||
if variation_strength == "low":
|
||||
brightness_factor = random.uniform(0.97, 1.03)
|
||||
contrast_factor = random.uniform(0.97, 1.03)
|
||||
saturation_factor = random.uniform(0.97, 1.03)
|
||||
max_rotation = 0.5
|
||||
border_size = random.randint(0, 1)
|
||||
use_extra = random.random() < 0.3 and extra_effects
|
||||
# use_extra = random.random() < 0.3 and extra_effects #<-- 旧逻辑
|
||||
elif variation_strength == "high":
|
||||
brightness_factor = random.uniform(0.92, 1.08)
|
||||
contrast_factor = random.uniform(0.92, 1.08)
|
||||
saturation_factor = random.uniform(0.92, 1.08)
|
||||
max_rotation = 2.0
|
||||
border_size = random.randint(0, 3)
|
||||
use_extra = extra_effects
|
||||
# use_extra = extra_effects #<-- 旧逻辑 (本身就是直接赋值)
|
||||
else: # medium
|
||||
brightness_factor = random.uniform(0.95, 1.05)
|
||||
contrast_factor = random.uniform(0.95, 1.05)
|
||||
saturation_factor = random.uniform(0.95, 1.05)
|
||||
max_rotation = 1.0
|
||||
border_size = random.randint(0, 2)
|
||||
use_extra = random.random() < 0.7 and extra_effects
|
||||
# use_extra = random.random() < 0.7 and extra_effects #<-- 旧逻辑
|
||||
|
||||
# --- FIX: 直接使用传入的 extra_effects 控制是否启用抗哈希和额外效果 ---
|
||||
use_extra = extra_effects
|
||||
# --- END FIX ---
|
||||
|
||||
# 调整图像为目标比例
|
||||
width, height = image.size
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user