iOS中normalizedPath是什么?如何将其转换为图像坐标并绘制使用?
normalizedPath 定义
Vision 框架返回的 normalizedPath 是归一化坐标系下的路径对象,所有坐标点的 x、y 取值范围固定在 [0, 1] 区间,坐标系原点在输入图像的左下角,和 UIKit 默认的左上角原点坐标系上下翻转。这种设计的目的是屏蔽原始图像尺寸差异,让识别结果可以适配任意缩放后的同比例图像场景。
归一化路径转全彩图像实际坐标
你已经将两张图按相同比例缩放到了相同尺寸,转换逻辑非常直接,只需要对归一化路径做两次仿射变换即可:
- 缩放变换:将 [0,1] 区间的坐标放大到实际图像的像素尺寸,x 乘以图像宽度,y 乘以图像高度
- 翻转平移变换:将 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
相关产品推荐
相关产品推荐

