在数字化时代,我们时常被各种图像信息所包围。然而,这些图像中有时隐藏着不为人知的秘密——被篡改的文字或图像。这些被篡改的内容可能误导我们的判断,甚至在某些情况下造成严重的后果。幸运的是,随着人工智能(AI)技术的发展,我们现在已经拥有了一种工具,可以帮助我们揪出这些图片中的“李鬼”,AI模型能够接收用户上传的疑似篡改的文字图像,并通过深度学习和图像分析技术,自动检测并标注出图像中疑似被篡改的区域。这对于新闻工作者、调查人员、甚至是普通网友来说,都是一项非常实用的功能。
本文所涉及所有资源均在传知代码平台可获取
目录
概述
演示效果
核心逻辑
写在最后
概述
在如今这个“P图大神”遍地走的时代,图片的真实性越来越难以保证。尤其是在文档图像领域,篡改文字、伪造证书等行为可能带来严重的风险。想象一下,你正准备签一份重要合同,却发现附件中的资质证书似乎有点不对劲。是的,你没猜错,这正是图像篡改的“作案现场”,然而,我们必须强调的是,尽管我们的模型在检测文字图像篡改方面具有较高的准确率,但它并不是万能的。AI的能力受限于其训练的数据和算法的设计。在检测物体擦除或人脸P图等更为复杂的图像篡改时,我们的模型可能无法提供同样准确的结果。这是因为这些类型的篡改通常涉及到更多的图像处理和合成技术,需要更高级的算法和更大的数据集来支持,如下图所示:
文字图像篡改,听起来是不是很像电影里的高级犯罪?但这可不仅仅是电影情节,它真实地发生在我们的数字生活中。文档图像篡改指的是对文档图像进行的未经授权的修改,包括文字、图表、印章等内容的删除、修改、添加或替换。 当你怀疑一张图片被篡改时,你会怎么做?是不是会像侦探一样,拿着放大镜仔细观察,寻找蛛丝马迹?AI侦探也是如此,它会运用一种叫做注意力机制的技术,就像人眼一样,不断放大缩小图像,对比观察不同区域的特征,从而精准定位篡改区域。
这种技术的运用,不仅提高了检测的准确性,也极大提升了效率,让AI在图像取证领域展现出了惊人的潜力。 但AI侦探的“火眼金睛”是如何炼成的呢?这就不得不提到一项最新的研究成果——一种结合了伪造痕迹增强和多尺度注意力机制的网络框架。这个框架通过深度学习算法,能够从多个维度分析图像,识别出那些肉眼难以察觉的篡改痕迹。 研究人员们通过构建一个大规模的文本图像篡改数据集,训练AI侦探识别各种篡改手段。在实验中,AI侦探展现出了极高的准确率,即使是面对经过精心伪装的篡改图像,也难逃它的“法眼”。 这项技术的出现,无疑为我们的数字生活增添了一份安全保障。它不仅能够帮助我们识别出那些潜在的风险,更能够提升我们对数字内容的信任度。在未来,随着技术的不断进步,AI侦探将更加智能,成为我们守护信息安全的重要伙伴。
注意力机制如何工作:想象一下,当你怀疑一张图片被篡改时,你会怎么做?是不是会像侦探一样,拿着放大镜仔细观察,寻找蛛丝马迹?AI侦探也是如此,它会运用一种叫做注意力机制的技术,就像人眼一样,不断放大缩小图像,对比观察不同区域的特征,从而精准定位篡改区域。
首先,AI模型会像一位细心的侦探一样,对图像进行彻底的特征提取,分析并记录下各种特征,比如颜色、纹理、形状等。这些特征就像是图像的指纹,为后续的分析提供了重要的线索。接着,模型会根据这些特征的重要性,为图像的不同区域分配不同的权重。这就好比侦探在案件中,会根据嫌疑人的可疑程度给予不同的关注。在图像篡改的案件中,那些与周围环境不一致的区域,往往就是篡改的痕迹,因此会被赋予更高的权重。最后,模型会根据权重分布,将注意力集中在最有可能被篡改的聚焦区域,进行更深入的分析。这就好比侦探在案件的关键环节,会集中精力,深入挖掘线索,力求揭开真相。注意力机制的优势显而易见。它不仅能够精准定位篡改痕迹,减少误判率,还能够高效处理图像数据,通过合理分配计算资源,只关注重要的区域。此外,它的权重分布还具有很好的可解释性,能够直观地展示模型的关注点,让整个过程更加透明。
尽管已有一些相关方法,但大多数现有算法是在受控实验室环境中开发和验证的,缺乏对真实场景的鲁棒性和普遍性考虑。在实际情况中,伪造图像不可避免地会遭受后处理,如有损压缩、重新捕捉或复杂融合,这些操作可能掩盖篡改痕迹,严重降低了篡改定位性能,文字图像篡改检测面临着独特的挑战:
1)文字图像具有均匀的纹理、简单的边界和规则的间隙,使得篡改区域难以识别。
2)篡改区域可能非常小(例如单个字符),并且与背景的对比度微妙,增加了检测难度。
3)现实场景中的伪造图像可能经过压缩、重拍或图像融合等后处理,进一步掩盖了篡改痕迹,降低了检测算法的有效性。
演示效果
传统的篡改检测方法往往依赖于单一的特征提取或简单的机器学习模型,这在面对复杂的篡改手段时,容易受到干扰和欺骗,而本论文提出的方法,通过深度学习技术的应用,能够从更深层次理解图像内容,从而提高检测的准确性,此外论文中的方法在设计时,充分考虑了现实世界中的复杂情况,本论文针对这一问题,提出了一种创新的解决方案,如图所示,该方法主要包括三个关键阶段:训练数据集的构建,篡改痕迹增强和文本图像篡改定位,如下:
篡改痕迹增强网络:经过篡改的文本图像常常会经历如JPEG压缩等后处理操作,这些操作往往会损害或掩盖篡改的痕迹。针对这一问题,该论文提出了一种篡改痕迹增强网络模块,其核心目的是提升图像定位在面临有损后处理时的鲁棒性。
该网络模块由两个主要部分构成:多模态特征提取器和篡改痕迹增强网络。多模态特征提取器采用两种不同的特征算子,分别从空间域和错误级域中提取篡改的线索。恢复网络则采用融合的特征,并应用类似UNet的网络结构,其主要目标是通过残差学习来恢复细微的篡改痕迹。此外,该恢复网络还能抑制非篡改相关的图像伪影,并尝试恢复纯篡改图像,以便于进一步的定位。
考虑输入图像𝐼I,以及经过预设质量因子进行的有损JPEG压缩函数𝐽()J()。特征提取器𝑆()S()用于从图像中提取特征图𝐹ELAFELA和𝐹SRMFSRM分别代表ELA和SRM特征图。恢复网络𝑈()U()采用U-Net结构,并利用残差学习技术以恢复难以察觉的篡改痕迹。该网络通过残差连接将来自收缩路径的篡改特征与来自扩张路径的恢复特征相融合,不仅强化了篡改的迹象,同时剔除了原始特征中的冗余信息。恢复过程可以用以下数学表达式表示:
文本图像篡改定位网络:在文字图像篡改检测领域,该论文引入了一个关键创新点——LHSE(Local and Hierarchical Semantic Enhancement)模块。该模块旨在通过局部和层次化的语义增强,进一步提升篡改检测的性能。具体来说,LHSE模块首先利用局部卷积操作精细捕捉图像中的局部特征,这些特征能够精确反映图像各区域的细节信息,特别是潜在的篡改区域。通过精心设计的卷积核大小和步长,模块能够提取出多尺度的局部特征,为后续的语义增强提供了丰富的信息基础。
接下来,LHSE模块利用层次化的语义融合策略整合这些局部特征。它采用多尺度金字塔结构,将不同层次的特征进行融合,从而全面捕获从微观到宏观的全方位信息。这种层次化的处理方式不仅有助于模型更好地理解图像的结构和上下文信息,还显著提高了篡改检测的准确性。
在实际应用中,LHSE模块不仅显著增强了图像中篡改痕迹的表达能力,使模型能够更准确地定位和识别篡改区域,还提高了检测的精度和可靠性。同时,该模块的设计充分考虑了现实世界中的多种失真场景,如JPEG压缩、图像重摄等,通过提取多尺度的局部特征和进行层次化的语义融合,模块能够在这些复杂场景下保持稳定的性能,从而增强了模型的鲁棒性,如下图所示:
下图是对LHSE模块前后的特征映射的可视化。从左到右两列分别为输入的篡改图像、真实掩模、LHSE模块前后的特征结果。由最后一列的结构可以看出,LHSE模块生成的融合特征图有效地捕获了被篡改的区域:
TFAM模块的功能在于通过学习特征图上不同位置之间的依赖关系,增强网络对篡改区域的全局理解,从而提高篡改检测的准确性。它能够抑制背景噪声,并使网络更加关注篡改区域,学习到更具有区分性的特征。因此,TFAM模块在文本图像篡改检测中发挥着关键作用,提高了模型的性能和稳健性,如下:
下图是对TFAM模块前后的特征映射的可视化。从左到右两列分别为输入图像、真实掩模、TFAM模块前后的特征结果。。由最后一列的结构可以看出,TFAM的特征映射输出集中在伪造区域,并且消除了背景纹理噪声的影响,这说明了TFAM模块的有效性:
系统开发了一个桌面版的GUI界面和一个网页版的web供算法的可视化演示,无论是使用桌面版GUI界面还是网页版web,用户都可以方便地进行图像篡改检测,并直观地查看检测结果。这些工具为图像篡改检测提供了便捷的可视化演示方式,有助于用户更好地理解和应用相关算法:
核心逻辑
在图像篡改检测的研究领域,首先关注实验结果的可视化图像,其中“Images”列展示了被篡改的原始图像,而“Mask”列则呈现了对应的篡改区域。该研究的主要目标是实现图像篡改区域的精确定位。从图像分类的角度来看,这个问题可以被视为一个逐像素级别的二分类任务。具体来说,针对被篡改的图像A中的每个像素点(x,y),模型需要对其是否被篡改进行判断。如果模型判断一个像素点被篡改,则输出1;否则,输出0。通过这种方式,所有像素点的0和1输出组合成了一张与原始图像A分辨率相同的二值掩膜图像。
在下面这张掩膜图像中,白色区域代表了图像中被篡改的位置,而黑色区域则表示未被篡改的部分。通过生成精确的篡改区域图,篡改检测模型能够辅助用户识别和定位图像中的不真实内容。在本文的可视化结果中,所提出的方法表现出对小规模篡改区域的精确定位能力,例如单个数字或字符的篡改。这种能力得益于所采用的多尺度特征融合机制,它能够有效整合高层语义特征和低层视觉细节。此外,从可视化结果中可以观察到,所提出的方法不仅能够突出微小篡改区域,而且能够有效抑制背景噪声,尤其在复杂文本图像背景下,仍能准确识别篡改区域,不受背景噪声的干扰:
下面这段代码中这些损失函数适用于需要处理类别不平衡或者需要同时优化预测准确性和空间相似性的二分类图像分割任务,通过调整权重可以有效地影响模型在不同类别或不同损失函数之间的学习重要性,从而提升模型在特定任务中的表现:
import torch.nn.functional as F
import torch.nn as nn
######## Weighted BCE Loss ###########
class WeightedBCE(nn.Module):
def __init__(self, weights=[0.2, 0.8]):
super(WeightedBCE, self).__init__()
self.weights = weights
def forward(self, logit_pixel, truth_pixel):
logit = logit_pixel.reshape(-1)
truth = truth_pixel.reshape(-1)
assert(logit.shape==truth.shape)
loss = F.binary_cross_entropy(logit, truth, reduction='mean')
pos = (truth>=0.35).float()
neg = (truth<0.35).float()
pos_weight = pos.sum().item() + 1e-12
neg_weight = neg.sum().item() + 1e-12
loss = (self.weights[0]*pos*loss/pos_weight + self.weights[1]*neg*loss/neg_weight).sum()
return loss
######## Weighted Dice Loss ###########
class WeightedDiceLoss(nn.Module):
def __init__(self, weights=[0.5, 0.5]): # W_pos=0.8, W_neg=0.2
super(WeightedDiceLoss, self).__init__()
self.weights = weights
def forward(self, logit, truth, smooth=1e-5):
batch_size = len(logit)
logit = logit.reshape(batch_size,-1)
truth = truth.reshape(batch_size,-1)
assert(logit.shape==truth.shape)
p = logit.view(batch_size,-1)
t = truth.view(batch_size,-1)
w = truth.detach()
w = w*(self.weights[1]-self.weights[0])+self.weights[0]
p = w*(p)
t = w*(t)
intersection = (p * t).sum(-1)
union = (p * p).sum(-1) + (t * t).sum(-1)
dice = 1 - (2*intersection + smooth) / (union +smooth)
loss = dice.mean()
return loss
######## Total Loss = WeightedDice Loss + WeightedBCE###########
class WeightedDiceBCE(nn.Module):
def __init__(self,dice_weight=1,BCE_weight=1):
super(WeightedDiceBCE, self).__init__()
self.BCE_loss = WeightedBCE(weights=[0.8, 0.2])
self.dice_loss = WeightedDiceLoss(weights=[0.5, 0.5])
self.BCE_weight = BCE_weight
self.lovasz_weight = 0
self.dice_weight = dice_weight
def forward(self, inputs, targets):
dice = self.dice_loss(inputs, targets)
BCE = self.BCE_loss(inputs, targets)
dice_BCE_loss = self.dice_weight * dice + self.BCE_weight * BCE
return dice_BCE_loss
下面这段代码定义了一个复杂的特征提取和融合模块 LHSE,它通过水平和垂直方向上的特征提取和融合,有效地捕获图像特征的局部和层次信息。每个方向上都通过多层卷积和批归一化层来增强特征表达能力,并通过点乘操作将不同方向的特征进行融合,以提升模型在图像处理任务中的性能和表现:
## 如下代码是使用torch对LHSE模块的搭建
import torch
import torch.nn as nn
import torch.nn.functional as F
class LHSE(nn.Module):
def __init__(self):
super(LHSE, self).__init__()
self.conv1h = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
self.bn1h = nn.BatchNorm2d(64)
self.conv2h = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
self.bn2h = nn.BatchNorm2d(64)
self.conv3h = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
self.bn3h = nn.BatchNorm2d(64)
self.conv4h = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
self.bn4h = nn.BatchNorm2d(64)
self.conv1v = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
self.bn1v = nn.BatchNorm2d(64)
self.conv2v = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
self.bn2v = nn.BatchNorm2d(64)
self.conv3v = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
self.bn3v = nn.BatchNorm2d(64)
self.conv4v = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
self.bn4v = nn.BatchNorm2d(64)
def forward(self, left, down):
if down.size()[2:] != left.size()[2:]:
down = F.interpolate(down, size=left.size()[2:], mode='bilinear')
out1h = F.relu(self.bn1h(self.conv1h(left )), inplace=True)
out2h = F.relu(self.bn2h(self.conv2h(out1h)), inplace=True)
out1v = F.relu(self.bn1v(self.conv1v(down )), inplace=True)
out2v = F.relu(self.bn2v(self.conv2v(out1v)), inplace=True)
fuse = out2h*out2v
out3h = F.relu(self.bn3h(self.conv3h(fuse )), inplace=True)+out1h
out4h = F.relu(self.bn4h(self.conv4h(out3h)), inplace=True)
out3v = F.relu(self.bn3v(self.conv3v(fuse )), inplace=True)+out1v
out4v = F.relu(self.bn4v(self.conv4v(out3v)), inplace=True)
return out4h, out4v
def initialize(self):
weight_init(self)
## 如下代码是使用torch对LHSE模块的搭建
class TFAM(nn.Module):
def __init__(self, in_channels, out_channels, tfam_channels=64):
super(TFAM, self).__init__()
# Series of 1x1 conv to generate attention feature maps
self.pab_channels = tfam_channels
self.in_channels = in_channels
self.top_conv = nn.Conv2d(in_channels, tfam_channels, kernel_size=1)
self.center_conv = nn.Conv2d(in_channels, tfam_channels, kernel_size=1)
self.bottom_conv = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)
self.map_softmax = nn.Softmax(dim=1)
self.out_conv = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)
def forward(self, x):
bsize = x.size()[0]
h = x.size()[2]
w = x.size()[3]
x_top = self.top_conv(x)
x_center = self.center_conv(x)
x_bottom = self.bottom_conv(x)
x_top = x_top.flatten(2)
x_center = x_center.flatten(2).transpose(1, 2)
x_bottom = x_bottom.flatten(2).transpose(1, 2)
sp_map = torch.matmul(x_center, x_top)
sp_map = self.map_softmax(sp_map.view(bsize, -1)).view(bsize, h * w, h * w)
sp_map = torch.matmul(sp_map, x_bottom)
sp_map = sp_map.reshape(bsize, self.in_channels, h, w)
x = x + sp_map
x = self.out_conv(x)
return x
下面这段代码实现了一个深度学习模型的训练过程,可以有效地训练深度学习模型,用于解决像素级别的图像分割任务,同时通过验证数据集进行模型性能的评估和调优:
# 定义训练函数
def train(train_loader, model, criterion1,optimizer, epoch, params,global_step):
metric_monitor = MetricMonitor() # 初始化指标监视器
model.train() # 设置模型为训练模式
stream = tqdm(train_loader,desc='processing',colour='CYAN') # 创建数据加载器的进度条
for i, (images, masks,_) in enumerate(stream, start=1): # 遍历数据加载器
images = images.cuda(non_blocking=params['non_blocking_']) # 将图像数据传输到GPU
masks = masks.cuda(non_blocking=params['non_blocking_']) # 将掩码数据传输到GPU
reg_outs = model(images) # 通过模型前向传播图像数据
reg_outs = torch.sigmoid(reg_outs) # 应用Sigmoid激活函数
loss = criterion1(reg_outs, masks) # 计算损失
optimizer.zero_grad() # 清空优化器的梯度
loss.backward() # 反向传播计算梯度
optimizer.step() # 更新模型参数
global_step += 1 # 增加全局步数
# 定义训练和验证函数
def train_and_validate(model, optimizer,train_dataset,val_dataset, params,epoch_start = 1,best_acc=0):
train_loader = DataLoader( # 创建训练数据加载器
train_dataset,
batch_size=params["batch_size"], # 指定批量大小
shuffle=True, # 随机打乱数据
num_workers=params["num_workers"], # 指定工作进程数
pin_memory=True, # 是否将数据固定在内存中
drop_last=True, # 是否丢弃最后一个不完整的批量
)
val_loader = DataLoader( # 创建验证数据加载器
val_dataset,
batch_size=params["test_batch_size"], # 指定批量大小
shuffle=False, # 不随机打乱数据
num_workers=params["num_workers"], # 指定工作进程数
pin_memory=True, # 是否将数据固定在内存中
drop_last=False, # 不丢弃最后一个不完整的批量
)
# 定义损失函数
criterion_1 = WeightedDiceBCE(dice_weight=5,BCE_weight=5).cuda()
global_step = 0 # 初始化全局步数为0
for epoch in range(epoch_start, params["epochs"] + 1): # 遍历指定的训练周期
train(train_loader, model,criterion_1,optimizer, epoch, params,global_step) # 调用训练函数
写在最后
随着技术的不断发展,AI在图像处理和分析领域展现出了惊人的能力。当涉及到揪出图片中的“李鬼”——即识别并区分真实图片与伪造、篡改或合成的图片时,AI技术发挥了至关重要的作用,AI之所以能够揪出图片中的“李鬼”,主要依赖于深度学习和计算机视觉技术。深度学习模型,特别是卷积神经网络(CNN),通过训练大量真实和伪造的图片数据,能够学习到图片中的细微特征和模式。这些特征和模式包括像素级的细节、图像的光照和阴影变化、物体的形状和纹理等。
一旦AI模型被训练好,它就可以对新的图片进行分析和判断。通过比较输入图片与训练数据中的特征,AI能够识别出图片是否经过篡改或合成。例如,如果一张图片中的某个区域与其他部分的光照条件不一致,或者存在不自然的像素过渡,AI就可能会将其标记为伪造图片。
然而,需要注意的是,AI在揪出图片中的“李鬼”时并非万无一失。由于伪造技术的不断进步和复杂化,AI可能会面临一些挑战和限制。例如,一些高级的伪造技术可以模拟真实图片的特征和模式,使得AI难以区分真实与伪造。此外,AI也可能存在误判的情况,将真实图片错误地标记为伪造图片,因此,在使用AI进行图片验证和识别时,我们需要综合考虑多种因素和技术手段,以提高其准确性和可靠性。同时,我们也需要不断研究和探索新的算法和技术,以应对伪造技术的不断发展和挑战。
详细复现过程的项目源码、数据和预训练好的模型可从该文章下方附件获取。