首页 > 其他分享 >传知代码-揭秘AI如何揪出图片中的“李鬼”(论文复现)

传知代码-揭秘AI如何揪出图片中的“李鬼”(论文复现)

时间:2024-07-17 19:26:22浏览次数:19  
标签:nn 传知 AI 检测 self 李鬼 模块 图像 篡改

代码以及视频讲解

本文所涉及所有资源均在传知代码平台可获取

文字篡改图像的“照妖镜”:揭秘AI如何揪出图片中的“李鬼”

在数字化时代,我们时常被各种图像信息所包围。然而,这些图像中有时隐藏着不为人知的秘密——被篡改的文字或图像。这些被篡改的内容可能误导我们的判断,甚至在某些情况下造成严重的后果。幸运的是,随着人工智能(AI)技术的发展,我们现在已经拥有了一种工具,可以帮助我们揪出这些图片中的“李鬼”。
我们的AI模型能够接收用户上传的疑似篡改的文字图像,并通过深度学习和图像分析技术,自动检测并标注出图像中疑似被篡改的区域。这对于新闻工作者、调查人员、甚至是普通网友来说,都是一项非常实用的功能。
然而,我们必须强调的是,尽管我们的模型在检测文字图像篡改方面具有较高的准确率,但它并不是万能的。AI的能力受限于其训练的数据和算法的设计。在检测物体擦除或人脸P图等更为复杂的图像篡改时,我们的模型可能无法提供同样准确的结果。这是因为这些类型的篡改通常涉及到更多的图像处理和合成技术,需要更高级的算法和更大的数据集来支持。
此外,我们还需要提醒用户,模型的效果与训练的数据集高度相关。不同的数据集会导致模型学习到不同的特征和模式。因此,使用不同的数据集训练得到的模型,在检测同一张图片时,可能会得到不同的结果。这也是为什么我们在提供这项服务时,会明确告知用户所使用的数据集和训练过程。
对于希望进一步提高检测准确率的用户,我们鼓励他们使用自己的数据集来训练模型。通过收集更多样化、更贴近实际需求的图像数据,用户可以训练出更加精准、更加符合自己需求的模型。当然,这需要一定的技术知识和经验,但这也是AI技术带来的魅力之一——它让我们有可能根据自己的需求来定制和优化解决方案。

前言

在如今这个“P图大神”遍地走的时代,图片的真实性越来越难以保证。尤其是在文档图像领域,篡改文字、伪造证书等行为可能带来严重的风险。想象一下,你正准备签一份重要合同,却发现附件中的资质证书似乎有点不对劲。是的,你没猜错,这正是图像篡改的“作案现场”。

文字图像篡改,听起来是不是很像电影里的高级犯罪?但这可不仅仅是电影情节,它真实地发生在我们的数字生活中。文档图像篡改指的是对文档图像进行的未经授权的修改,包括文字、图表、印章等内容的删除、修改、添加或替换。 当你怀疑一张图片被篡改时,你会怎么做?是不是会像侦探一样,拿着放大镜仔细观察,寻找蛛丝马迹?AI侦探也是如此,它会运用一种叫做注意力机制的技术,就像人眼一样,不断放大缩小图像,对比观察不同区域的特征,从而精准定位篡改区域。这种技术的运用,不仅提高了检测的准确性,也极大提升了效率,让AI在图像取证领域展现出了惊人的潜力。 但AI侦探的“火眼金睛”是如何炼成的呢?这就不得不提到一项最新的研究成果——一种结合了伪造痕迹增强和多尺度注意力机制的网络框架。这个框架通过深度学习算法,能够从多个维度分析图像,识别出那些肉眼难以察觉的篡改痕迹。 研究人员们通过构建一个大规模的文本图像篡改数据集,训练AI侦探识别各种篡改手段。在实验中,AI侦探展现出了极高的准确率,即使是面对经过精心伪装的篡改图像,也难逃它的“法眼”。 这项技术的出现,无疑为我们的数字生活增添了一份安全保障。它不仅能够帮助我们识别出那些潜在的风险,更能够提升我们对数字内容的信任度。在未来,随着技术的不断进步,AI侦探将更加智能,成为我们守护信息安全的重要伙伴。

AI侦探的“放大镜”和“显微镜”:揭秘注意力机制如何工作

想象一下,当你怀疑一张图片被篡改时,你会怎么做?是不是会像侦探一样,拿着放大镜仔细观察,寻找蛛丝马迹?AI侦探也是如此,它会运用一种叫做注意力机制的技术,就像人眼一样,不断放大缩小图像,对比观察不同区域的特征,从而精准定位篡改区域。

那么,这个神秘的注意力机制是如何工作的呢?首先,AI模型会像一位细心的侦探一样,对图像进行彻底的特征提取,分析并记录下各种特征,比如颜色、纹理、形状等。这些特征就像是图像的指纹,为后续的分析提供了重要的线索。接着,模型会根据这些特征的重要性,为图像的不同区域分配不同的权重。这就好比侦探在案件中,会根据嫌疑人的可疑程度给予不同的关注。在图像篡改的案件中,那些与周围环境不一致的区域,往往就是篡改的痕迹,因此会被赋予更高的权重。最后,模型会根据权重分布,将注意力集中在最有可能被篡改的聚焦区域,进行更深入的分析。这就好比侦探在案件的关键环节,会集中精力,深入挖掘线索,力求揭开真相。注意力机制的优势显而易见。它不仅能够精准定位篡改痕迹,减少误判率,还能够高效处理图像数据,通过合理分配计算资源,只关注重要的区域。此外,它的权重分布还具有很好的可解释性,能够直观地展示模型的关注点,让整个过程更加透明。

实战演练:复现论文代码 当然,光说不练假把式。在接下来的文章中,我们将以一篇论文为例,论文题目是《Robust Text Image Tampering Localization via Forgery Traces Enhancement and Multiscale Attention》,于24年2月发表在SCI二区期刊**IEEE Transactions on Consumer Electronics上,**详细讲解文字篡改图像的检测定位技术,并带你一起复现论文中的代码。通过亲自动手实践,你将更深入地理解这项技术的原理和实现过程,也能更好地掌握AI侦探的“火眼金睛”。

论文背景

在数字化时代,图像已成为信息传播的主要载体之一。无论是社交媒体分享,还是正式文件电子版,图像都扮演着关键角色。然而,随着图像编辑技术的飞速发展,尤其是深度学习和人工智能的介入,图像篡改变得前所未有的容易。一些不法分子利用这些技术,对图像内容进行非法篡改,以达到误导、欺诈甚至更严重的犯罪目的。

其中,文字图像篡改尤其值得关注。如资质证书、官方文件、合同协议等,文字篡改可能导致极其严重的后果。一份被篡改的合同文本,可能会造成巨大的经济损失;一张伪造的身份证,可能被用于洗钱或其他犯罪活动。因此,研究和开发有效的文字图像篡改检测技术,对于维护社会秩序、保护公民权益、促进信息安全具有重大意义。相较于自然图像,文本图像中轻微的篡改(如单个字符)可能会大幅改变其语义,因此确保文本图像真实性至关重要。与自然图像相比,文本图像篡改检测面临独特挑战,包括均匀的纹理、简单的封闭边界,以及对象之间的规则间隙。篡改区域可能微小(如单个字符),与背景对比度也很微妙,这使得文本图像篡改检测更具挑战性。

文字图像篡改检测面临着独特的挑战:

  • 文字图像具有均匀的纹理、简单的边界和规则的间隙,使得篡改区域难以识别。
  • 篡改区域可能非常小(例如单个字符),并且与背景的对比度微妙,增加了检测难度。
  • 现实场景中的伪造图像可能经过压缩、重拍或图像融合等后处理,进一步掩盖了篡改痕迹,降低了检测算法的有效性。

尽管已有一些相关方法,但大多数现有算法是在受控实验室环境中开发和验证的,缺乏对真实场景的鲁棒性和普遍性考虑。在实际情况中,伪造图像不可避免地会遭受后处理,如有损压缩、重新捕捉或复杂融合,这些操作可能掩盖篡改痕迹,严重降低了篡改定位性能。

论文思路

在文字图像篡改检测这一领域,该论文提出了一种创新的网络框架,旨在提升检测的准确性和鲁棒性。论文的核心思路是通过增强篡改痕迹和应用多尺度注意力机制,来精确地定位和检测图像中的篡改区域。这一思路的提出,基于对现有技术的深刻理解和对现实挑战的准确把握。

该篇论文的主要贡献点为:

  1. 篡改痕迹增强网络:论文中提出的伪造痕迹增强网络是一个创新点。该网络能够从多个领域增强伪造痕迹,减少背景干扰,这对于提高篡改区域的检测精度至关重要。这一模块的设计,使得模型能够更好地聚焦于潜在的篡改区域,而不是被图像的非篡改部分所分散注意力。
  2. 多尺度注意力机制:通过设计一个多尺度注意力模块,论文进一步创新了特征融合策略。这种机制类似于人类视觉系统的工作方式,能够同时关注图像的宏观结构和微观细节,从而更全面地捕捉篡改特征。
  3. 编码器-解码器网络:论文中提出的编码器-解码器网络结构,通过融合高级语义和低级视觉细节,进一步提升了篡改特征的提取能力。这种结构的设计,使得模型在处理复杂的图像篡改时,能够保持高效的特征传递和信息恢复。
  4. 大规模数据集构建:为了验证所提方法的有效性,研究者构建了一个大规模的文本图像篡改数据集。该数据集包含了多种篡改方法和失真情况,为研究者提供了一个全面评估模型性能的平台。

在文字图像篡改检测领域,该论文的提出的方法与现有技术相比,具有显著的优势。传统的篡改检测方法往往依赖于单一的特征提取或简单的机器学习模型,这在面对复杂的篡改手段时,容易受到干扰和欺骗。而该论文提出的方法,通过深度学习技术的应用,能够从更深层次理解图像内容,从而提高检测的准确性。此外,论文中的方法在设计时,充分考虑了现实世界中的复杂情况。例如,现实世界中的篡改图像往往会经历多次压缩、传输和编辑,这些操作会在图像中留下难以察觉的痕迹。通过增强这些痕迹并应用多尺度分析,论文中的方法能够有效地抵抗这些干扰,提高检测的鲁棒性。论文中的模型在多种真实世界的失真场景下进行了测试,包括JPEG压缩、图像重摄和屏幕截图等。这些测试结果证明了模型不仅在理论上是可行的,而且在实际应用中也具有很高的鲁棒性。

模型结构

该论文针对这一问题,提出了一种创新的解决方案,如图所示,该方法主要包括三个关键阶段:训练数据集的构建,篡改痕迹增强和文本图像篡改定位。

篡改痕迹增强网络

经过篡改的文本图像常常会经历如JPEG压缩等后处理操作,这些操作往往会损害或掩盖篡改的痕迹。针对这一问题,该论文提出了一种篡改痕迹增强网络模块,其核心目的是提升图像定位在面临有损后处理时的鲁棒性。

该网络模块由两个主要部分构成:多模态特征提取器和篡改痕迹增强网络。多模态特征提取器采用两种不同的特征算子,分别从空间域和错误级域中提取篡改的线索。恢复网络则采用融合的特征,并应用类似UNet的网络结构,其主要目标是通过残差学习来恢复细微的篡改痕迹。此外,该恢复网络还能抑制非篡改相关的图像伪影,并尝试恢复纯篡改图像,以便于进一步的定位。

该网络结合了误差级别分析(Error Level Analysis,ELA)和空间丰富模型(Spatial Rich Model,SRM)来提取粗略的篡改伪影。SRM模块在空间域中操作,提供了图像的空间统计信息和文本结构的重要线索。ELA模块则在误差级别域中工作,揭示出篡改过程中引入的差异和伪影。这两种模态的融合为后续模块提供了区分真实区域和被篡改区域的有力特征。因此,多模态特征提取器包括ELA和SRM两个算子,其可表示为:

F E L A = ∣ I − J ( I ) ∣ , \mathbf{F}_{\mathrm{ELA}}=|\mathbf{I}-\mathcal{J}(\mathbf{I})|, FELA​=∣I−J(I)∣,

F S R M = S ( I ) , \mathbf{F}_{\mathrm{SRM}}=\mathcal{S}(\mathbf{I}), FSRM​=S(I),

考虑输入图像 I \mathbf{I} I,以及经过预设质量因子进行的有损JPEG压缩函数 J ( ) \mathcal{J}() J()。特征提取器 S ( ) \mathcal{S}() S()用于从图像中提取特征图 F E L A \mathbf{F}_{\mathrm{ELA}} FELA​和 F S R M \mathbf{F}_{\mathrm{SRM}} FSRM​分别代表ELA和SRM特征图。恢复网络 U ( ) \mathcal{U}() U()采用U-Net结构,并利用残差学习技术以恢复难以察觉的篡改痕迹。该网络通过残差连接将来自收缩路径的篡改特征与来自扩张路径的恢复特征相融合,不仅强化了篡改的迹象,同时剔除了原始特征中的冗余信息。恢复过程可以用以下数学表达式表示:

I ^ = I + U ( C o n C a t ( F E L A , F S R M ) ) , \mathbf{\hat{I}}=\mathbf{I}+\mathcal{U}\left(\mathrm{ConCat}\left(\mathbf{F}_{\mathrm{ELA}},\mathbf{F}_{\mathrm{SRM}}\right)\right), I^=I+U(ConCat(FELA​,FSRM​)),

其中 I ^ \mathbf{\hat{I}} I^表示最终恢复的图像,而 C o n C a t ( ) \mathrm{ConCat}() ConCat()代表级联操作。通过引入恢复网络,提出的篡改痕迹增强架构能够在文本图像经有损后处理传输时,提高篡改定位的鲁棒性,减轻有损压缩等后处理操作对图像质量的影响。

文本图像篡改定位网络

在文字图像篡改检测领域,该论文引入了一个关键创新点——LHSE(Local and Hierarchical Semantic Enhancement)模块。该模块旨在通过局部和层次化的语义增强,进一步提升篡改检测的性能。具体来说,LHSE模块首先利用局部卷积操作精细捕捉图像中的局部特征,这些特征能够精确反映图像各区域的细节信息,特别是潜在的篡改区域。通过精心设计的卷积核大小和步长,模块能够提取出多尺度的局部特征,为后续的语义增强提供了丰富的信息基础。

接下来,LHSE模块利用层次化的语义融合策略整合这些局部特征。它采用多尺度金字塔结构,将不同层次的特征进行融合,从而全面捕获从微观到宏观的全方位信息。这种层次化的处理方式不仅有助于模型更好地理解图像的结构和上下文信息,还显著提高了篡改检测的准确性。

为了进一步增强篡改痕迹的表达能力,LHSE模块还引入了一种语义增强机制。通过对特征图进行非线性变换和重新加权,模块能够突出显示潜在的篡改区域,并有效抑制背景干扰。这种增强操作使模型能够更加专注于篡改痕迹,从而提高了检测的灵敏度。

在实际应用中,LHSE模块不仅显著增强了图像中篡改痕迹的表达能力,使模型能够更准确地定位和识别篡改区域,还提高了检测的精度和可靠性。同时,该模块的设计充分考虑了现实世界中的多种失真场景,如JPEG压缩、图像重摄等,通过提取多尺度的局部特征和进行层次化的语义融合,模块能够在这些复杂场景下保持稳定的性能,从而增强了模型的鲁棒性。

下图是对LHSE模块前后的特征映射的可视化。从左到右两列分别为输入的篡改图像、真实掩模、LHSE模块前后的特征结果。由最后一列的结构可以看出,LHSE模块生成的融合特征图有效地捕获了被篡改的区域。

TFAM模块是该论文提出的一个重要组成部分,旨在提高文本图像篡改检测的准确性。该模块采用了空间注意力机制,能够学习特征图上不同位置之间的关系,从而增强模型对篡改区域的全局语义理解。具体而言,TFAM模块首先获取来自LHSE模块输出的特征图,然后通过1x1卷积层生成两个特征图 F a F_a Fa​和 F b F_b Fb​。接着, F a F_a Fa​和 F b F_b Fb​被重塑为矩阵形式,并通过softmax函数计算特征图上每个位置之间的相关性,生成空间注意力图A。A的每个元素反映了不同位置特征之间的关系,有助于学习篡改特征的全局语义关系。随后,空间注意力图A与特征图进行矩阵乘法,得到加权特征图 F t f a m F_{tfam} Ftfam​,最后通过3x3卷积层输出最终的特征图 F T F_T FT​。
TFAM模块的功能在于通过学习特征图上不同位置之间的依赖关系,增强网络对篡改区域的全局理解,从而提高篡改检测的准确性。它能够抑制背景噪声,并使网络更加关注篡改区域,学习到更具有区分性的特征。因此,TFAM模块在文本图像篡改检测中发挥着关键作用,提高了模型的性能和稳健性。

下图是对TFAM模块前后的特征映射的可视化。从左到右两列分别为输入图像、真实掩模、TFAM模块前后的特征结果。。由最后一列的结构可以看出,TFAM的特征映射输出集中在伪造区域,并且消除了背景纹理噪声的影响,这说明了TFAM模块的有效性。

损失函数

该论文提出了一种损失函数,旨在提高文本图像篡改检测的准确性。该损失函数将权重二进制交叉熵(WeightBCE)和权重骰子损失(WeightDice)进行组合,以平衡正负样本和困难样本的权重。

具体而言,权重二进制交叉熵损失函数通过引入额外的权重参数q,控制负样本与正样本的比例,从而有效解决训练过程中正负样本的不平衡问题。权重骰子损失函数则计算预测掩膜和对应真值掩膜之间的交集和并集,以量化预测和真值之间的重叠程度。同时,通过引入权重参数p,该损失函数可以调整困难样本的权重,以提高检测的准确性。

综合而言,该损失函数能够有效地利用权重二进制交叉熵损失函数的优势,惩罚模型在错误区域过度自信的倾向,同时利用权重骰子损失函数的优势,量化预测和真值之间的重叠程度。通过合理地平衡正负样本和困难样本的权重,该损失函数在文本图像篡改检测任务中取得了较好的性能。

L t o t a l = λ 1 L W e i g h t B C E + ( 1 − λ 1 ) L W e i g h t D i c e . L_{\mathrm{total}}=\lambda_1L_{\mathrm{WeightBCE}}+(1-\lambda_1)L_{\mathrm{WeightDice}}. Ltotal​=λ1​LWeightBCE​+(1−λ1​)LWeightDice​.

L Weight-BCE = − q ⋅ y log ⁡ ( y ^ ) − ( 1 − q ) ( 1 − y ) log ⁡ ( 1 − y ^ ) L_{\text{Weight-BCE}}=-q\cdot y\log{(\hat{y})}-(1-q) (1-y)\log{(1-\hat{y})} LWeight-BCE​=−q⋅ylog(y^​)−(1−q)(1−y)log(1−y^​)

L Weight-DICE = 1 − 2 ∑ i ( p ⋅ intersection i ) ∑ i ( p ⋅ union i ) , L_\text{Weight-DICE}=1-\frac{2\sum_i(p\cdot\text{intersection}_i)}{\sum_i(p\cdot\text{union}_i)}, LWeight-DICE​=1−∑i​(p⋅unioni​)2∑i​(p⋅intersectioni​)​,

复现过程

在图像篡改检测的研究领域,首先关注实验结果的可视化图像,其中“Images”列展示了被篡改的原始图像,而“Mask”列则呈现了对应的篡改区域。该研究的主要目标是实现图像篡改区域的精确定位。从图像分类的角度来看,这个问题可以被视为一个逐像素级别的二分类任务。具体来说,针对被篡改的图像A中的每个像素点(x,y),模型需要对其是否被篡改进行判断。如果模型判断一个像素点被篡改,则输出1;否则,输出0。通过这种方式,所有像素点的0和1输出组合成了一张与原始图像A分辨率相同的二值掩膜图像。在这张掩膜图像中,白色区域代表了图像中被篡改的位置,而黑色区域则表示未被篡改的部分。通过生成精确的篡改区域图,篡改检测模型能够辅助用户识别和定位图像中的不真实内容。在本文的可视化结果中,所提出的方法表现出对小规模篡改区域的精确定位能力,例如单个数字或字符的篡改。这种能力得益于所采用的多尺度特征融合机制,它能够有效整合高层语义特征和低层视觉细节。此外,从可视化结果中可以观察到,所提出的方法不仅能够突出微小篡改区域,而且能够有效抑制背景噪声,尤其在复杂文本图像背景下,仍能准确识别篡改区域,不受背景噪声的干扰。

复现过程可以分解成以下几个模块分别实现(以下只给出代码的关键部分):

  1. 使用python代码实现给出的损失函数公式;
  2. 使用pytorch代码搭建模型网络结构搭建;
  3. 整体训练框架搭建;
  4. 设置参数,训练和测试模型;

步骤一:

  • 使用python代码实现给出的损失函数公式,由上可得,总损失函数由两个损失函数组成,分别是Weighted BCE Loss Weighted Dice Loss
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

步骤二:

  • 使用pytorch代码搭建模型网络结构搭建,这一步的关键是根据对网络的描述实现对上述LHSE模块和TFAM模块的结构搭建:

    ## 如下代码是使用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
    

步骤三:

  • 整体训练框架搭建,该步骤主要包含对数据集的处理和加载、loss的梯度更新等
# 定义训练函数
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)  # 调用训练函数

附件代码说明:

步骤一:准备环境和数据集

  1. 下载数据集:
    • 根据附件txt文件中提供的数据集下载地址,下载所需的图像篡改检测定位的数据集。
    • 确保数据集下载完成后,放置在合适的位置,以便后续操作可以正确引用。
  2. 安装依赖:
    • 确保您的Python环境已经安装,并安装了代码运行所需的所有依赖库。
    • 如果需要,可以使用pip install命令安装缺失的库。

步骤二:训练模型

  1. 运行训练脚本:
    • 打开终端或命令提示符,定位到代码所在的目录。
    • 运行python main.py命令开始训练过程。
    • 等待训练完成,这可能需要一些时间,具体取决于数据集的大小和计算机的性能。

步骤三:准备测试环境

  1. 获取预训练模型:
    • 从附件txt文件中获取作者提供的预训练模型文件。
    • 将模型文件放置在代码可以访问的路径下。
  2. 准备测试数据集:
    • 如果已经有自己的测试数据集,确保图像和对应的mask图像文件名相同,并分别放在./test_dataset/val_img./test_dataset/val_mask目录下。
    • 如果没有mask图像,只需将图像文件放在./test_dataset/val_img目录中,并在代码中相应位置将val_gt_mask_dir设置为与val_img_dir相同的路径。

步骤四:运行测试脚本

  1. 修改测试数据集路径:
    • 打开test.py脚本,找到定义测试数据集路径的部分。
    • 根据实际情况修改val_img_dirval_gt_mask_dir(如果需要的话)为测试数据集的正确路径。
  2. 运行测试:
    • 在终端或命令提示符中,运行python test.py命令。
    • 脚本将使用预训练模型对测试数据集中的图像进行篡改检测定位,并生成预测结果。

步骤五:查看预测结果

  1. 检查预测结果:
    • 预测完成后,生成的图像将保存在./test_dataset/predict_results目录中。
    • 您可以打开该目录,查看预测结果图像,并与实际图像进行对比分析。

操作界面说明

此外,还开发了一个桌面版的GUI界面和一个网页版的web供算法的可视化演示。

一、桌面版GUI界面使用步骤

  1. 启动GUI界面:

    • 运行app.py文件,将会弹出一个图形用户界面。
  2. 选择待检测图像:

    • 在GUI界面中,点击请选择待检测图像按钮。
    • 导航至test_data目录下的img文件夹,该文件夹中存放了用于测试的示例图像。
    • 选择一张待检测的图像,并点击OK按钮。
  3. 加载并显示图像:

    • GUI界面左侧将加载并显示所选的疑似篡改图像。
  4. 进行篡改检测:

    • 点击篡改检测按钮,程序将开始对图像进行篡改检测。
    • 稍等几秒钟,界面右侧将显示疑似篡改的区域。
  5. 查看检测结果:

    • 检测结果以热力图的形式展示,越接近蓝色的区域表示越不可能是篡改区域,而越接近红色的区域则表示更可能是篡改区域。
    • 通过观察热力图,可以清晰地识别出图像中的篡改部分。
  6. 扩展功能:

    • 除了检测一般的篡改图像,该GUI界面还支持检测聊天截图中可能存在的篡改区域。

二、网页版web使用步骤

  1. 启动web服务:
    • 运行python web.py文件,将启动一个web服务。
  2. 访问web界面:
    • 打开浏览器,输入指定的网址(通常是localhost:7865),即可访问web界面。
  3. 上传待检测图像:
    • 在web界面中,找到图像上传功能,选择一张待检测的图像进行上传。
  4. 进行篡改检测:
    • 上传完成后,web界面将自动对图像进行篡改检测。
    • 等待片刻,检测结果将显示在web界面上。
  5. 查看检测结果:
    • 检测结果同样以热力图的形式呈现,用户可以通过观察热力图来判断图像中的篡改区域。


无论是使用桌面版GUI界面还是网页版web,用户都可以方便地进行图像篡改检测,并直观地查看检测结果。这些工具为图像篡改检测提供了便捷的可视化演示方式,有助于用户更好地理解和应用相关算法。

亲爱的读者朋友们,下次当你面对一张令人怀疑的图片时,不妨让我们的AI侦探出马,让它帮你揭开隐藏在像素之下的秘密。在这个充满变数的数字世界里,让我们携手AI,共同守护信息的真实与安全。

参考文献

[1] Dong, L., Liang, W., & Wang, R. (2024). Robust Text Image Tampering Localization via Forgery Traces Enhancement and Multiscale Attention. IEEE Transactions on Consumer Electronics.

源码下载

标签:nn,传知,AI,检测,self,李鬼,模块,图像,篡改
From: https://blog.csdn.net/chuanzhi_tech/article/details/140503374

相关文章

  • whisper-api语音识别语音翻译高性能兼容openai接口协议的开源项目
    whisper-api介绍使用openai的开源项目winsper语音识别开源模型封装成openaichatgpt兼容接口软件架构使用uvicorn、fastapi、openai-whisper等开源库实现高性能接口更多介绍[https://blog.csdn.net/weixin_40986713/article/details/138712293](https://blog.csdn.net......
  • python ssl报错 aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot
    报错信息原代码:asyncwithsession.post(url,headers=headers,data=payload)asresponse:print(f"{id}签到结果:",awaitresponse.text())原因:在使用aiohttp进行HTTPS请求时,如果没有设置正确的SSL证书验证,就可能会出现以上问题解决办法忽略SSL......
  • Doris failed to initialize storage reader. tablet=106408, res=[NOT_IMPLEMENTED_E
    ApacheDoris2.3以下的版本会存在一个bug,导致数据在合并时存在异常,在后续查询该字段数据时会提示[1105][HY000]:errCode=2,detailMessage=(192.168.15.228)[CANCELLED]failedtoinitializestoragereader.tablet=106408,res=[NOT_IMPLEMENTED_ERROR]tobeimplemen......
  • 7、nginx-日志模块的格式-log_format main、access.log(访问服务器记录的日志)
    日志模块的名称:ngx_http_log_module路径:vim/etc/nginx/nginx.conf相关指令:·日志格式:log_format---nginx有非常灵活的日志模式,每个级别的配置可以有各自独立的访问日志、日志格式通过log_format命令定义··语法Syntax:log_formatname[escape=default|json]......
  • 利用FastAPI和OpenAI-Whisper打造高效的语音转录服务
    最近好久没有写博客了,浅浅记录下如何将OpenAI-Whisper做成Web服务吧......
  • AI论文写作软件哪些好用?
    以下是一些被认为好用的AI论文写作软件,它们各自有不同的特点和优势,可以根据您的具体需求来选择:1、writehelp论文写作:可以免费生成论文大纲快速完成论文初稿优点:输入题目一键生成完整论文并提供(知网、维普)论文查重报告,内容逻辑连贯性、语句通顺度、结构完整性均在95%以上,生......
  • 仅靠AI视频收入6万,AI副业太炸裂了!
    仅靠AI视频收入6万,这个项目究竟有多炸裂?仅靠简单的英语AI早教视频,快速在40天内涨粉到10万,按照广告费为粉丝量的3%~6%计算,一条广告为5000元左右,再加上其他的变现方式,一个月轻轻松松收入几万元!还有下面账号在短短10天内,粉丝从3.8万涨到4.3万,获赞5.2万,通过开通店铺售卖《100......
  • Raid1创建
    创建RAID1(镜像)阵列在CentOS7上的实验过程如下。RAID1提供了数据冗余,这意味着在其中一块硬盘故障时,数据可以从另一块硬盘恢复,但同时它的性能和容量利用率低于RAID0。如果想要使用/dev/sdb和/dev/sdc这两个完整硬盘来创建一个RAID1镜像阵列,你需要首先确保这两个硬......
  • 19集 两款ESP32开发板如何选择?-《MCU嵌入式AI开发笔记》
    19集两款ESP32开发板我们用哪款?-《MCU嵌入式AI开发笔记》有两款ESP32的开发板分别是ESP32S3和C3的,我们该如何选择?1、ESP32-S3-BOX-3在乐鑫官网上,https://www.espressif.com.cn/zh-hans/products/devkits有ESP32S3BOX开发板,链接如下:https://github.com/espressif/es......
  • 2024-07-17 vite打包vue项目,无法正确加载,报错:TypeError: Failed to resolve module sp
    我这会打算打个包扔到线上看看效果,结果线上报错:TypeError:Failedtoresolvemodulespecifier"vue".Relativereferencesmuststartwitheither"/","./",or"../".奇怪,之前还好好的,因为本地调试什么的都正常,甚至昨天都可以打包。我不信邪,遂新建vue项目,做一下测试,这......