You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python3对比原始音频与对抗样本提取扰动生成perturbation.wav

嘿,这个需求其实很好实现——对抗样本里的扰动本质上就是带扰动音频与原始音频的差值,直接用Python做减法就行!下面给你两种实用的实现方式,你可以根据自己的环境选:

方法一:用Python标准库wave(无需额外安装)

如果不想装第三方库,用Python自带的wave模块就能搞定,核心思路是把音频帧转换成数值数组,做差值后再写回文件:

import wave
import numpy as np

def extract_perturbation(original_path, attacked_path, output_path):
    # 打开两个音频文件
    with wave.open(original_path, 'rb') as orig_wav, wave.open(attacked_path, 'rb') as att_wav:
        # 先检查两个音频的参数必须完全一致(采样率、位深、声道数、长度)
        assert orig_wav.getparams() == att_wav.getparams(), \
            "Error: 两个音频的参数(采样率、位深、声道数等)必须完全匹配才能提取扰动!"
        
        # 读取所有音频帧
        orig_frames = orig_wav.readframes(-1)
        att_frames = att_wav.readframes(-1)
        
        # 根据位深选择对应的数据类型
        sample_width = orig_wav.getsampwidth()
        if sample_width == 1:
            dtype = np.uint8
            offset = 128  # 8位音频是无符号,要转成有符号计算
        elif sample_width == 2:
            dtype = np.int16
            offset = 0
        elif sample_width == 4:
            dtype = np.int32
            offset = 0
        else:
            raise ValueError(f"不支持的音频位深:{sample_width}字节")
        
        # 把字节数据转成数值数组
        orig_data = np.frombuffer(orig_frames, dtype=dtype) - offset
        att_data = np.frombuffer(att_frames, dtype=dtype) - offset
        
        # 计算扰动:带扰动音频 - 原始音频
        perturbation_data = att_data - orig_data
        
        # 转换回原始位深的字节格式
        perturbation_data += offset
        perturbation_frames = perturbation_data.astype(dtype).tobytes()
        
        # 写入输出文件
        with wave.open(output_path, 'wb') as out_wav:
            out_wav.setparams(orig_wav.getparams())
            out_wav.writeframes(perturbation_frames)

# 调用函数,替换成你的文件路径
extract_perturbation("original.wav", "attacked.wav", "perturbation.wav")

注意事项:

  • 对抗样本攻击生成的attacked.wav通常和original.wav参数完全一致,所以断言一般不会触发,但如果不一致,你需要先把两个音频转成相同参数(比如用FFmpeg转码)。
  • 8位音频是无符号类型,所以要减去128转成有符号数再计算,避免溢出。
方法二:用librosa(更简洁,适合复杂场景)

如果你经常处理音频,librosa会让代码更简洁,它会自动处理位深、声道等细节,不过需要先安装依赖:

pip install librosa soundfile

实现代码:

import librosa
import soundfile as sf

def extract_perturbation_librosa(original_path, attacked_path, output_path):
    # 读取音频,sr=None表示保留原始采样率
    orig_data, sr = librosa.load(original_path, sr=None, mono=False)
    att_data, _ = librosa.load(attacked_path, sr=sr, mono=False)
    
    # 检查音频形状是否一致
    assert orig_data.shape == att_data.shape, \
        "Error: 两个音频的声道数和长度必须一致!"
    
    # 直接计算扰动
    perturbation_data = att_data - orig_data
    
    # 写入输出文件:注意librosa返回的是(声道数, 采样点数),soundfile需要转成(采样点数, 声道数)
    sf.write(output_path, perturbation_data.T, sr)

# 调用函数
extract_perturbation_librosa("original.wav", "attacked.wav", "perturbation.wav")

额外提示:

  • 提取出来的扰动音频大概率是人类几乎听不到的噪音,这是正常的——对抗扰动本来就是精心设计的、不影响听觉但能误导模型的微小信号。
  • 如果需要调整扰动的音量,可以给perturbation_data乘以一个系数(比如perturbation_data * 10),但注意不要超出音频的数值范围(浮点型是[-1,1])。

内容的提问来源于stack exchange,提问作者Alexis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:12:49