2014-10-07 17 views
13

Sto scrivendo un'app che esegue un'elaborazione video in tempo reale utilizzando uno AVCaptureSession con un AVCaptureVideoDataOutput come output e uno AVCaptureDeviceInput con il file video (non deve più essere in tempo reale) come input.come utilizzare AVCaptureSession per leggere un video da un file?

È possibile utilizzare il file video come in ingresso su AVCaptureSession anziché sulla fotocamera? Se non è possibile, qual è il metodo migliore per elaborare un file video utilizzando l'acquisizione video di opencv on iOS (simultaneamente o in sequenza)?

risposta

1

Poiché si ha accesso ai frame di file video non elaborati (dal proprio AVCaptureVideoDataOutput), è possibile convertire ciascun fotogramma in un oggetto cv::Mat (una matrice di opencv, che rappresenta un'immagine). Quindi esegui l'elaborazione delle immagini su ogni singolo fotogramma.

Verificare https://developer.apple.com/library/ios/qa/qa1702/_index.html per un esempio in tempo reale utilizzando la fotocamera; puoi convertire il tuo UIImage in un cv::Mat usando cvMatFromUIImage.

0

Quindi risulta che non è troppo difficile da fare. Lo schema di base è:

  1. Creare un cv::VideoCapture di leggere da un file
  2. Creare un CALayer per ricevere e visualizzare ogni fotogramma.
  3. Eseguire un metodo a una determinata velocità che legge ed elabora ogni fotogramma.
  4. Terminata l'elaborazione, convertire ogni cv::Mat in un CGImageRef e visualizzarlo sullo CALayer.

L'implementazione attuale è la seguente:

Passaggio 1: Creare cv :: VideoCapture

std::string filename = "/Path/To/Video/File"; 
capture = cv::VideoCapture(filename); 
if(!capture.isOpened()) NSLog(@"Could not open file.mov"); 

Fase 2: creare l'output CALayer

self.previewLayer = [CALayer layer]; 
self.previewLayer.frame = CGRectMake(0, 0, width, height); 
[self.view.layer addSublayer:self.previewLayer]; 

Passaggio 3: Creare Elaborazione di Loop w/GCD

int kFPS = 30; 

dispatch_queue_t queue = dispatch_queue_create("timer", 0); 
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); 
dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), (1/kFPS) * NSEC_PER_SEC, (0.5/kFPS) * NSEC_PER_SEC); 

dispatch_source_set_event_handler(self.timer, ^{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self processNextFrame]; 
    }); 
}); 

dispatch_resume(self.timer); 

Fase 4: Metodo di elaborazione

-(void)processNextFrame { 
    /* Read */ 
    cv::Mat frame; 
    capture.read(frame); 

    /* Process */ 
    ... 

    /* Convert and Output to CALayer*/ 
    cvtColor(frame, frame, CV_BGR2RGB); 
    NSData *data = [NSData dataWithBytes:frame.data 
           length:frame.elemSize()*frame.total()]; 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGBitmapInfo bitmapInfo = (frame.elemSize() == 3) ? kCGImageAlphaNone : kCGImageAlphaNoneSkipFirst; 
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef) data); 

    CGImageRef imageRef = CGImageCreate(frame.cols, 
             frame.rows, 
             8, 
             8 * frame.elemSize(), 
             frame.step[0], 
             colorSpace, 
             bitmapInfo, 
             provider, 
             NULL, 
             false, 
             kCGRenderingIntentDefault); 

    self.previewLayer.contents = (__bridge id)imageRef; 

    CGImageRelease(imageRef); 
    CGColorSpaceRelease(colorSpace); 
} 
Problemi correlati