上一教程: 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 濾波器,在這種情況下會很方便。