将视觉边界框从 VNFaceObservation 转换为矩形以在图像上绘制

问题描述 投票:0回答:5

我正在尝试使用新的

VNDetectFaceRectanglesRequest
API 中的
Vision
来检测图像上的人脸。然后,我在每个检测到的脸上绘制一个红色矩形。

但是我在将

boundingBox
VNFaceObservation
转换为
CGRect
时遇到问题。看来我唯一的问题是y起源


这是我的代码:

let request=VNDetectFaceRectanglesRequest{request, error in
    var final_image=UIImage(ciImage: image)
    if let results=request.results as? [VNFaceObservation]{
        for face_obs in results{
          UIGraphicsBeginImageContextWithOptions(final_image.size, false, 1.0)
          final_image.draw(in: CGRect(x: 0, y: 0, width: final_image.size.width, height: final_image.size.height))

          var rect=face_obs.boundingBox
/*/*/*/ RESULT 2 is when I uncomment this line to "flip" the y  /*/*/*/
          //rect.origin.y=1-rect.origin.y
          let conv_rect=CGRect(x: rect.origin.x*final_image.size.width, y: rect.origin.y*final_image.size.height, width: rect.width*final_image.size.width, height: rect.height*final_image.size.height)

          let c=UIGraphicsGetCurrentContext()!
          c.setStrokeColor(UIColor.red.cgColor)
          c.setLineWidth(0.01*final_image.size.width)
          c.stroke(conv_rect)

          let result=UIGraphicsGetImageFromCurrentImageContext()
          UIGraphicsEndImageContext()

          final_image=result!
        }
    }
    DispatchQueue.main.async{
        self.image_view.image=final_image
    }
}


let handler=VNImageRequestHandler(ciImage: image)
DispatchQueue.global(qos: .userInteractive).async{
    do{
        try handler.perform([request])
    }catch{
        print(error)
    }
}

这是迄今为止的结果。

结果 1(不翻转 y) Result 1

结果 2(翻转 y) Result 2



解决方案

我自己找到了解决方案。

let rect=face_obs.boundingBox
let x=rect.origin.x*final_image.size.width
let w=rect.width*final_image.size.width
let h=rect.height*final_image.size.height
let y=final_image.size.height*(1-rect.origin.y)-h
let conv_rect=CGRect(x: x, y: y, width: w, height: h)

但是,我将@wei-jay 的答案标记为好答案,因为它更优雅。

ios swift computer-vision face-detection vision-api
5个回答
34
投票

有一些内置方法可以为您做到这一点。 要从标准化形式转换,请使用以下命令:

func VNImageRectForNormalizedRect(_ normalizedRect: CGRect, _ imageWidth: Int, _ imageHeight: Int) -> CGRect

反之亦然:

func VNNormalizedRectForImageRect(_ imageRect: CGRect, _ imageWidth: Int, _ imageHeight: Int) -> CGRect

点的类似方法:

func VNNormalizedFaceBoundingBoxPointForLandmarkPoint(_ faceLandmarkPoint: vector_float2, _ faceBoundingBox: CGRect, _ imageWidth: Int, _ imageHeight: Int) -> CGPoint
func VNImagePointForNormalizedPoint(_ normalizedPoint: CGPoint, _ imageWidth: Int, _ imageHeight: Int) -> CGPoint

12
投票

您必须根据图像进行过渡和缩放。 示例

func drawVisionRequestResults(_ results: [VNFaceObservation]) {
    print("face count = \(results.count) ")
    previewView.removeMask()

    let transform = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -self.view.frame.height)

    let translate = CGAffineTransform.identity.scaledBy(x: self.view.frame.width, y: self.view.frame.height)

    for face in results {
        // The coordinates are normalized to the dimensions of the processed image, with the origin at the image's lower-left corner.
        let facebounds = face.boundingBox.applying(translate).applying(transform)
        previewView.drawLayer(in: facebounds)
    }
}

5
投票

我尝试了多种方法,以下是最适合我的方法:

dispatch_async(dispatch_get_main_queue(), ^{
    VNDetectedObjectObservation * newObservation = request.results.firstObject;
    if (newObservation) {
        self.lastObservation = newObservation;
        CGRect transformedRect = newObservation.boundingBox;
        CGRect convertedRect = [self.previewLayer rectForMetadataOutputRectOfInterest:transformedRect];
        self.highlightView.frame = convertedRect;
    }
});

4
投票
var rect = CGRect()
rect.size.height = viewSize.height * boundingBox.width
rect.size.width = viewSize.width * boundingBox.height
rect.origin.x = boundingBox.origin.y * viewSize.width
rect.origin.y = boundingBox.origin.x * viewSize.height

0
投票

@bitemybyte 的答案是正确的。我只是想补充一点,如果您有方向问题(尤其是在 macOS 上),请确保在设置

orientation
时配置正确的
VNImageRequestHandler
,例如:

VNImageRequestHandler(cvPixelBuffer: image, orientation: .up, options: [:])

© www.soinside.com 2019 - 2024. All rights reserved.