(六)PS识别:源数据分析- 挖掘图像的 “元语言”技术实现

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

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

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

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

介绍

本文介绍的 PSExifChecker 类便是利用 exifreadpiexifPILpython - magic 等库,通过读取图片的 EXIF 元数据和文件信息,对图片进行多维度检测的实现。

原理

这段代码主要用于检测图片是否经过 Photoshop 处理或者是否为截图,核心原理是通过读取图片的 EXIF(Exchangeable Image File Format)元数据,根据元数据中的信息(如软件信息、拍摄设备信息等)以及图片的基本属性(如分辨率、文件类型等)来判断图片是否可疑。

实现思路

  1. 元数据读取 :使用 exifreadpiexif 库读取图片的 EXIF 元数据。
  2. 截图检测:通过检查元数据的数量、图片分辨率以及软件标签等信息判断图片是否为截图。
  3. PS 处理检测 :检查元数据中的软件信息是否包含 PhotoshopPS,判断图片是否经过 Photoshop 处理。
  4. 设备信息检测:检查元数据中的拍摄设备信息,若截图中出现异常拍摄设备信息,则认为图片可能被修改。
  5. 文件类型检查 :使用 python - magic 库检查文件类型和扩展名是否一致。

代码逻辑

python 复制代码
import exifread

import exifread
import piexif
from PIL import Image
import magic


class PSExifChecker:

    def __init__(self):
        pass

    def process_image(self, image_path):
        try:
            with open(image_path, 'rb') as f:
                tags = exifread.process_file(f)
                if not tags:
                    return False, "无元数据"
                # 常见可疑点:软件信息含Photoshop、创建时间异常等
                software = tags.get('Image Software', '').values
                if 'Photoshop' in str(software) or 'PS' in str(software):
                    return True, "检测到PS相关软件痕迹"

                camera_model = tags.get('Image Model', '').values
                if camera_model and "screenshot" not in str(camera_model).lower():
                    return True, "截图中出现异常拍摄设备信息,可能被修改"

                return False, "元数据正常"
        except Exception as e:
            return False, "读取失败"+str(e)

    def is_ps_extract_exif_info(self, image_path):
        try:
            # 只读取指定文件格式的图片
            img = Image.open(image_path)
            img_format = img.format.upper()
            if img_format not in ['JPEG', 'TIFF']:
                return False, f"Unsupported image format: {img_format}. Only JPEG and TIFF are supported."

            exif_dict = piexif.load(image_path)
            for ifd in ("0th", "Exif", "GPS", "1st"):
                for tag in exif_dict[ifd]:
                    print(f"{piexif.TAGS[ifd][tag]['name']}: {exif_dict[ifd][tag]}")

            # Check the amount of EXIF information
            is_screenshot = len(exif_dict) == 0 or (
                    len(exif_dict) == 1 and "0th" in exif_dict and len(exif_dict["0th"]) == 0
            )

            # Check Image Width and Image Height
            if not is_screenshot:
                width = exif_dict["0th"].get(piexif.ImageIFD.ImageWidth)
                height = exif_dict["0th"].get(piexif.ImageIFD.ImageLength)
                if width and height:
                    common_resolutions = [
                        (1920, 1080),
                        (1366, 768),
                        (2560, 1440),
                        (3840, 2160),
                    ]
                    if (width, height) in common_resolutions:
                        is_screenshot = True

            # Check the Software tag
            if not is_screenshot:
                software = exif_dict["0th"].get(piexif.ImageIFD.Software)
                if software:
                    software_str = software.decode("utf-8", errors="ignore")
                    screenshot_tools = [
                        "Snipping Tool",
                        "Snip & Sketch",
                        "Greenshot",
                        "Lightshot",
                    ]
                    for tool in screenshot_tools:
                        if tool in software_str:
                            is_screenshot = True
                            break

            if is_screenshot:
                print("The image may be a screenshot.")

            return False, "Metadata is normal."
        except piexif.InvalidImageDataError as e:
            print(f"An unknown error occurred while reading EXIF information: {str(e)}")
            return True, "Failed to read EXIF information. The image may have been processed or the format is not supported."
        except Exception as e:
            print(f"An error occurred while processing EXIF information: {str(e)}")
            return True, "该图片Exif信息错误.可能被修改"

    def check_file_type(self,image_path):
        """
        检查文件类型和扩展名是否一致
        :param image_path: 图片文件路径
        :return: 检查结果
        """
        common_screenshot_formats = ["png", "bmp", "jpg", "jpeg"]
        file_type = magic.from_file(image_path)
        file_extension = image_path.split('.')[-1].lower()
        print(f"File type: {file_type}")
        print(f"File extension: {file_extension}")
        #针对截图的特殊处理:检查常见截图格式的一致性
        if file_extension in common_screenshot_formats and file_extension not in file_type.lower():
            return  True,"截图文件扩展名与检测类型不一致,可能被处理过"
        return False, "文件类型与扩展名正常"


# 启动调用
if __name__ == "__main__":
    checker = PSExifChecker()
    # 替换为你要检查的图片路径
    image_path = "new_img.jpg"
    result, message = checker.process_image(image_path)
    print(f"is_ps_check_exif 结果: {result}, 信息: {message}")

    result, message = checker.is_ps_extract_exif_info(image_path)
    print(f"is_ps_extract_exif_info 结果: {result}, 信息: {message}")

    result, message = checker.check_file_type(image_path)

    print(f"is_ps_extract_exif_info 结果: {result}, 信息: {message}")
#启动调用
PSExifChecker
  • __init__ 方法:初始化方法,目前为空。
  • process_image 方法
    1. 以二进制模式打开图片文件,使用 exifread 库读取 EXIF 元数据。
    2. 若没有元数据,返回 False, "无元数据"
    3. 检查软件信息是否包含 PhotoshopPS,若包含则返回 True, "检测到PS相关软件痕迹"
    4. 检查拍摄设备信息,若截图中出现异常拍摄设备信息,则返回 True, "截图中出现异常拍摄设备信息,可能被修改"
    5. 若以上条件都不满足,返回 False, "元数据正常"
  • is_ps_extract_exif_info 方法
    1. 使用 PIL 库打开图片,检查图片格式是否为 JPEGTIFF,若不是则返回相应错误信息。
    2. 使用 piexif 库加载 EXIF 元数据,并打印所有元数据信息。
  • check_file_type 方法
    1. 定义常见截图文件格式。
    2. 使用 python - magic 库获取文件类型,获取文件扩展名。
    3. 若文件扩展名是常见截图格式,但文件类型不包含该扩展名,则返回 True, "截图文件扩展名与检测类型不一致,可能被处理过"
    4. 否则返回 False, "文件类型与扩展名正常"

优点

  • 多维度检测:从元数据信息、图片分辨率、文件类型等多个维度进行检测,提高了检测的准确性。。
  • 扩展性强:可以方便地添加新的检测规则,以适应不同的检测需求。

缺点

  • 误判风险:仅根据元数据信息和简单规则进行判断,可能会出现误判。例如,软件信息可能被手动修改,导致检测结果不准确。
  • 兼容性问题 :只支持 JPEGTIFF 格式的图片,对于其他格式的图片无法进行检测。
  • 性能问题:在处理大量图片时,多次读取文件和解析元数据可能会导致性能下降。
相关推荐
niucloud-admin7 小时前
JAVA V6 多商户商城 开发文档——job 计划任务开发
java·python·github
小叶肥辉7 小时前
LangChain链和LangGraph图的学习笔记【三】——分别用langchain_openai库和langchain_community库调用大模型
笔记·python·langchain
2401_873479408 小时前
IP属地为什么有时显示外省?用IP查询工具核查动态分配、运营商出口与GeoIP库
python·tcp/ip·ip
OKkankan10 小时前
LangChain 能力详解!:输出解析、RAG、向量数据库与 Retriever 检索器
数据结构·python·langchain·ai应用
山哥ol11 小时前
【Geany 环境配置与中文乱码解决参考】
python
会飞锦鲤11 小时前
基于 Mask R-CNN 的药片缺陷检测系统
人工智能·pytorch·python·神经网络·resnet-50
默 语11 小时前
Java新手入门:从零开始安装JDK并配置环境变量
java·开发语言·python·mysql·group by·1024程序员节·数据去重
清水白石00812 小时前
Python 异步编程深度解析:Cancellation 到底是异常还是控制信号?从 asyncio 取消机制到企业级事务设计最佳实践
开发语言·python
Patrick在香港12 小时前
Python 审计香港开放数据目录:两个端点差 10 倍,只有 9.3% 的资源标了「最后修改时间」
开发语言·数据库·python·数据分析·api·数据治理·开放数据
IT毕设梦工厂12 小时前
计算机毕业设计选题推荐:基于大数据的草鱼价格分析与可视化|毕业设计选题|计算机毕设|选题推荐|毕设指导|项目定制|源码|高质量项目
大数据·hadoop·python·数据挖掘·数据分析·课程设计·大数据毕设项目