上一教程: OpenCV iOS - 图像处理
| |
原作者 | Eduard Feicho |
兼容性 | OpenCV >= 3.0 |
本教程解释如何使用 iPhone 的摄像头和 OpenCV 处理视频帧。
前提条件
- Xcode 4.3 或更高版本
- 基本的 iOS 编程知识(Objective-C,Interface Builder)
在您的 iOS 项目中包含 OpenCV 库
OpenCV 库以框架的形式提供,您可以直接将其拖放到您的 Xcode 项目中。从 http://sourceforge.net/projects/opencvlibrary/files/opencv-ios/ 下载最新的二进制文件。或者按照本指南 在 iOS 中安装 手动编译框架。获得框架后,只需将其拖放到 Xcode 中即可。
您还需要找到项目中所有头文件使用的前缀头文件。该文件通常位于“ProjectName/Supporting Files/ProjectName-Prefix.pch”中。在那里,您需要添加一个 include 语句来导入 opencv 库。但是,请确保在包含 UIKit 和 Foundation 之前包含 opencv,否则您会遇到一些奇怪的编译错误,例如 min 和 max 等宏被多次定义。例如,前缀头文件可能如下所示:
//
// 'VideoFilters' 项目中 'VideoFilters' 目标的所有源文件的预编译头文件
//
#import <Availability.h>
#ifndef __IPHONE_4_0
#warning "此项目使用仅在 iOS SDK 4.0 及更高版本中可用的功能。"
#endif
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
示例视频帧处理项目
用户界面
首先,我们创建一个简单的 iOS 项目,例如 Single View Application。然后,我们创建并添加一个 UIImageView 和 UIButton 来启动摄像头并显示视频帧。故事板可能如下所示:
确保添加并连接 IBOutlets 和 IBActions 到相应的 ViewController
@interface ViewController : UIViewController
{
IBOutlet UIImageView* imageView;
IBOutlet UIButton* button;
}
- (IBAction)actionStart:(id)sender;
@end
添加摄像头
我们向视图控制器添加一个摄像头控制器,并在视图加载时对其进行初始化
#import <opencv2/videoio/cap_ios.h>
using namespace cv;
@interface ViewController : UIViewController
{
...
CvVideoCamera* videoCamera;
}
...
@property (nonatomic, retain) CvVideoCamera* videoCamera;
@end
- (void)viewDidLoad
{
[super viewDidLoad];
// 执行任何其他设置,加载视图后通常来自 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;
}
在这种情况下,我们初始化摄像头并将 imageView 作为渲染每一帧的目标。CvVideoCamera 基本上是 AVFoundation 的包装器,因此我们将其一些 AVFoundation 摄像头选项作为属性提供。例如,我们想使用前置摄像头,将视频大小设置为 352x288,以及视频方向(视频摄像头通常以横向模式输出,当您设计纵向应用程序时,会导致数据转置)。
属性 defaultFPS 设置摄像头的 FPS。如果处理速度低于所需的 FPS,则会自动丢弃帧。
属性 grayscale=YES 会导致不同的色彩空间,即“YUV (YpCbCr 4:2:0)”,而 grayscale=NO 将输出 32 位 BGRA。
此外,我们必须手动添加 opencv 框架的框架依赖项。最后,您的项目中至少应该包含以下框架:
- opencv2
- Accelerate
- AssetsLibrary
- AVFoundation
- CoreGraphics
- CoreImage
- CoreMedia
- CoreVideo
- QuartzCore
- UIKit
- Foundation
处理帧
我们遵循委托模式(这在 iOS 中非常常见)来访问每个摄像头帧。基本上,视图控制器必须实现 CvVideoCameraDelegate 协议,并且必须设置为视频摄像头的委托
@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;
{
// 使用图像执行一些 OpenCV 操作
}
#endif
请注意,我们在这里使用 C++(cv::Mat)。重要提示:您必须将视图控制器的扩展名 .m 重命名为 .mm,以便编译器在 Objective-C++(Objective-C 和 C++ 混合)的假设下编译它。然后,当编译器处理 C++ 代码的文件时,将定义 __cplusplus。因此,我们将代码放在 __cplusplus 定义的块中。
基础视频处理
从这里您可以开始处理视频帧。例如,以下代码片段可以反转图像颜色
- (void)processImage:(Mat&)image;
{
// 使用图像执行一些 OpenCV 操作
Mat image_copy;
cvtColor(image, image_copy, COLOR_BGR2GRAY);
// 反转图像
bitwise_not(image_copy, image_copy);
// 将 BGR 转换为 BGRA(三通道到四通道)
Mat bgr;
cvtColor(image_copy, bgr, COLOR_GRAY2BGR);
cvtColor(bgr, image, COLOR_BGR2BGRA);
}
开始!
最后,我们必须告诉摄像头实际开始/停止工作。以下代码将在您按下按钮时启动摄像头,假设您已正确连接 UI
#pragma mark - UI Actions
- (IBAction)actionStart:(id)sender;
{
[self.videoCamera start];
}
提示
尽可能避免代价高昂的矩阵复制操作,尤其是在追求实时处理的情况下。由于图像数据作为引用传递,因此如果可能,请就地操作。
当您处理灰度数据时,请将 grayscale 设置为 YES,因为 YUV 色彩空间可以直接访问亮度平面。
Accelerate 框架提供了一些 CPU 加速的 DSP 滤波器,这在您的情况下非常有用。