识破骗局:揭露深度伪造声音

社区文章 发布于 2023 年 10 月 29 日

image/png

引言:

在人工智能不断重新定义技术边界的时代,最引人关注和令人担忧的进展之一是深度伪造声音的出现。这些对真实人声的惊人模仿以极高的精度制作,甚至有可能欺骗最敏锐的耳朵。本文将深入探讨音频深度伪造检测的世界,探讨其重要性、面临的挑战以及用于打击欺骗性深度伪造声音兴起的策略。

人工智能的概念在历史上获得了显著的关注,在当代仍然是持续讨论和探索的主题。人工智能(AI)一直是许多文学作品和电影中反复出现的主题,其在未来背景下的重要性被预测。对人工智能的这种主题探索几十年来一直是创意努力的主题。近年来,深度伪造技术已成为人工智能领域一个突出的关注主题。深度伪造技术被广泛认为是基于人工智能和深度学习的创新。许多深度伪造应用程序最近对公众产生了重大影响。除了针对知名人士的操纵视频的制作之外,深度伪造技术显然在多个领域具有许多潜在应用。本研究的目的是探索深度伪造技术在许多领域的潜在应用。该研究通过关注深度学习的概念并参考人工智能技术来检查深度伪造技术。该研究通过进行全面的文献分析和分析其在不同领域的使用示例,对深度伪造技术的许多应用进行了分类。根据研究结果,可以将深度伪造技术的重要应用分为四个不同的类别。前面提到的类别包括艺术和娱乐、广告和营销、电影业、政治传播和媒体。

image/png

声音在人工智能中的作用:

人声是沟通、情感和身份的有力工具。在人工智能领域,声音的作用已大大扩展,产生了大量与声音相关的应用。

  1. 语音助手:Siri、Alexa 和 Google Assistant 等虚拟助手依靠语音识别技术来理解和响应用户命令。

  2. 文本转语音 (TTS):AI 驱动的 TTS 系统将书面文本转换为听起来自然的声音,增强了可访问性并实现了自然的人机交互。

  3. 语音认证:语音生物识别技术用于安全和认证,允许个人使用其独特的声纹解锁设备或访问敏感信息。

  4. 有声读物和播客:人工智能使得将书面内容转换为口语成为可能,扩大了文学和信息的覆盖范围和可访问性。

音频深度伪造检测:揭示欺骗的声音

  1. 音频深度伪造的挑战:音频深度伪造技术可以以惊人的精度模仿一个人的声音和语音模式。这带来了巨大的挑战,因为越来越难以区分真实音频和伪造音频。识别音频深度伪造需要多方面的策略,结合知识、技术和警惕性。

  2. 数据收集和整理:数据是所有深度伪造检测算法的基石。一个包含真实和深度伪造音频录音的多样化数据集至关重要。该数据集应代表各种声音、语言和设置。为了从音频中提取重要元素,例如频谱图或梅尔频率倒谱系数 (MFCC),需要使用预处理方法。这些特征构成了机器学习模型的基础。

  3. 机器学习模型:选择合适的机器学习模型是识别音频深度伪造的关键选择。卷积神经网络 (CNN)、循环神经网络 (RNN) 和混合架构是几种模型类型的示例。使用用于音频分类的预训练模型可能是一个很好的起点。

  4. 特征提取:为了区分真实音频和深度伪造音频,特征提取至关重要。MFCC、频谱图图像或两者的混合可以用作模型的输入特征。这些特征捕捉音频的频率和时间方面,帮助模型识别异常。

  5. 训练和评估:训练过程是检测系统的主要组成部分。为了训练模型区分两种类型的数据,使用了真实数据和深度伪造数据。应用数据增强技术来提高模型的鲁棒性。使用许多指标来评估模型的性能。为了确保模型的有效性,使用未见过的数据进行测试和交叉验证是必不可少的过程。

  6. 优化和后处理:模型的性能得到最大化,并通过微调解决任何偏差或弱点。后处理方法用于改进模型的预测并降低误报的数量。

  7. 持续监控和实时检测:最终目标是将模型部署用于音频文件或流中的实时检测。该模型可以通过与音频处理框架和工具集成,在实际情况下运行。它需要持续观察和更新以适应新的深度伪造方法。

  8. 道德考量和用户教育:对于个人和组织而言,他们都必须了解音频深度伪造的存在。鼓励负责任地使用音频内容并确认其有效性是共同的责任。解决道德和法律考量,例如安全和隐私问题,也至关重要。

  9. 道德考量和用户教育:对于个人和组织而言,他们都必须了解音频深度伪造的存在。鼓励负责任地使用音频内容并确认其有效性是我们的共同责任。此外,解决道德和法律考量,例如安全和隐私问题,也至关重要。

image/png

来源:深度伪造

代码实现

在本节中,我们将逐步介绍如何从 Kaggle 下载深度伪造检测挑战数据集,该数据集将作为深度伪造检测项目的基础。深度伪造检测挑战数据集是经过处理和未处理视频的丰富资源,是训练和评估深度伪造检测模型的关键组成部分。

步骤 1:导入库

import numpy as np
import pandas as pd
import os
import matplotlib
import seaborn as sns
import matplotlib.pyplot as plt
from tqdm import tqdm_notebook
%matplotlib inline 
import cv2 as cv

from pathlib import Path
import subprocess
import librosa.display
import librosa.filters

DATA_FOLDER = '/kaggle/input/deepfake-detection-challenge'
TRAIN_SAMPLE_FOLDER = 'train_sample_videos'
TEST_FOLDER = 'test_videos'
INPUT_PATH = '../input/realfake045/all/all'
WAV_PATH = './wavs/'
print(f"Train samples: {len(os.listdir(os.path.join(DATA_FOLDER, TRAIN_SAMPLE_FOLDER)))}")
print(f"Test samples: {len(os.listdir(os.path.join(DATA_FOLDER, TEST_FOLDER)))}")

此代码为深度伪造检测挑战中的数据文件路径设置变量。它将“DATA_FOLDER”定义为主数据目录,“TRAIN_SAMPLE_FOLDER”定义为包含标记训练视频的文件夹,“TEST_FOLDER”定义为测试视频的文件夹。它使用“os”模块来计算这些文件夹中的文件。该代码利用 f 字符串来打印训练和测试数据的样本计数。此代码是深度伪造检测挑战中数据探索的一个有用步骤,可以轻松评估数据样本大小。

步骤 2:检查文件类型

在这里,我们检查训练数据文件的扩展名。大多数文件似乎都具有 mp4 扩展名,让我们检查是否有其他扩展名。

train_list = list(os.listdir(os.path.join(DATA_FOLDER, TRAIN_SAMPLE_FOLDER)))
ext_dict = []
for file in train_list:
    file_ext = file.split('.')[1]
    if (file_ext not in ext_dict):
        ext_dict.append(file_ext)
print(f"Extensions: {ext_dict}")

输出

Extensions: ['mp4', 'json']
让我们统计每种扩展名的文件数量。
for file_ext in ext_dict:
    print(f"Files with extension `{file_ext}`: {len([file for file in train_list if  file.endswith(file_ext)])}")

输出

Files with extension `mp4`: 400
Files with extension `json`: 1

让我们对测试视频文件夹重复相同的过程。

test_list = list(os.listdir(os.path.join(DATA_FOLDER, TEST_FOLDER)))
ext_dict = []
for file in test_list:
    file_ext = file.split('.')[1]
    if (file_ext not in ext_dict):
        ext_dict.append(file_ext)
print(f"Extensions: {ext_dict}")
for file_ext in ext_dict:
    print(f"Files with extension `{file_ext}`: {len([file for file in train_list if  file.endswith(file_ext)])}")

让我们检查 json 文件

json_file = [file for file in train_list if  file.endswith('json')][0]
print(f"JSON file: {json_file}")

此代码片段在 train_list 中搜索以 .json 扩展名结尾的文件,并将其分配给变量 json_file。

让我们探索这个 JSON 文件。

def get_meta_from_json(path):
    df = pd.read_json(os.path.join(DATA_FOLDER, path, json_file))
    df = df.T
    return df

meta_train_df = get_meta_from_json(TRAIN_SAMPLE_FOLDER)
meta_train_df.head()

输出

    label	   split	  original
aagfhgtpmv.mp4	FAKE	train	vudstovrck.mp4
aapnvogymq.mp4	FAKE	train	jdubbvfswz.mp4
abarnvbtwb.mp4	REAL	train	None
abofeumbvv.mp4	FAKE	train	atvmxvwyns.mp4
abqwwspghj.mp4	FAKE	train	qzimuostzz.mp4

步骤 3:元数据探索

现在让我们探索训练样本中的元数据。

缺失数据

  1. 我们首先检查是否有任何缺失值。
def missing_data(data):
    total = data.isnull().sum()
    percent = (data.isnull().sum()/data.isnull().count()*100)
    tt = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])
    types = []
    for col in data.columns:
        dtype = str(data[col].dtype)
        types.append(dtype)
    tt['Types'] = types
    return(np.transpose(tt))

此代码定义了一个名为 missing_data(data) 的函数,该函数将 pandas DataFrame 对象数据作为输入,并返回 DataFrame 中缺失数据的摘要。

missing_data(meta_train_df)

输出

      label	 split	original
Total	0	  0	     77
Percent	0	  0	    19.25
Types object object	object

此代码正在调用 missing_data() 函数,并传递 meta_train_df DataFrame 作为参数。

  1. 有缺失数据,占样本的 19.25%(或 77 个)。我们怀疑实际数据缺少原始数据(如果我们从我们瞥见的数据中进行概括)。让我们验证这个假设。
missing_data(meta_train_df.loc[meta_train_df.label=='REAL'])

此代码正在对满足特定条件的 meta_train_df DataFrame 的子集调用 missing_data() 函数,使用 .loc 方法根据标签列的值选择行。

步骤 4:唯一值

def unique_values(data):
    total = data.count()
    tt = pd.DataFrame(total)
    tt.columns = ['Total']
    uniques = []
    for col in data.columns:
        unique = data[col].nunique()
        uniques.append(unique)
    tt['Uniques'] = uniques
    return(np.transpose(tt))

此代码定义了一个名为 unique_values(data) 的函数,该函数将 pandas DataFrame 对象数据作为输入,并返回 DataFrame 中唯一值的摘要。

  • 总的来说,此代码对于快速识别 pandas DataFrame 中唯一值的数量非常有用,它为 DataFrame 中的每一列提供了唯一值数量的摘要。
unique_values(meta_train_df)

此代码正在调用 unique_values() 函数,并传递 meta_train_df DataFrame 作为参数。

步骤 5:最常见的原始数据

def most_frequent_values(data):
    total = data.count()
    tt = pd.DataFrame(total)
    tt.columns = ['Total']
    items = []
    vals = []
    for col in data.columns:
        itm = data[col].value_counts().index[0]
        val = data[col].value_counts().values[0]
        items.append(itm)
        vals.append(val)
    tt['Most frequent item'] = items
    tt['Frequence'] = vals
    tt['Percent from total'] = np.round(vals / total * 100, 3)
    return(np.transpose(tt))
most_frequent_values(meta_train_df)

代码“most_frequent_values(meta_train_df)”正在调用“most_frequent_values”函数,并带有名为“meta_train_df”的参数。这表明“meta_train_df”是一个 pandas DataFrame,并且该函数正用于计算此 DataFrame 中每列的最常见值和其他信息。

步骤 6:数据分布可视化

def plot_count(feature, title, df, size=1):
    '''
    Plot count of classes / feature
    param: feature - the feature to analyze
    param: title - title to add to the graph
    param: df - dataframe from which we plot feature's classes distribution 
    param: size - default 1.
    '''
    f, ax = plt.subplots(1,1, figsize=(4*size,4))
    total = float(len(df))
    g = sns.countplot(df[feature], order = df[feature].value_counts().index[:20], palette='Set3')
    g.set_title("Number and percentage of {}".format(title))
    if(size > 2):
        plt.xticks(rotation=90, size=8)
    for p in ax.patches:
        height = p.get_height()
        ax.text(p.get_x()+p.get_width()/2.,
                height + 3,
                '{:1.2f}%'.format(100*height/total),
                ha="center") 
    plt.show()    
plot_count('split', 'split (train)', meta_train_df)

image/png

步骤 7:视频数据探索

接下来我们将探索一些视频数据。

缺失视频(或元数据) 我们首先检查元信息中的文件列表和文件夹中的文件列表是否相同。

meta = np.array(list(meta_train_df.index))
storage = np.array([file for file in train_list if  file.endswith('mp4')])
print(f"Metadata: {meta.shape[0]}, Folder: {storage.shape[0]}")
print(f"Files in metadata and not in folder: {np.setdiff1d(meta,storage,assume_unique=False).shape[0]}")
print(f"Files in folder and not in metadata: {np.setdiff1d(storage,meta,assume_unique=False).shape[0]}")

输出

Metadata: 400, Folder: 400
Files in metadata and not in folder: 0
Files in folder and not in metadata: 0

少量伪造视频

fake_train_sample_video = list(meta_train_df.loc[meta_train_df.label=='FAKE'].sample(3).index)
fake_train_sample_video

输出

['bguwlyazau.mp4', 'byfenovjnf.mp4', 'dsndhujjjb.mp4']

修改显示视频中选定图像的函数

def display_image_from_video(video_path):
    '''
    input: video_path - path for video
    process:
    1. perform a video capture from the video
    2. read the image
    3. display the image
    '''
    capture_image = cv.VideoCapture(video_path) 
    ret, frame = capture_image.read()
    fig = plt.figure(figsize=(10,10))
    ax = fig.add_subplot(111)
    frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
    ax.imshow(frame)
for video_file in fake_train_sample_video:
    display_image_from_video(os.path.join(DATA_FOLDER, TRAIN_SAMPLE_FOLDER, video_file))

输出:image/png

让我们现在对一些真实图像进行相同的操作。

real_train_sample_video = list(meta_train_df.loc[meta_train_df.label=='REAL'].sample(3).index)
real_train_sample_video

输出

['ciyoudyhly.mp4', 'ekcrtigpab.mp4', 'cfxkpiweqt.mp4']
for video_file in real_train_sample_video:
    display_image_from_video(os.path.join(DATA_FOLDER, TRAIN_SAMPLE_FOLDER, video_file))

image/png

步骤 8:具有相同原始文件的视频

meta_train_df['original'].value_counts()[0:5]

输出

meawmsgiti.mp4    6
atvmxvwyns.mp4    6
qeumxirsme.mp4    5
kgbkktcjxf.mp4    5
qzklcjjxdq.mp4    4
Name: original, dtype: int64

修改我们的可视化函数以处理多个图像。

def display_image_from_video_list(video_path_list, video_folder=TRAIN_SAMPLE_FOLDER):
    '''
    input: video_path_list - path for video
    process:
    0. for each video in the video path list
        1. perform a video capture from the video
        2. read the image
        3. display the image
    '''
    plt.figure()
    fig, ax = plt.subplots(2,3,figsize=(16,8))
    # we only show images extracted from the first 6 videos
    for i, video_file in enumerate(video_path_list[0:6]):
        video_path = os.path.join(DATA_FOLDER, video_folder,video_file)
        capture_image = cv.VideoCapture(video_path) 
        ret, frame = capture_image.read()
        frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
        ax[i//3, i%3].imshow(frame)
        ax[i//3, i%3].set_title(f"Video: {video_file}")
        ax[i//3, i%3].axis('on')
same_original_fake_train_sample_video = list(meta_train_df.loc[meta_train_df.original=='meawmsgiti.mp4'].index)
display_image_from_video_list(same_original_fake_train_sample_video)

image/png

代码的总体目的是显示从名为“meawmsgiti.mp4”的原始视频文件生成的元数据 DataFrame 训练集中每个伪造视频文件的第一帧。这对于分析从特定原始视频生成的伪造视频的质量和特征非常有用。

步骤 9:测试视频文件

我们再看看一些测试数据文件。

test_videos = pd.DataFrame(list(os.listdir(os.path.join(DATA_FOLDER, TEST_FOLDER))), columns=['video'])
test_videos.head()

现在让我们可视化其中一个视频。

display_image_from_video(os.path.join(DATA_FOLDER, TEST_FOLDER, test_videos.iloc[0].video))

image/png

“display_image_from_video”函数的作用是将指定视频文件的第一帧显示为图像。因此,代码的总体目的是显示数据目录“test”文件夹中第一个视频文件的第一帧,以便轻松检查视频的内容和质量。

步骤 10:播放视频文件

fake_videos = list(meta_train_df.loc[meta_train_df.label=='FAKE'].index)
from IPython.display import HTML
from base64 import b64encode

def play_video(video_file, subset=TRAIN_SAMPLE_FOLDER):
    '''
    Display video
    param: video_file - the name of the video file to display
    param: subset - the folder where the video file is located (can be TRAIN_SAMPLE_FOLDER or TEST_Folder)
    '''
    video_url = open(os.path.join(DATA_FOLDER, subset,video_file),'rb').read()
    data_url = "data:video/mp4;base64," + b64encode(video_url).decode()
    return HTML("""<video width=500 controls><source src="%s" type="video/mp4"></video>""" % data_url)
play_video(fake_videos[0])

<video controls autoplay src="

">

步骤 11:下载公共数据集:https://www.kaggle.com/rakibilly/ffmpeg-static-buildhttps://www.kaggle.com/datasets/phoenix9032/realfake045

!tar xvf /kaggle/input/ffmpeg-static-build/ffmpeg-git-amd64-static.tar.xz
output_format = 'wav'  # can also use aac, wav, etc

output_dir = Path(f"{output_format}s")
Path(output_dir).mkdir(exist_ok=True, parents=True)
fake_name ='aaeflzzhvy'
real_name = 'flqgmnetsg'
list_of_files = []
for file in os.listdir(os.path.join(DATA_FOLDER,TRAIN_SAMPLE_FOLDER)):
    filename = os.path.join(DATA_FOLDER,TRAIN_SAMPLE_FOLDER)+file
    list_of_files.append(filename)
%%time
create_wav(list_of_files)

image/png

结论

总而言之,“识破骗局:揭露深度伪造声音”阐明了不断发展的音频深度伪造技术领域。随着数字时代的进步,以空前的真实感操纵音频记录的能力引发了重大担忧,包括错误信息、隐私泄露和网络安全风险。

本文深入探讨了音频深度伪造检测的复杂格局,阐明了该领域面临的挑战。从数据收集和整理的复杂过程到各种机器学习模型、特征提取技术和稳健训练程序的使用,揭露深度伪造声音的方法多种多样且要求苛刻。

此外,模型优化和后处理的关键阶段确保了最高水平的性能,同时解决了偏差和弱点。在音频流和文件中实现实时检测是最终目标,需要持续监控和更新以阻止新的深度伪造方法。

本文不仅是一项技术探索,还强调了围绕音频内容负责任使用的伦理考量。它强调了维护音频信息完整性的集体责任,并解决了道德和法律维度,包括安全和隐私。

在一个日益受人工智能塑造的世界中,理解和应对欺骗性深度伪造声音的兴起是一项至关重要的任务。凭借警惕、创新和对道德原则的承诺,我们可以努力在一个技术奇迹和欺骗的时代中保持音频的真实性。

“保持联系,并通过各种平台支持我的工作

请求和问题:如果您有项目想让我参与,或者对我解释的概念有任何疑问,请不要犹豫告诉我。我一直在寻找未来 Notebook 的新想法,并且喜欢帮助解决您可能有的任何疑问。

请记住,每一个“赞”、“分享”和“星标”都极大地有助于我的工作,并激励我继续创作更多高质量的内容。感谢您的支持!

资源

社区

注册登录 发表评论