文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

此教程解释如何使用 OpenCV 和 iPhone 的摄像头来处理视频帧。

前提条件:

  • Xcode 4.3 或者更新的版本
  • iOS 编程基础 (Objective-C, Interface Builder)

在 iOS 项目中引入 OpenCV 库

OpenCV 库是以框架的形式存在,你可以直接拖放到 XCode 项目中。可从 <http://sourceforge.net/projects/opencvlibrary/files/opencv-ios/> 下载最新的二进制版本。或者参考此文来从源码中编译框架。编译完成后直接拖放到 Xcode 项目即可。

../../../../_images/xcode_hello_ios_framework_drag_and_drop.png
第 1 段(可获 2 积分)

此外,您必须找到用于项目中所有头文件的前缀头。 该文件通常位于“ProjectName / Supporting Files / ProjectName-Prefix.pch”。 在那里,您添加一个include语句来导入opencv库。 但是,在包含UIKit和Foundation之前,请确保已经包含了opencv,不然你会得到一些奇怪的编译错误:一些宏,如min和max被定义多次。 例如,前缀头可能如下所示:

//
// Prefix header for all source files of the 'VideoFilters' target in the 'VideoFilters' project
//

#import <Availability.h>

#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif

#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif

#ifdef __OBJC__
        #import <UIKit/UIKit.h>
        #import <Foundation/Foundation.h>
#endif
第 2 段(可获 2 积分)

视频帧处理的示例项目

用户界面

首先,我们创建一个简单的 iOS 项目,例如是一个单视图的项目。然后创建并添加一个 UIImageView 和 UIButton 来启动摄像头以及显示捕获的视频帧。StoryBoard 效果如下图所示:

../../../../_images/xcode_hello_ios_viewcontroller_layout.png

确保添加并连接 IBOutlets 和 IBActions 到相应的 ViewController:

@interface ViewController : UIViewController
{
        IBOutlet UIImageView* imageView;
        IBOutlet UIButton* button;
}

- (IBAction)actionStart:(id)sender;

@end

添加摄像头

紧接着添加摄像头控件到视图控制器中并在视图加载时进行初始化:

第 3 段(可获 2 积分)
#import <opencv2/highgui/cap_ios.h>
using namespace cv;


@interface ViewController : UIViewController
{
        ...
        CvVideoCamera* videoCamera;
}
...
@property (nonatomic, retain) CvVideoCamera* videoCamera;

@end
- (void)viewDidLoad
{
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.

        self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
        self.videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionFront;
        self.videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset352x288;
        self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
        self.videoCamera.defaultFPS = 30;
        self.videoCamera.grayscale = NO;
}
第 4 段(可获 2 积分)

在这种情况下,我们初始化相机并提供imageView作为渲染每个帧的目标。 CvVideoCamera是基于AVFoundation包装的,所以我们能提供一些AVFoundation相机选择属性。 例如,我们要使用前置摄像头,将视频大小设置为352x288和视频方向(摄像机通常以横向模式输出,这在设计人像应用程序时会产生转置数据)。

属性defaultFPS设置摄像机的FPS。 如果处理的比期望的FPS快,则帧被自动丢弃。

第 5 段(可获 2 积分)

属性grayscale=YES导致不同的颜色空间,即“YUV(YpCbCr 4:2:0)”,而grayscale=NO将输出32位BGRA。

此外,我们必须手动添加opencv框架的框架依赖关系。 最后,您的项目中至少应该有以下框架:

  • opencv2

  • Accelerate

  • AssetsLibrary

  • AVFoundation

  • CoreGraphics

  • CoreImage

  • CoreMedia

  • CoreVideo

  • QuartzCore

  • UIKit

  • Foundation

    ../../../../_images/xcode_hello_ios_frameworks_add_dependencies.png

处理帧

我们遵循委托模式,这在iOS中非常常见,以提供对每个摄像机帧的访问。 基本上,View控制器必须实现CvVideoCameraDelegate协议,并且必须设置为视频摄像机的委派:

第 6 段(可获 2 积分)
@interface ViewController : UIViewController<CvVideoCameraDelegate>

- (void)viewDidLoad
{
        ...
        self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
        self.videoCamera.delegate = self;
        ...
}

#pragma mark - Protocol CvVideoCameraDelegate

#ifdef __cplusplus
- (void)processImage:(Mat&)image;
{
        // Do some OpenCV stuff with the image
}
#endif

注意,我们在这里使用C ++(cv :: Mat)。 重要:您必须将视图控制器的扩展名.m重命名为.mm,以便编译器假设在Objective-C ++(Objective-C和C ++混合)下编译它。 然后,__cplusplus在编译器处理C ++代码的文件时定义。 因此,我们将代码放在定义__cplusplus的块中。

第 7 段(可获 2 积分)

基本的视频处理

在这里你可以开始处理视频帧,例如下面的代码可以对图像进行色彩变换:

- (void)processImage:(Mat&)image;
{
        // Do some OpenCV stuff with the image
        Mat image_copy;
        cvtColor(image, image_copy, CV_BGRA2BGR);

        // invert image
        bitwise_not(image_copy, image_copy);
        cvtColor(image_copy, image, CV_BGR2BGRA);
}

开始!

最后,我们需要通知摄像头开始和停止工作。下面的代码将在点击按钮时启动摄像头,假设你已经将代码关联到 UI 属性中:

第 8 段(可获 2 积分)
#pragma mark - UI Actions

- (IBAction)actionStart:(id)sender;
{
        [self.videoCamera start];
}

提示

尽你所能的避免昂贵的矩阵复制操作,特别是当你的目标是实时处理的时候。 当图像数据作为引用传递时,可能的话,就地处理数据。

当您使用灰度数据时,由于YUV色彩空间允许您直接访问亮度平面,因此设置 grayscale = YES。

Accelerate框架提供了一些CPU加速的DSP过滤器,这可以让您更得心应手。

第 9 段(可获 2 积分)

文章评论