近期,某院士在清华大学回复关于图片重复问题时,指出实验室数据管理很重要,要引起重视。
恰巧的是,近期一学者同时发表于 Nature 的两篇文章均被指出出现图片重复。
这进一步突显了在学术研究和出版过程中,数据管理的重要性,以及采取必要的措施来避免这种低级错误的发生。
因此这边就尝试搞了一套流程来检测使用图片是否有重复的问题。
这里不探究图片重复的原因(如相同组别、粗心大意、数据管理不善、造假、论文工厂等有可能),而是专注于解决“如何低成本检测预发表文献中可能存在的图片重复问题”。
以下代码的原理是通过计算 结构相似性指数(SSIM, Structural Similarity Index) 来评估两张图片的相似度,从而检测它们是否重复或相似。
SSIM 是一种衡量两张图片相似度的指标。与传统的像素差异(例如,均方误差 MSE)相比,SSIM 更加关注图像的结构、亮度、对比度等特征,因此它能够更有效地模拟人眼对图像的感知方式。
import cv2
import os
from skimage.metrics import structural_similarity as ssim
def calculate_similarity(image_path1, image_path2):
"""
使用 SSIM 计算两张图片的相似度。
参数:
image_path1 (str): 第一张图片的路径。
image_path2 (str): 第二张图片的路径。
返回:
float: 两张图片的 SSIM 相似度指数(范围 -1 到 1)。
"""
# 检查文件是否存在
if not os.path.exists(image_path1):
raise ValueError(f"未找到文件:{image_path1}")
if not os.path.exists(image_path2):
raise ValueError(f"未找到文件:{image_path2}")
# 读取图片
img1 = cv2.imread(image_path1, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(image_path2, cv2.IMREAD_GRAYSCALE)
# 检查图片是否加载成功
if img1 is None or img2 is None:
raise ValueError("其中一张或两张图片路径无效,或图片无法加载。")
# 如果图片尺寸不同,则调整大小
if img1.shape != img2.shape:
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))
# 计算 SSIM
score, _ = ssim(img1, img2, full=True)
return score
def get_images_from_folder(folder_path):
"""
获取指定文件夹中的所有图片文件路径。
参数:
folder_path (str): 文件夹的路径。
返回:
list: 图片文件路径的列表。
"""
valid_extensions = (".png", ".jpg", ".jpeg", ".bmp", ".tiff") # 支持的图片格式
return [
os.path.join(folder_path, file)
for file in os.listdir(folder_path)
if file.lower().endswith(valid_extensions)
]
if __name__ == "__main__":
# 输入文件夹路径
folder_path = input("请输入图片所在文件夹路径:").strip()
# 检查文件夹是否存在
if not os.path.exists(folder_path):
print(f"文件夹不存在:{folder_path}")
exit(1)
# 获取文件夹中的所有图片
image_paths = get_images_from_folder(folder_path)
# 检查是否有足够的图片
if len(image_paths) < 2:
print("文件夹中没有足够的图片进行比较(至少需要两张图片)。")
exit(1)
# 开始计算相似度
print(f"检测到 {len(image_paths)} 张图片,开始相似度检测...\n")
pair_index = 1
results = []
for i in range(len(image_paths)):
for j in range(i + 1, len(image_paths)): # 确保每张图片只与其后面的图片比较
try:
print(f"第 {pair_index} 对:")
print(f" 图片 1: {image_paths[i]}")
print(f" 图片 2: {image_paths[j]}")
# 计算相似度
similarity = calculate_similarity(image_paths[i], image_paths[j])
print(f" SSIM 相似度: {similarity:.4f}\n")
# 保存结果
results.append({
"pair": pair_index,
"image1": image_paths[i],
"image2": image_paths[j],
"similarity": similarity
})
pair_index += 1
except Exception as e:
print(f" 处理该对时出错:{e}\n")
continue
print("相似度检测完成。\n")
# 打印总结
print("结果汇总:")
for result in results:
print(f"第 {result['pair']} 对:")
print(f" 图片 1: {result['image1']}")
print(f" 图片 2: {result['image2']}")
print(f" SSIM 相似度: {result['similarity']:.4f}\n")
这是其中一篇文章里面的重复图片。其中在补充图片的图 3 左下角和图 7 右下角出现了图片重复(以下用代号 A 和 C 来表示,其中 B 作为非重复的对照,A_rep 作为 A 的复制)。
我们预期,
以下是结果:
请输入图片所在文件夹路径:E:\XXXX\2024_12_24_graph_sim
检测到 4 张图片,开始相似度检测...
第 1 对:
图片 1: E:\XXXX\2024_12_24_graph_sim\A.png
图片 2: E:\XXXX\2024_12_24_graph_sim\A_rep.png
SSIM 相似度: 1.0000
第 2 对:
图片 1: E:\XXXX\2024_12_24_graph_sim\A.png
图片 2: E:\XXXX\2024_12_24_graph_sim\B.png
SSIM 相似度: 0.1058
第 3 对:
图片 1: E:\XXXX\2024_12_24_graph_sim\A.png
图片 2: E:\XXXX\2024_12_24_graph_sim\C.png
SSIM 相似度: 0.5486
第 4 对:
图片 1: E:\XXXX\2024_12_24_graph_sim\A_rep.png
图片 2: E:\XXXX\2024_12_24_graph_sim\B.png
SSIM 相似度: 0.1058
第 5 对:
图片 1: E:\XXXX\2024_12_24_graph_sim\A_rep.png
图片 2: E:\XXXX\2024_12_24_graph_sim\C.png
SSIM 相似度: 0.5486
第 6 对:
图片 1: E:\XXXX\2024_12_24_graph_sim\B.png
图片 2: E:\XXXX\2024_12_24_graph_sim\C.png
SSIM 相似度: 0.1325
相似度检测完成。
从结果可以看出,如果图片是复制的,那么他们的相似度是 1。如果不是重复的图片,相似度较低,0.1 左右。由于部分是通过截图来进行检测,所以重复的图片相似度下降明显,但是还是显著高于非重复图片, 相似度 0.5。
所以如果你的图片相似度大于 0.3 以上,请注意检查是否有图片重复。