前言
图片去重
由于数据采集的截图是每秒一次,一旦有事离开会采集太多相同的图片,光是玩了几盘就已经收集了4G的图片了,训练时长也逐渐增加,感觉有必要对重复的图片进行去重。
像素相似度比对
因为游戏的大多数画面是动态的,直接比对像素去重效果肯定不太好,想根据相似度判断后去重,无奈图片比对太耗性能,O(N^2)的复杂度完全跑不动4G的图片,因此改成了只和前一张比对:
def is_same_image(img1_path, img2_path, threshold=0.99):
with Image.open(img1_path) as img1, Image.open(img2_path) as img2:
if img1.size != img2.size:
return False
img1_array = np.array(img1)
img2_array = np.array(img2)
if img1_array.shape != img2_array.shape:
return False
diff = np.abs(img1_array.astype(np.float32) - img2_array.astype(np.float32))
similarity = 1 - (np.sum(diff) / (diff.size * 255))
return similarity >= threshold
哈希相似度比对
但是和前一张比对只能处理放着不动产生的重复画面,对于多次游玩截图的重复画面依然没有办法解决。查阅资料得知imagehash库的phash和dhash可以对图片生成hash后计算相似度距离,于是编写代码测试:
image_hashes = {}
for img_path in tqdm(image_files, desc="计算图片哈希值"):
with Image.open(img_path) as img:
# 使用 dhash 算法,它对图片细节更敏感
hash_value = imagehash.dhash(img)
image_hashes[img_path] = str(hash_value)
查看比对结果发现,游戏的UI部分在画面占比较小,不同图片反映的信息不同,但是phash和dhash算法均不能很好的捕捉到UI数据的变化,把大量不同数据的图片归为了相似图片。
哈希去重
没办法还是直接通过像素计算哈希去重吧:
hash_cache = {}
for img_path in tqdm(image_files, desc="计算图片哈希值"):
with Image.open(img_path) as img:
img_array = np.array(img)
hash_cache[img_path] = hashlib.sha256(img_array.tobytes()).hexdigest()
def is_same_image(img1_path, img2_path):
hash1 = hash_cache[img1_path]
hash2 = hash_cache[img2_path]
return hash1 == hash2
和预想的一样,相似的图片很少,但是这个脚本对于后续数字识别的去重很有帮助。
下一步
现在已经有了准确的状态识别模型,那么就可以在养成界面截取数据进行数字识别了。