首页 > 解决方案 > Swift 中 Numpy 的 argmax()

问题描述

我正在开发一个将用户的脸转换为表情符号的项目。为此,我使用 Apple 的 ARKit。

我需要得到最可能的选择。我写了这段代码:

func renderer(for anchor: ARAnchor) {
    guard let faceAnchor = anchor as? ARFaceAnchor else {
        return
    }
    
    let shapes = faceAnchor.blendShapes

    let browDownLeft = shapes[.browDownLeft]!.doubleValue
    let browInnerUp = shapes[.browInnerUp]!.doubleValue
    let browOuterUpLeft = shapes[.browOuterUpLeft]!.doubleValue
    
    let leftBrowMax = max(browDownLeft, browInnerUp, browOuterUpLeft)
    
    switch leftBrowMax {
    case browDownLeft:
        userFace.leftBrow = .browDown
    case browInnerUp:
        userFace.leftBrow = .browInnerUp
    case browOuterUpLeft:
        userFace.leftBrow = .browOuterUp
    default:
        userFace.leftBrow = .any
    }
}

我需要复制函数的主体六次(眉毛,眼睛和嘴边),所以我想以更方便的方式编写它。Swift 中有没有像 numpy 的 argmax 函数这样的选项?我还需要指定参数范围,因为嘴的参数不应该与眉毛的参数进行比较。

标签: swiftarkit

解决方案


你可以使用这样的东西:

func maxBlendShape(for blendShapes: [ARFaceAnchor.BlendShapeLocation], in shape: [ARFaceAnchor.BlendShapeLocation: NSNumber]) -> Double? {
    blendShapes
        .compactMap { shape[$0] }
        .map(\.doubleValue)
        .max()
}

用法将是这样的:

maxBlendShape(for: [.browDownLeft, .browInnerUp, .browOuterUpLeft], in: faceAnchor.blendShapes)

注意:这里没有特定于ARKit,您只需从字典中过滤一些键并找到它们的最大值。通用解决方案可能如下所示:

extension Dictionary where Value == NSNumber {
    func maxDouble(for keys: [Key]) -> Double? {
        keys
            .compactMap({self[$0]})
            .map(\.doubleValue)
            .max()
    }
}

faceAnchor.blendShapes.maxDouble(for: [.browInnerUp, .browDownLeft, .browOuterUpLeft])

推荐阅读