Cómo dibujar la ruta de rectángulo detectada en la alimentación de camera en vivo utilizando CAShapeLayer y UIBezeirPath

Estoy desarrollando una aplicación para detectar rectangularjs en una alimentación de camera en vivo y resaltar el rectángulo detectado. Hice lo de la camera usando AVFoundation y usé los methods siguientes para detectar y resaltar el rectángulo detectado.

 var detector: CIDetector?; override func viewDidLoad() { super.viewDidLoad(); detector = self.prepareRectangleDetector(); } func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) { // re check this method // Need to shimmy this through type-hell let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) // Force the type change - pass through opaque buffer let opaqueBuffer = Unmanaged<CVImageBuffer>.passUnretained(imageBuffer!).toOpaque() let pixelBuffer = Unmanaged<CVPixelBuffer>.fromOpaque(opaqueBuffer).takeUnretainedValue() let sourceImage = CIImage(CVPixelBuffer: pixelBuffer, options: nil) // Do some detection on the image self.performRectangleDetection(sourceImage); var outputImage = sourceImage // Do some clipping var drawFrame = outputImage.extent let imageAR = drawFrame.width / drawFrame.height let viewAR = videoDisplayViewBounds.width / videoDisplayViewBounds.height if imageAR > viewAR { drawFrame.origin.x += (drawFrame.width - drawFrame.height * viewAR) / 2.0 drawFrame.size.width = drawFrame.height / viewAR } else { drawFrame.origin.y += (drawFrame.height - drawFrame.width / viewAR) / 2.0 drawFrame.size.height = drawFrame.width / viewAR } //videoDisplayView is a GLKView which is used to display camera feed videoDisplayView.bindDrawable() if videoDisplayView.context != EAGLContext.currentContext() { EAGLContext.setCurrentContext(videoDisplayView.context) } // clear eagl view to grey glClearColor(0.5, 0.5, 0.5, 1.0); glClear(0x00004000) // set the blend mode to "source over" so that CI will use that glEnable(0x0BE2); glBlendFunc(1, 0x0303); renderContext.drawImage(outputImage, inRect: videoDisplayViewBounds, fromRect: drawFrame); videoDisplayView.display(); } func prepareRectangleDetector() -> CIDetector { let options: [String: AnyObject] = [CIDetectorAccuracy: CIDetectorAccuracyHigh]; return CIDetector(ofType: CIDetectorTypeRectangle, context: nil, options: options); } func performRectangleDetection(image: CIImage){ let resultImage: CIImage? = nil; if let detector = detector { // Get the detections let features = detector.featuresInImage(image, options: [CIDetectorAspectRatio:NSNumber(float:1.43)]); if features.count != 0{ // feature found for feature in features as! [CIRectangleFeature] { self.previewImageView.layer.sublayers = nil; let line: CAShapeLayer = CAShapeLayer(); line.frame = self.videoDisplayView.bounds; let linePath: UIBezierPath = UIBezierPath(); linePath.moveToPoint(feature.topLeft); linePath.addLineToPoint(feature.topRight); linePath.addLineToPoint(feature.bottomRight); linePath.addLineToPoint(feature.bottomLeft); linePath.addLineToPoint(feature.topLeft); linePath.closePath(); line.lineWidth = 5.0; line.path = linePath.CGPath; line.fillColor = UIColor.clearColor().CGColor; line.strokeColor = UIColor(netHex: 0x3399CC, alpha: 1.0).CGColor; // videoDisplayParentView is the parent of videoDisplayView and they both have same bounds self.videoDisplayParentView.layer.addSublayer(line); } } } } 

Utilicé CAShapeLayer y UIBezierPath para dibujar el rectángulo. Esto es muy, muy lento. El path se hace visible después de unos minutos.

¿Alguien puede ayudarme a entender por qué es lento o avisarme si estoy haciendo algo mal aquí. Cualquier ayuda sería muy apreciada.

O si hay alguna manera más fácil que esto, me gustaría saberlo también.

Si te metes en el negocio de agregar una subcapa a un GLKView, será lento. El GLKView aquí se actualiza varias veces por segundo (como en el método captureOutput: didOutputSampleBuffer: ..), el process de creación y adición de la subcapa cada vez no podrá mantenerse al día.

Una mejor manera es dibujar la ruta usando CoreImage y comstackndola sobre resultImage.