Почему в нормированных результатах обнаружения объектов присутствуют отрицательные координаты?(CoreML, Vision, Swift, Ios) - PullRequest
0 голосов
/ 02 мая 2019

Я скомпилировал пример.

https://developer.apple.com/documentation/vision/recognizing_objects_in_live_capture

Это не сработало корректно для меня на iPhone 7 Plus.Нарисованные прямоугольники не закрывают обнаруженные предметы.

Я создал собственное приложение для расследования.Обнаруженные объекты возвращаются как нормализованные границы.Однако границы могут быть отрицательными в направлении Y.Добавление коррекции 0,2 возвращает их в выравнивание.

Обнаружение, кажется, обрезает квадрат от центра портретной рамки, чтобы выполнить обнаружение.Я создал квадратное наложение, и когда объект выходит за пределы квадрата вверх или вниз, обнаружение прекращается.Верхняя и нижняя части квадрата равны 0 и 1,0 в нормализованной координате.

Тестовое приложение передает данные из captureOutput в VNImageRequestHandler.Код, который устанавливает запрос также ниже.Есть идеи, почему наблюдения иногда бывают отрицательными в направлении Y?Почему мне нужно добавить смещение, чтобы вернуть их обратно в единицу площади и выровнять их по изображению?

Я установил камеру в 4K в своем тестовом приложении.Еще не пробовал никаких других настроек.

    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return
        }

        //let exifOrientation = exifOrientationFromDeviceOrientation()
        let exifOrientation = CGImagePropertyOrientation.up
        let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: exifOrientation, options: [:])
        do {
            try imageRequestHandler.perform(self.requests)
        } catch {
            print(error)
        }
    }
@discardableResult
func setupVision() -> NSError? {
    // Setup Vision parts
    let error: NSError! = nil

    guard let modelURL = Bundle.main.url(forResource: "ResistorModel", withExtension: "mlmodelc") else {
        return NSError(domain: "VisionObjectRecognitionViewController", code: -1, userInfo: [NSLocalizedDescriptionKey: "Model file is missing"])
    }
    do {
        let visionModel = try VNCoreMLModel(for: MLModel(contentsOf: modelURL))
        let objectRecognition = VNCoreMLRequest(model: visionModel, completionHandler: { (request, error) in
            DispatchQueue.main.async(execute: {
                // perform all the UI updates on the main queue
                if let results = request.results {
                    self.drawVisionRequestResults(results)
                }
            })
        })
        self.requests = [objectRecognition]
    } catch let error as NSError {
        print("Model loading went wrong: \(error)")
    }

    return error
}


    func drawVisionRequestResults(_ results: [Any]) {
        var pipCreated = false
        CATransaction.begin()
        CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
        detectionOverlay.sublayers = nil // remove all the old recognized objects
        for observation in results where observation is VNRecognizedObjectObservation {
            guard let objectObservation = observation as? VNRecognizedObjectObservation else {
                continue
            }
            // Select only the label with the highest confidence.
            let topLabelObservation = objectObservation.labels[0]
            if topLabelObservation.identifier == "resistor" {
                if (objectObservation.boundingBox.minX < 0.5) && (objectObservation.boundingBox.maxX > 0.5) && (objectObservation.boundingBox.minY < 0.3) && (objectObservation.boundingBox.maxY > 0.3) {
                    //print(objectObservation.boundingBox.minX)
                    //print(objectObservation.boundingBox.minY)

                    let bb = CGRect(x: objectObservation.boundingBox.minX, y:0.8 -  objectObservation.boundingBox.maxY, width: objectObservation.boundingBox.width, height: objectObservation.boundingBox.height)
                    //let bb = CGRect(x: 0.5,y: 0.5,width: 0.5,height: 0.5)
                        //let objectBounds = VNImageRectForNormalizedRect(bb, 500, 500)
                    let objectBounds = VNImageRectForNormalizedRect(bb, Int(detectionOverlay.bounds.width), Int(detectionOverlay.bounds.width))

//                    print(objectBounds)
//                    print(objectBounds.minX)
//                    print(objectBounds.minY)
//                    print(objectBounds.width)
//                    print(objectBounds.height)

                    print(objectObservation.boundingBox)
//                    print(objectBounds.minX)
//                    print(objectBounds.minY)
//                    print(objectBounds.width)
//                    print(objectBounds.height)

                    let textLayer = self.createTextSubLayerInBounds(objectBounds,
                                                                    identifier: topLabelObservation.identifier,
                                                                    confidence: topLabelObservation.confidence)

                    let shapeLayer = self.createRoundedRectLayerWithBounds(objectBounds)

                    shapeLayer.addSublayer(textLayer)
                    detectionOverlay.addSublayer(shapeLayer)

                    if !pipCreated {
                        pipCreated = true
                        let pip = Pip(imageBuffer: self.imageBuffer!)
                        if self.pip {
                            pipView.image = pip?.uiImage
                        } else {
                            pipView.image = nil
                        }
                    }
                }
            }
        }
        CATransaction.commit()
        doingStuff = false
    }

1 Ответ

0 голосов
/ 03 мая 2019

Я не уверен, почему он так себя вел. Однако я хотел бы, чтобы оно использовало все изображение для обнаружения объекта и результаты, которые должны быть связаны, нормализовались к исходному портретному вводу. Обратите внимание, что модель была обучена таким образом.

Существует тема https://github.com/apple/turicreate/issues/1016, посвященная этой конкретной проблеме. Пример не работает и не работает при изменении модели.

Решение, ближе к концу поста, говорит, что нужно использовать ...

objectRecognition.imageCropAndScaleOption = .scaleFill

Это позволило обнаружению использовать все изображение и создать связанные прямоугольники, которые были нормализованы для всего изображения. Нет больше произвольного смещения. Может случиться так, что обучающая геометрия и геометрия обнаружения должны быть одинаковыми, чтобы правильно рассчитать ограниченную рамку. Однако я не уверен, почему.

...