2016-06-10 35 views
3

我正在開發一個應用程序來檢測實時攝像頭中的矩形並突出顯示檢測到的矩形。我使用AVFoundation做了相機的事情,並使用下面的方法來檢測和突出顯示檢測到的矩形。如何使用CAShapeLayer和UIBezeirPath在實時攝像頭上繪製檢測到的矩形路徑

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); 
      }  
     }      
    } 
} 

我用CAShapeLayerUIBezierPath以繪製矩形。這非常慢。路徑在數分鐘後可見。

有人可以幫我弄清楚爲什麼它很慢或讓我知道如果我在這裏做錯了什麼。任何幫助將不勝感激。

或者如果有一些方法比這更容易,我也想知道它。

+0

您對目前爲止所嘗試的任何信息? – nayana

+0

對不起,我沒有得到你需要知道的,確切地說。我已經在實時視頻源中檢測到了矩形,並且我得到了正確的答案。現在我需要使用這4點在我的實時視頻輸入中繪製一個矩形。我用UIBezierPath和CAShapeLayer繪製矩形。但速度很慢。 – GMHSJ

+0

TL; DR ..好的..那就是我不知道它的慢,直到你編輯.. – nayana

回答

0

如果你開始將一個子圖層添加到GLKView中,它會很慢。 GLKView每秒刷新多次(如captureOutput:didOutputSampleBuffer:..方法),每次創建和添加子圖層的過程都無法跟上。

更好的方法是使用CoreImage繪製路徑並將其合成到resultImage上。