Numpy 的 argmax() 在 Swift

Numpy's argmax() in Swift

我正在从事一个将用户面部转换为表情符号的项目。为此,我使用了 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 函数那样的选项?另外我需要指定参数范围,因为嘴巴的参数不应该与眉毛的参数进行比较。

你可以这样使用:

func maxBlendShape(for blendShapes: [ARFaceAnchor.BlendShapeLocation], in shape: [ARFaceAnchor.BlendShapeLocation: NSNumber]) -> Double? {
    blendShapes
        .compactMap { shape[[=10=]] }
        .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[[=12=]]})
            .map(\.doubleValue)
            .max()
    }
}

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