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

Swift4中调用CGRect的scaled方法报错,求解决方案

解决Swift 4中CGRect无scaled成员的问题

这个错误很常见——在Swift 4对应的iOS版本(iOS 11/12)里,CGRect确实没有内置的scaled(to:)方法,这个方法是iOS 13及以后才加入的系统API,所以你在Swift 4里调用自然会报错。而且还要注意:Vision框架返回的boundingBox是归一化坐标系(原点在图像左下角,数值范围0-1),和UIKit的视图坐标系(原点在左上角)不匹配,就算有scaled方法,直接用也会导致人脸框位置不对。

下面给你两种可行的解决方法:

方法一:手动完成坐标转换(推荐)

直接通过仿射变换同时完成缩放和坐标系翻转,这是处理Vision人脸框坐标的标准方式:

func detectLandmarks(on image: CIImage) {
    try? faceLandmarksDetectionRequest.perform([faceLandmarks], on: image)
    if let landmarksResults = faceLandmarks.results as? [VNFaceObservation] {
        for observation in landmarksResults {
            DispatchQueue.main.async {
                let boundingBox = observation.boundingBox // 直接用当前检测结果的boundingBox,而非inputFaceObservations
                let imageSize = image.extent.size
                // 第一步:将归一化坐标缩放到视图尺寸
                let scale = CGAffineTransform(scaleX: self.view.bounds.width / imageSize.width, 
                                             y: self.view.bounds.height / imageSize.height)
                // 第二步:翻转Y轴,适配UIKit坐标系
                let flip = CGAffineTransform(scaleX: 1, y: -1)
                    .translatedBy(x: 0, y: -self.view.bounds.height)
                // 组合变换得到最终的人脸框
                let faceBoundingBox = boundingBox.applying(scale).applying(flip)
                
                // 这里就可以用faceBoundingBox做绘制等操作了
            }
        }
    }
}

注意:我调整了获取boundingBox的方式,你之前用inputFaceObservations?.first可能不是当前检测到的最新结果,直接用循环里的observation.boundingBox才是正确的。

方法二:自定义CGRect的scaled扩展

如果你确实想复用类似scaled(to:)的语法,可以自己给CGRect写一个扩展,但记得之后还要处理坐标系翻转:

extension CGRect {
    func scaled(to targetSize: CGSize) -> CGRect {
        return CGRect(
            x: origin.x * targetSize.width,
            y: origin.y * targetSize.height,
            width: size.width * targetSize.width,
            height: size.height * targetSize.height
        )
    }
}

使用时仍需添加翻转步骤:

let scaledBox = boundingBox.scaled(to: self.view.bounds.size)
let flipTransform = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -self.view.bounds.height)
let faceBoundingBox = scaledBox.applying(flipTransform)

内容的提问来源于stack exchange,提问作者Haochen Wang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:13:04