2016-06-10 7 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을 사용했다. 이것은 매우 느립니다. 분이 지나면 경로가 표시됩니다.

Can not 누군가가 저에게 왜 느린지를 알아 내거나 제가 여기서 잘못하고있는 것임을 알려주십시오. 어떤 도움을 주시면 감사하겠습니다.

또는 이보다 쉬운 방법이 있다면 나도 알고 싶습니다.

+0

지금까지 시도한 내용에 대한 정보가 있습니까? – nayana

+0

죄송합니다. 정확히 알 필요는 없어요. 라이브 비디오 피드에서 직사각형을 감지했는데 정확한 포인트를 얻고 있습니다. 이제 4 포인트를 사용하여 라이브 비디오 피드에 직사각형을 그려야합니다. UIBezierPath와 CAShapeLayer를 사용하여 사각형을 그립니다. 그러나 그것은 매우 느립니다. – GMHSJ

+0

TL ... DR .. 좋아 .. 내가 그 did not는 당신이 편집 할 때까지 그것의 천천히 알고있다. .. – nayana

답변

0

GLKView에 하위 레이어를 추가하는 작업에 익숙해지면 느려질 것입니다. 여기서 GLKView는 매 초마다 여러 번 새로 고침을합니다 (captureOutput : didOutputSampleBuffer : .. method에 있음). 매번 하위 레이어를 만들고 추가하는 프로세스는 계속 유지할 수 없습니다.

더 좋은 방법은 CoreImage를 사용하여 경로를 그리고 resultImage를 통해 경로를 합성하는 것입니다.