NoOneNoBody
2023-03-31 15:51:13 +08:00
小图很快的,不需要 3000s ,但 1m 又基本不行
不知道你的参照有多少,我 1000 vs 1000 ,5~10MB/pic ,也就 30 分钟内
如果参照已经缓存了计算值,时间减半,小图(<1MB/pic),时间减 2/3
方案 1. pyvips
def viMse(vim, refvim)->float:
'''计算 MSE 差异值,vim/refvim 都是 pyvips.Image 类型'''
return ((vim - refvim) ** 2).avg()
然后你按 mse 比较,网上有
opencv 也有 mse 计算,但比 pyvips 慢
方案 2 pyvips|opencv
有些图片字节数相同或极度接近,但 md5/crc32 不同,它们可能只是 exif 或者文件头不同,图片内容是完全相同的
可以用
np.isclose((vim1-vim2).max(), 0, rtol=1e-9)
或
cvim1.shape==cvim2.shape and not (numpy.bitwise_xor(cvim1, cvim2).any())
vim 为 pyvips.Image 格式,cvim 为 opencv/numpy 格式,vips 较快且耗内存小,但大图有可能有未知错误,全自动的话 opencv 在保证内存足够的情况下比较保险
方案 3 opencv.imgHash
target 和 refer 分别计算 imgHash ,opencv 的 imgHash 有七八种,阙值是自定的,但网上有参考,自己选择
无论哪种方案,应该做预匹配,不然就是 10000 * 10000 ,计算量大
预匹配就是从字节、文件名相似、exif 日期时间一致,长宽比……这些很少计算能快速排除“完全不可能相似”
如果很难做预匹配,例如上述参数都没有规律,那就只能硬着头皮按组合双循环计算了
还有其他方案,但此题好像不适用,我主要目标是找有没有裁切水印把图变小了,和你需求略有不同
PS: 如果 refer 经常使用的话,建议把上述计算的中间值保存,以后使用跳过计算,省时间,我是入库的