如何将 Vision 输出显示到 UI 中?

Posted

技术标签:

【中文标题】如何将 Vision 输出显示到 UI 中?【英文标题】:How to make a Vision output display into a UI? 【发布时间】:2021-05-12 13:28:16 【问题描述】:

我对编码比较陌生,最近我一直在开发一个程序,该程序允许用户使用 iPhone 的后置摄像头扫描水晶,它会识别水晶的种类。我使用 CreateML 来构建模型,并使用 Vision 来识别晶体。我似乎无法弄清楚如何将结果放入我构建的 UI 中。结果正在打印到 Xcode 控制台。

这是故事板的图片:

【问题讨论】:

如果您可以编辑帖子并提供更具体的详细信息,人们可能会更容易提供帮助。代码 sn-ps、屏幕截图等总是有助于提供上下文。 @stef 是的,我也这么认为。我将用更多信息编辑帖子。谢谢。 【参考方案1】:

我假设您想在检测到的水晶周围画一个框?

你的水晶应该是boundingBox,看起来像这样:

(0.166666666666667, 0.35, 0.66666666666667, 0.3)

这些是“标准化”坐标,这意味着它们与您发送到 Vision 的图像相关。我更详细地解释这个here...

What you are used to What Vision returns

您需要将这些“标准化”坐标转换为您可以使用的 UIKit 坐标。为此,我有这个转换功能:

func getConvertedRect(boundingBox: CGRect, inImage imageSize: CGSize, containedIn containerSize: CGSize) -> CGRect 
    
    let rectOfImage: CGRect
    
    let imageAspect = imageSize.width / imageSize.height
    let containerAspect = containerSize.width / containerSize.height
    
    if imageAspect > containerAspect  /// image extends left and right
        let newImageWidth = containerSize.height * imageAspect /// the width of the overflowing image
        let newX = -(newImageWidth - containerSize.width) / 2
        rectOfImage = CGRect(x: newX, y: 0, width: newImageWidth, height: containerSize.height)
        
     else  /// image extends top and bottom
        let newImageHeight = containerSize.width * (1 / imageAspect) /// the width of the overflowing image
        let newY = -(newImageHeight - containerSize.height) / 2
        rectOfImage = CGRect(x: 0, y: newY, width: containerSize.width, height: newImageHeight)
    
    
    let newOriginBoundingBox = CGRect(
    x: boundingBox.origin.x,
    y: 1 - boundingBox.origin.y - boundingBox.height,
    width: boundingBox.width,
    height: boundingBox.height
    )
    
    var convertedRect = VNImageRectForNormalizedRect(newOriginBoundingBox, Int(rectOfImage.width), Int(rectOfImage.height))
    
    /// add the margins
    convertedRect.origin.x += rectOfImage.origin.x
    convertedRect.origin.y += rectOfImage.origin.y
    
    return convertedRect

你可以这样使用它:

let convertedRect = self.getConvertedRect(
    boundingBox: observation.boundingBox,
    inImage: image.size, /// image is the image that you feed into Vision
    containedIn: self.previewView.bounds.size /// the size of your camera feed's preview view
)
self.drawBoundingBox(rect: convertedRect)

/// draw the rectangle
func drawBoundingBox(rect: CGRect) 
    let uiView = UIView(frame: rect)
    previewView.addSubview(uiView)
        
    uiView.backgroundColor = UIColor.orange.withAlphaComponent(0.2)
    uiView.layer.borderColor = UIColor.orange.cgColor
    uiView.layer.borderWidth = 3

结果(我正在做一个VNDetectRectanglesRequest):

如果您想在手机移动时“跟踪”检测到的物体,请在此处查看我的answer

【讨论】:

这绝对有帮助,但我在原帖中添加了更多细节,试图澄清模糊的原帖。我正在尝试在扫描水晶时弹出一个 UI 以显示该水晶的详细信息。 @bigdogg99juherd 明白了。 showCrystalInfo 不工作吗? @bigdogg99juherd 那么目前发生了什么?可以加个截图吗? 我知道了。刚刚添加。 @bigdogg99juherd 所以你在showCrystalInfo 之后在print(firstObservation.identifier, firstObservation.confidence) 之后打电话,对吧?您的执行 segue 代码似乎很好

以上是关于如何将 Vision 输出显示到 UI 中?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UI 中显示 spark java 应用程序的输出

如何通过 Dart/Flutter 中的“application/octet-stream”将 png 文件发送到 Microsoft Custom Vision?

如何将 firebase 错误消息从终端显示到 UI?

Swift3:如何将一个String类型值添加到已经粘贴了计算值的UI Label中?

如何仅输出整个段落[Google Cloud Vision API,document_text_detection]

如何将额外的参数传递给 Vision 框架?