(五)PS识别:压缩痕迹挖掘-压缩量化表与 DCT 系数分析

 (一)PS识别: Python 图像分析PS识别之道

 (二)PS识别: 特征识别-直方图分析的从原理到实现

(三)PS识别:基于噪声分析PS识别的技术实现

(四)PS识别:基于边缘纹理检测分析PS识别的技术实现

一 介绍

      本文将介绍一种基于量化表分析和 DCT 系数分析的图片 PS 检测方法,帮助你判断图片是否经过处理。

二 实现原理

量化表分析

         在 JPEG 图片的压缩过程中,量化表起着关键作用。不同的软件或处理操作可能会改变量化表的数值分布。我们通过计算量化表中最大值与最小值的差异,以及标准差等指标,来判断图片是否可能经过 PS 处理。如果量化表差异过大,就意味着图片可能在后期被修改过。

DCT 系数分析

        DCT(离散余弦变换)是 JPEG 压缩的核心步骤之一。对图片进行 DCT 变换后,低频系数包含了图片的主要信息,高频系数则反映了细节和噪声。经过 PS 处理的图片,其 DCT 系数的分布往往会发生变化。我们通过计算低频系数的方差,以及高频系数的分布等特征,来判断图片是否存在处理痕迹。

三 代码实现

以下是将该检测方法封装成通用类的 Python 代码:


from skimage.io import imread
from skimage.color import rgb2ycbcr
from scipy.fftpack import dct
import numpy as np
from PIL import Image, JpegImagePlugin
import cv2


class PSImageAnalyzer:
    def __init__(self, quant_max_diff_threshold=100, dct_low_freq_var_threshold=1000, block_size=8, save_marked_image=False, save_path=None):
        """
        初始化 PS 图片分析器

        :param quant_max_diff_threshold: 量化表最大差异阈值
        :param dct_low_freq_var_threshold: DCT 低频系数方差阈值
        :param block_size: DCT 分块大小
        :param save_marked_image: 是否保存标注图片
        :param save_path: 标注图片保存路径
        """
        self.quant_max_diff_threshold = quant_max_diff_threshold
        self.dct_low_freq_var_threshold = dct_low_freq_var_threshold
        self.block_size = block_size
        self.save_marked_image = save_marked_image
        self.save_path = save_path

    def analyze_quantization_table(self, image_path):
        """
        分析 JPEG 图片的量化表,判断图片是否可能经过 PS 处理。

        :param image_path: 图片文件的路径
        :return: 一个元组,包含布尔值和相应的提示信息
        """
        try:
            img = Image.open(image_path)
            if isinstance(img, JpegImagePlugin.JpegImageFile):
                q_table = img.quantization
                if q_table:
                    q_table = np.array(list(q_table.values()))
                    max_diff = np.max(q_table) - np.min(q_table)
                    if max_diff > self.quant_max_diff_threshold:
                        return True, "量化表差异大,可能被处理过"
                    return False, "量化表正常"
                return False, "未找到量化表"
            return False, "图片不是 JPEG 格式"
        except Exception as e:
            return False, f"错误: {e}"

    def analyze_dct_coefficients(self, image_path):
        """
        分析图片的 DCT 系数,判断图片是否可能经过 PS 处理。
        同时标记出可能存在问题的 DCT 块。

        :param image_path: 图片文件的路径
        :return: 一个元组,包含布尔值、相应的提示信息和标记后的图片
        """
        try:
            image = imread(image_path)
            marked_image = image.copy()
            ycbcr = rgb2ycbcr(image)
            y_channel = ycbcr[:, :, 0]
            dct_blocks = []
            suspicious_blocks = []
            for i in range(0, y_channel.shape[0], self.block_size):
                for j in range(0, y_channel.shape[1], self.block_size):
                    block = y_channel[i:i + self.block_size, j:j + self.block_size]
                    if block.shape == (self.block_size, self.block_size):
                        dct_block = dct(dct(block, axis=0, norm='ortho'), axis=1, norm='ortho')
                        dct_blocks.append(dct_block)
                        low_freq_var = np.var(dct_block[:2, :2])
                        if low_freq_var > self.dct_low_freq_var_threshold:
                            suspicious_blocks.append((i, j))

            dct_blocks = np.array(dct_blocks)
            mean_dct = np.mean(dct_blocks, axis=0)
            low_freq_var = np.var(mean_dct[:2, :2])
            if low_freq_var > self.dct_low_freq_var_threshold:
                for i, j in suspicious_blocks:
                    cv2.rectangle(marked_image, (j, i), (j + self.block_size, i + self.block_size), (0, 0, 255), 1)
                return True, "DCT 低频系数方差大,可能被处理过", marked_image
            return False, "DCT 系数正常", marked_image
        except Exception as e:
            return False, f"错误: {e}", image

    def is_ps_combined_check(self, image_path):
        """
        综合量化表分析和 DCT 系数分析,判断图片是否可能经过 PS 处理。

        :param image_path: 图片文件的路径
        :return: 一个元组,包含布尔值、相应的提示信息和标记后的图片
        """
        quant_is_ps, quant_message = self.analyze_quantization_table(image_path)
        dct_is_ps, dct_message, marked_image = self.analyze_dct_coefficients(image_path)

        final_is_ps = quant_is_ps or dct_is_ps
        final_messages = []
        if quant_is_ps:
            final_messages.append(quant_message)
        if dct_is_ps:
            final_messages.append(dct_message)

        if final_is_ps:
            final_message = "检测到可能的 PS 痕迹:" + ", ".join(final_messages)
            if self.save_marked_image and self.save_path:
                cv2.imwrite(self.save_path, cv2.cvtColor(marked_image, cv2.COLOR_RGB2BGR))
        else:
            final_message = "未检测到 PS 痕迹,图片正常。"

        return final_is_ps, final_message, marked_image


# 使用示例
if __name__ == "__main__":
    analyzer = PSImageAnalyzer(
        quant_max_diff_threshold=100,
        dct_low_freq_var_threshold=1000,
        block_size=8,
        save_marked_image=True,
        save_path='marked_image.jpg'
    )
    is_ps, message, marked_image = analyzer.is_ps_combined_check('2.jpg')
    print(f"是否 PS: {is_ps}, 信息: {message}")

    # 显示标记后的图片
    cv2.imshow('Marked Image', cv2.cvtColor(marked_image, cv2.COLOR_RGB2BGR))
    cv2.waitKey(0)
    cv2.destroyAllWindows()

参数调整与影响

量化表最大差异阈值(quant_max_diff_threshold)
          此阈值如同一个“松紧调节器”。当数值增大时,判断标准变得宽松,这可能会让一些经过 PS 处理但量化表差异相对较小的图片“蒙混过关”,降低检测的敏感度;而当数值减小时,判断标准更为严格,虽能提高对处理图片的捕捉能力,但也可能因过于敏感而将正常图片误判为经过 PS 处理。

DCT 低频系数方差阈值(dct_low_freq_var_threshold)
             该阈值的调整直接影响着对图片 DCT 系数变化的敏感度。增大阈值,意味着需要更大的低频系数方差才会判定图片可能被处理,这可能会遗漏一些细微的处理痕迹;减小阈值,则能更敏锐地捕捉到图片的变化,但也容易将正常的图像波动误判为处理痕迹。

DCT 分块大小(block_size)
     分块大小决定了对图片分析的细致程度。较大的分块就像用广角镜头观察图片,更侧重于整体特征,可能会忽略一些局部的 PS 处理痕迹;较小的分块则如同使用显微镜,能更细致地观察局部细节,但同时也会增加计算量,并且可能受到图片噪声等因素的干扰,导致误判率上升。

是否保存标注图片(save_marked_image)与保存路径(save_path)
这两个参数为开发者提供了灵活的结果管理方式。根据实际需求,选择是否保存标注图片,能够方便后续对检测结果进行深入分析和复查,同时合理设置保存路径有助于对检测结果进行有序的组织和管理。

总结


          通过量化表分析和 DCT 系数分析,我们可以在一定程度上判断图片是否经过 PS 处理。开发人员可以根据实际情况调整参数,平衡检测敏感度和误判率。这种方法虽然不能 100% 准确判断图片是否经过处理,但为图片真实性鉴定提供了一种有效的思路和工具。

你可能感兴趣的:(机器学习,python,图像处理,人工智能,计算机视觉)