我正在编写一个使用AVCaptureSession
进行实时视频处理的应用,输出为AVCaptureVideoDataOutput
,视频文件为AVCaptureDeviceInput
(不再需要实时)作为输入。
是否可以将视频文件用作AVCaptureSession
的输入而不是相机?
如果不可能,使用opencv on iOS
的视频捕获(同时或顺序)处理视频文件的最佳方法是什么?
答案 0 :(得分:1)
由于您可以访问原始视频文件帧(来自AVCaptureVideoDataOutput
),因此您可以将每个帧转换为cv::Mat
对象(表示图像的opencv矩阵)。然后在每个帧上进行图像处理。
结帐https://developer.apple.com/library/ios/qa/qa1702/_index.html
用于使用相机的实时示例;您可以使用cv::Mat
将您的UIImage转换为cvMatFromUIImage
。
答案 1 :(得分:0)
事实证明,它太太难了。基本概要是:
cv::VideoCapture
以从文件中读取CALayer
以接收并显示每个框架。cv::Mat
转换为CGImageRef
并将其显示在CALayer
上。实际实施如下:
第1步:创建cv :: VideoCapture
std::string filename = "/Path/To/Video/File";
capture = cv::VideoCapture(filename);
if(!capture.isOpened()) NSLog(@"Could not open file.mov");
第2步:创建输出CALayer
self.previewLayer = [CALayer layer];
self.previewLayer.frame = CGRectMake(0, 0, width, height);
[self.view.layer addSublayer:self.previewLayer];
第3步:使用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);
第4步:处理方法
-(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);
}
答案 2 :(得分:0)
我实现了pasawaya解决方案... PreviewLayer没有刷新...我发现问题出在哪里:
在第4步中,替换:
self.previewLayer.contents = (__bridge id)imageRef;
使用:
[self performSelectorOnMainThread:@selector(displayFrame:) withObject:(__bridge id)imageRef waitUntilDone:YES];
并添加:
- (void)displayFrame:(CGImageRef)frame {
_previewLayer.contents = (__bridge id)frame;
[CATransaction flush];
}
希望获得帮助!