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

如何拆分VNCoreMLRequest的识别结果,实现多物体辐条数的分别统计

如何拆分VNCoreMLRequest的识别结果,实现多物体辐条数的分别统计

嗨,我看了你的问题和代码,问题出在你现在只是把所有检测到的辐条结果直接汇总统计,没有把辐条和它所属的齿轮物体绑定在一起,所以才会出现把所有辐条总数加起来的情况。咱们需要把每个辐条对应到它所在的齿轮框里,再按齿轮分组统计。

问题根源分析

你当前的代码中,coreResults是所有辐条的检测结果,gearDetectorResults是所有齿轮的检测结果,但两者之间没有建立关联。你之前的统计逻辑只是把所有在交叉线区域内的辐条计数求和,完全没考虑这些辐条属于哪个齿轮,自然就会把所有物体的辐条数加总在一起。

解决方案:建立辐条与齿轮的关联,按齿轮分组统计

我们需要先把每个齿轮的检测框转换成视图坐标系,然后遍历每个辐条结果,判断它属于哪个齿轮的范围,最后按齿轮分组统计数量。下面是修改后的核心统计代码,替换你原来的counts计算部分:

////// 替换原来的counts计算代码
// 1. 先处理齿轮检测结果:转成视图坐标系的框,给每个齿轮分配唯一ID和颜色
let gearBoxes = gearDetectorResults.enumerated().map { index, gearObservation in
    let gearRect = self.rect(for: gearObservation)
    // 可以按齿轮序号分配颜色,比如从你的colors字典里取,或者生成不同颜色
    let gearColor = colors["gear_\(index)"] ?? [.red, .blue, .green, .orange][index % 4]
    return (id: index, rect: gearRect, color: gearColor)
}

// 2. 把每个辐条匹配到对应的齿轮
let spokeToGearMatches = coreResults.compactMap { spokeObservation -> (gearId: Int, spoke: VNRecognizedObjectObservation)? in
    let spokeRect = self.rect(for: spokeObservation)
    // 判断辐条是否属于某个齿轮:这里用交集面积来判断,比单纯contains更灵活
    guard let matchedGear = gearBoxes.first(where: { gearBox in
        let intersectionRect = spokeRect.intersection(gearBox.rect)
        // 交集面积超过辐条面积的50%,就认为属于这个齿轮,可根据实际调整阈值
        return intersectionRect.area / spokeRect.area > 0.5
    }) else {
        return nil // 忽略不属于任何齿轮的辐条
    }
    return (gearId: matchedGear.id, spoke: spokeObservation)
}

// 3. 按齿轮分组统计辐条数量
let counts = gearBoxes.map { gearBox in
    // 统计当前齿轮下的辐条总数
    let totalSpokes = spokeToGearMatches.filter { $0.gearId == gearBox.id }.count
    // 生成对应的结果对象
    return CountingResult(
        key: "Object \(gearBox.id + 1)",
        count: totalSpokes,
        color: gearBox.color
    )
}
//////

代码逻辑说明

  1. 齿轮预处理:给每个检测到的齿轮分配一个序号(index),把它的bounding box转换成和辐条结果一致的视图坐标系,同时分配对应的颜色。
  2. 辐条-齿轮匹配:遍历每个辐条,计算它的框和每个齿轮框的交集面积,当交集占辐条面积的50%以上时,就认为这个辐条属于该齿轮(你可以根据实际情况调整这个阈值)。
  3. 分组统计:针对每个齿轮,统计匹配到它的辐条数量,最后生成每个物体单独的统计结果,也就是你想要的Object 1 : 20 spokes | Color1这种格式。

额外优化建议

  • 确保rect(for:)方法能正确把VN的坐标转换成视图坐标(VN的坐标原点在左下角,而UIKit的原点在左上角,这个转换是关键)。
  • 如果存在齿轮重叠的情况,可以考虑用更精确的匹配逻辑,比如判断辐条框的中心点是否在齿轮框内,避免重叠时的误匹配。
  • 可以去掉原来的crosshairSize相关判断,因为现在我们是基于齿轮的范围来统计辐条,不需要再依赖交叉线区域了。

这样修改后,你就能得到每个物体单独的辐条数量统计结果啦!

备注:内容来源于stack exchange,提问作者Jobins John

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 12:14:29