(一)PS识别: Python 图像分析PS识别之道
(二)PS识别: 特征识别-直方图分析的从原理到实现
(三)PS识别:基于噪声分析PS识别的技术实现
(四)PS识别:基于边缘纹理检测分析PS识别的技术实现
(五)PS识别:压缩痕迹挖掘-压缩量化表与 DCT 系数分析
介绍
本文介绍的 PSExifChecker
类便是利用 exifread
、piexif
、PIL
和 python - magic
等库,通过读取图片的 EXIF 元数据和文件信息,对图片进行多维度检测的实现。
原理
这段代码主要用于检测图片是否经过 Photoshop 处理或者是否为截图,核心原理是通过读取图片的 EXIF(Exchangeable Image File Format)元数据,根据元数据中的信息(如软件信息、拍摄设备信息等)以及图片的基本属性(如分辨率、文件类型等)来判断图片是否可疑。
实现思路
- 元数据读取:使用
exifread
和piexif
库读取图片的 EXIF 元数据。 - 截图检测:通过检查元数据的数量、图片分辨率以及软件标签等信息判断图片是否为截图。
- PS 处理检测:检查元数据中的软件信息是否包含
Photoshop
或PS
,判断图片是否经过 Photoshop 处理。 - 设备信息检测:检查元数据中的拍摄设备信息,若截图中出现异常拍摄设备信息,则认为图片可能被修改。
- 文件类型检查:使用
python - magic
库检查文件类型和扩展名是否一致。
代码逻辑
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
方法:- 以二进制模式打开图片文件,使用
exifread
库读取 EXIF 元数据。 - 若没有元数据,返回
False, "无元数据"
。 - 检查软件信息是否包含
Photoshop
或PS
,若包含则返回True, "检测到PS相关软件痕迹"
。 - 检查拍摄设备信息,若截图中出现异常拍摄设备信息,则返回
True, "截图中出现异常拍摄设备信息,可能被修改"
。 - 若以上条件都不满足,返回
False, "元数据正常"
。
- 以二进制模式打开图片文件,使用
is_ps_extract_exif_info
方法:- 使用
PIL
库打开图片,检查图片格式是否为JPEG
或TIFF
,若不是则返回相应错误信息。 - 使用
piexif
库加载 EXIF 元数据,并打印所有元数据信息。
- 使用
check_file_type
方法:- 定义常见截图文件格式。
- 使用
python - magic
库获取文件类型,获取文件扩展名。 - 若文件扩展名是常见截图格式,但文件类型不包含该扩展名,则返回
True, "截图文件扩展名与检测类型不一致,可能被处理过"
。 - 否则返回
False, "文件类型与扩展名正常"
。
优点
- 多维度检测:从元数据信息、图片分辨率、文件类型等多个维度进行检测,提高了检测的准确性。。
- 扩展性强:可以方便地添加新的检测规则,以适应不同的检测需求。
缺点
- 误判风险:仅根据元数据信息和简单规则进行判断,可能会出现误判。例如,软件信息可能被手动修改,导致检测结果不准确。
- 兼容性问题:只支持
JPEG
和TIFF
格式的图片,对于其他格式的图片无法进行检测。 - 性能问题:在处理大量图片时,多次读取文件和解析元数据可能会导致性能下降。