上一教程: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 库。但是,请务必在 include opencv 之前 include UIKit 和 Foundation,否则您会遇到一些奇怪的编译错误,例如 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 项目,例如“单视图应用程序”。然后,我们创建一个 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 - 协议 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(图像,图像副本,COLOR_BGR2GRAY);
// 反转图像
bitwise_not(图像副本,图像副本);
//将 BGR 转换为 BGRA(三通道转换为四通道)
Mat bgr;
cvtColor(图像副本,bgr,COLOR_GRAY2BGR);
cvtColor(bgr,图像,COLOR_BGR2BGRA);
}
开始!
最后,我们必须实际告诉摄像头开始/停止工作。以下代码将在你按下按钮时启动摄像头,假设你正确地连接了 UI
#pragma mark - UI 操作
- (IBAction)actionStart:(id)sender;
{
[self.videoCamera 启动];
}
提示
尽可能避免昂贵的矩阵复制操作,尤其是当你的目标是实时时。由于图像数据是作为参考传递的,如果可能的话,就地工作。
当你处理灰度数据时,将设置灰度 = YES,因为 YUV 颜色空间能让你直接访问亮度平面。
Accelerate 框架提供了一些 CPU 加速的 DSP 滤波器,在你的案例中很方便。