You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现数组中单个元素与其余所有元素的对比(图片相似度计算场景)

核心解决思路

你现在的代码只完成了「第一张图和剩余所有图对比」的逻辑,要实现所有图两两对比,只需要在外层再加一层循环,逐个把每张图当作基准图和其余图对比即可,同时要注意2个初学者容易踩的坑:

  • 不要边遍历数组边删除元素,很容易出现索引越界崩溃
  • 提前把所有图片的特征值计算好存起来,不用每次对比都重复转PNG、重复计算特征,能大幅提升运行速度

完整实现代码

// 先定义个结构体存每张图的索引和对应的特征值,方便后续处理
struct ImageFeature {
    let index: Int
    let feature: FeatureprintObservation // 这里替换成你项目里featureprintObservation的实际类型
}

private func findAllSimilarImages() {
    // 1、先把所有图片的特征值一次性算完存好
    var allFeatures = [ImageFeature]()
    for (index, image) in imageArray.enumerated() {
        guard let pngData = image.pngData(),
              let feature = featureprintObservationForImage(data: pngData) else {
            continue // 某张图计算失败就跳过,不要直接return终止整个流程
        }
        allFeatures.append(ImageFeature(index: index, feature: feature))
    }
    
    // 用Set存重复图的索引,自动去重
    var duplicateIndexSet = Set<Int>()
    
    // 2、双层循环两两对比
    // 外层循环:每次取第i张图当基准图
    for i in allFeatures.indices {
        // 如果当前图已经被标记为重复了,就不用再当基准图对比了,跳过
        if duplicateIndexSet.contains(i) {
            continue
        }
        let baseFeature = allFeatures[i].feature
        
        // 内层循环:从i+1开始,只和基准图后面的图对比,避免重复计算
        for j in (i+1)..<allFeatures.count {
            if duplicateIndexSet.contains(j) {
                continue
            }
            let compareFeature = allFeatures[j].feature
            
            do {
                var distance: Float = 0
                try compareFeature.computeDistance(&distance, to: baseFeature)
                print("第\(i)张和第\(j)张的相似度距离:\(distance)")
                if distance <= 3.0 {
                    // 标记为重复
                    duplicateIndexSet.insert(j)
                }
            } catch {
                print("计算第\(i)和\(j)张图特征距离失败:\(error)")
            }
        }
    }
    
    // 3、统一处理结果
    // 所有重复图
    similarImages = duplicateIndexSet.compactMap { index in
        imageArray[index]
    }
    // 所有不重复的图
    let uniqueImages = imageArray.enumerated()
        .filter { !duplicateIndexSet.contains($0.offset) }
        .map { $0.element }
    
    print("找到重复图数量:\(similarImages.count)")
}

关键逻辑说明

  • 内层循环从i+1开始,是因为第0张和第1张对比过之后,第1张就不用再回头和第0张对比了,能减少一半的计算量
  • 用Set存重复索引,是为了避免同一张图被多次标记为重复
  • 提前计算所有特征值,避免同一张图被反复转PNG、反复算特征,性能提升非常明显

内容的提问来源于stack exchange,提问作者Artem Golubinskiy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 13:36:04