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

如何提取VNClassificationObservation对象颜色及静态图像中对应坐标位置

关于VNClassificationObservation的坐标与颜色值提取说明

首先明确:VNClassificationObservation 是全局图像分类请求的输出类,默认仅包含分类置信度、类别标识符两个核心属性,本身不携带目标区域坐标和图像颜色信息,你当前的代码只能实现打印Top2分类的置信度与类别,无法拿到你需要的坐标和颜色值,具体实现方法如下:


1. 如何获取分类对象对应的图像坐标

如果需要同时拿到类别和对应物体的边界框,你需要替换全局图像分类请求为目标检测类请求,使用VNRecognizedObjectObservation类,它自带boundingBox属性,返回的是归一化坐标(原点在图像左下角,值范围0~1),可以按以下方式转换为图像实际像素坐标:

// 示例:用目标检测请求同时获取类别和坐标
let request = VNRecognizeObjectsRequest { request, error in
    guard let results = request.results as? [VNRecognizedObjectObservation] else { return }
    let topResults = results.prefix(2)
    topResults.forEach { obj in
        // 拿到分类信息
        guard let topClass = obj.labels.first else { return }
        print(String(format: "  (%.2f) %@", topClass.confidence, topClass.identifier))
        
        // 归一化坐标转实际图像坐标(imageSize为原始图像的实际尺寸)
        let imageSize: CGSize = UIImage(named: "你的原始图像")!.size
        let boundingBox = obj.boundingBox
        // 转换坐标系(从左下原点适配为UIKit通用的左上原点)
        let actualRect = VNImageRectForNormalizedRect(boundingBox, Int(imageSize.width), Int(imageSize.height))
            .applying(CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -imageSize.height))
        print("对应区域坐标:\(actualRect)")
    }
}

如果你确实需要用全局分类请求,可以先把图像按自定义规则裁剪为多个子块,分别对每个子块做分类,同时提前记录每个子块对应的原始图像坐标,就可以把分类结果和坐标关联起来。


2. 如何提取对应区域的颜色值

拿到边界框的实际像素坐标后,你可以从原始图像中裁剪出对应区域,再提取颜色,以下是提取区域平均色的示例:

// 从UIImage中裁剪指定区域并提取平均色
extension UIImage {
    func averageColor(in rect: CGRect) -> UIColor? {
        guard let cgImage = self.cgImage,
              let croppedImg = cgImage.cropping(to: rect) else { return nil }
        let ciImage = CIImage(cgImage: croppedImg)
        let filter = CIFilter(name: "CIAreaAverage", parameters: [
            kCIInputImageKey: ciImage,
            kCIInputExtentKey: CIVector(cgRect: ciImage.extent)
        ])
        guard let outputImage = filter?.outputImage else { return nil }
        
        var bitmap = [UInt8](repeating: 0, count: 4)
        let context = CIContext(options: [.workingColorSpace: kCFNull!])
        context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil)
        
        return UIColor(red: CGFloat(bitmap[0])/255, green: CGFloat(bitmap[1])/255, blue: CGFloat(bitmap[2])/255, alpha: CGFloat(bitmap[3])/255)
    }
}

// 调用示例
if let areaColor = yourOriginalImage.averageColor(in: actualRect) {
    print("区域平均色:\(areaColor)")
}

如果需要提取区域内所有像素的颜色值,遍历裁剪后图像的像素位图即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 19:27:03