2014-10-07 33 views
13

Tôi đang viết một ứng dụng thực hiện xử lý video thời gian thực bằng cách sử dụng AVCaptureSession với đầu ra AVCaptureVideoDataOutput làm đầu ra và AVCaptureDeviceInput với tệp video (nó không còn cần phải ở thời gian thực) làm đầu vào.cách sử dụng AVCaptureSession để đọc video từ một tệp?

Có thể sử dụng tệp video như trong đầu vào cho AVCaptureSession thay vì máy ảnh không? Nếu không thể, phương pháp nào tốt nhất để xử lý tệp video bằng cách quay video opencv on iOS (đồng thời hoặc tuần tự)?

Trả lời

1

Vì bạn có quyền truy cập vào khung tệp video thô (từ AVCaptureVideoDataOutput), bạn có thể chuyển đổi từng khung thành đối tượng cv::Mat (ma trận opencv, đại diện cho hình ảnh). Sau đó, xử lý hình ảnh của bạn trên từng khung hình riêng lẻ.

Khám phá https://developer.apple.com/library/ios/qa/qa1702/_index.html để biết ví dụ thời gian thực bằng máy ảnh; bạn có thể chuyển đổi UIImage thành cv::Mat bằng cách sử dụng cvMatFromUIImage.

0

Vì vậy, hóa ra nó không phải là quá khó làm. Khái quát cơ bản là:

  1. Tạo một cv::VideoCapture để đọc từ một tập tin
  2. Tạo một CALayer tiếp nhận và hiển thị mỗi khung.
  3. Chạy phương thức ở một tốc độ nhất định đọc và xử lý từng khung.
  4. Sau khi xử lý xong, chuyển đổi mỗi cv::Mat thành CGImageRef và hiển thị nó trên CALayer.

Việc thực hiện thực tế là như sau:

Bước 1: Tạo cv :: VideoCapture

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

Bước 2: Tạo ra CALayer

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

Bước 3: Tạo Chế biến Vòng 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); 

Bước 4: Phương pháp chế biến

-(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); 
} 
Các vấn đề liên quan