上一教程: 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 中非常常见,以提供对每个摄像头帧的访问。 基本上,View Controller 必须实现 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 滤波器,在这种情况下会很方便。