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

iOS中normalizedPath是什么?如何将其转换为图像坐标并绘制使用?

normalizedPath 定义

Vision 框架返回的 normalizedPath 是归一化坐标系下的路径对象,所有坐标点的 x、y 取值范围固定在 [0, 1] 区间,坐标系原点在输入图像的左下角,和 UIKit 默认的左上角原点坐标系上下翻转。这种设计的目的是屏蔽原始图像尺寸差异,让识别结果可以适配任意缩放后的同比例图像场景。

归一化路径转全彩图像实际坐标

你已经将两张图按相同比例缩放到了相同尺寸,转换逻辑非常直接,只需要对归一化路径做两次仿射变换即可:

  1. 缩放变换:将 [0,1] 区间的坐标放大到实际图像的像素尺寸,x 乘以图像宽度,y 乘以图像高度
  2. 翻转平移变换:将 Vision 的左下角原点坐标系转换为 UIKit/Core Graphics 用的左上角原点坐标系
    最终转换后调用路径的 boundingBox 属性就能拿到你要的白色区域对应的 CGRect。

Swift 代码示例:

// 入参:Vision返回的归一化路径、两张图统一缩放后的尺寸
func convertNormalizedPath(_ normalizedPath: CGPath, to targetSize: CGSize) -> (CGPath, CGRect) {
    var transform = CGAffineTransform(scaleX: targetSize.width, y: targetSize.height)
        .concatenating(CGAffineTransform(scaleX: 1, y: -1))
        .concatenating(CGAffineTransform(translationX: 0, y: targetSize.height))
    let actualPath = normalizedPath.copy(using: &transform)!
    let targetRect = actualPath.boundingBox
    return (actualPath, targetRect)
}

Objective-C 代码示例:

- (void)convertPath:(CGPathRef)normalizedPath toSize:(CGSize)targetSize completion:(void(^)(CGPathRef actualPath, CGRect targetRect))completion {
    CGAffineTransform transform = CGAffineTransformConcat(
        CGAffineTransformMakeScale(targetSize.width, targetSize.height),
        CGAffineTransformConcat(
            CGAffineTransformMakeScale(1, -1),
            CGAffineTransformMakeTranslation(0, targetSize.height)
        )
    );
    CGPathRef actualPath = CGPathCreateCopyByTransformingPath(normalizedPath, &transform);
    CGRect targetRect = CGPathGetBoundingBox(actualPath);
    if (completion) completion(actualPath, targetRect);
    CGPathRelease(actualPath);
}
iOS 中将路径绘制到图像上的实现

用 UIGraphicsImageRenderer 即可实现路径叠加绘制,代码示例:

func drawPath(_ path: CGPath, on image: UIImage, strokeColor: UIColor = .red, fillColor: UIColor = .clear) -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: image.size)
    return renderer.image { context in
        // 先绘制原始全彩图像
        image.draw(at: .zero)
        // 配置绘制样式
        strokeColor.setStroke()
        fillColor.setFill()
        context.cgContext.setLineWidth(2)
        // 绘制路径
        context.cgContext.addPath(path)
        context.cgContext.drawPath(using: .fillStroke)
    }
}

如果需要直接在 UIImageView 上叠加显示路径,也可以创建自定义 CAShapeLayer,把路径赋值给 path 属性后添加到 imageView 的 layer 上,性能更高适合动态更新的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 19:06:04