Search code examples
iosswiftcomputer-visionapple-vision

VNDetectRectanglesRequest Only Detects One Rectangle In Image With Two Rectangles - Vision, Swift


I am using the following to detect rectangles in this image: https://richardzhaodesign.files.wordpress.com/2015/02/order-final.jpg?w=300&h=300

import UIKit
import Vision

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    guard let image = UIImage(named: "sample2") else { return }

    let imageView = UIImageView(image: image)
    imageView.contentMode = .scaleAspectFit
    let scaledHeight = view.frame.width / image.size.width * image.size.height
    imageView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: scaledHeight)
    imageView.backgroundColor = .blue

    view.addSubview(imageView)

    let request = VNDetectRectanglesRequest { (req, err) in

        if let err = err {
            print("Failed to detect faces:", err)
            return
        }

        req.results?.forEach({ (res) in
            print("one")
            DispatchQueue.main.async {
                guard let rectangleObservation = res as? VNRectangleObservation else { return }

                let x = self.view.frame.width * rectangleObservation.boundingBox.origin.x
                let height = scaledHeight * rectangleObservation.boundingBox.height
                let y = scaledHeight * (1 -  rectangleObservation.boundingBox.origin.y) - height
                let width = self.view.frame.width * rectangleObservation.boundingBox.width

                let redView = UIView()
                redView.layer.borderColor = UIColor.red.cgColor
                redView.layer.borderWidth = 5
                redView.frame = CGRect(x: x, y: y, width: width, height: height)
                self.view.addSubview(redView)

            }
        })
    }

    guard let cgImage = image.cgImage else { return }

    DispatchQueue.global(qos: .background).async {
        let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
        do {
            try handler.perform([request])
        } catch let reqErr {
            print("Failed to perform request:", reqErr)
        }
    }

}
}

My question is why does this not recognize two squares. I have seen other codes recognize multiple rectangles, but mine will always only recognize one. I am sure that it is not that the Vision framework is not capable of recognizing the other one with high accuracy, just that I am missing something in my code. Thanks you.


Solution

  • You must set the maximumObservations property of your VNDetectRectanglesRequest. The default value is 1, which is why you are only getting 1 result.

    For example:

        let request = VNDetectRectanglesRequest { (req, err) in
            // Your completion handler code
        }
    
        request.maximumObservations = 2