Home | History | Annotate | Download | only in video_processing
      1 OpenCV iOS - Video Processing {#tutorial_video_processing}
      2 =============================
      3 
      4 This tutorial explains how to process video frames using the iPhone's camera and OpenCV.
      5 
      6 Prerequisites:
      7 --------------
      8 
      9 -   Xcode 4.3 or higher
     10 -   Basic knowledge of iOS programming (Objective-C, Interface Builder)
     11 
     12 Including OpenCV library in your iOS project
     13 --------------------------------------------
     14 
     15 The OpenCV library comes as a so-called framework, which you can directly drag-and-drop into your
     16 XCode project. Download the latest binary from
     17 <http://sourceforge.net/projects/opencvlibrary/files/opencv-ios/>. Alternatively follow this
     18 guide @ref tutorial_ios_install to compile the framework manually. Once you have the framework, just
     19 drag-and-drop into XCode:
     20 
     21 ![](images/xcode_hello_ios_framework_drag_and_drop.png)
     22 
     23 Also you have to locate the prefix header that is used for all header files in the project. The file
     24 is typically located at "ProjectName/Supporting Files/ProjectName-Prefix.pch". There, you have add
     25 an include statement to import the opencv library. However, make sure you include opencv before you
     26 include UIKit and Foundation, because else you will get some weird compile errors that some macros
     27 like min and max are defined multiple times. For example the prefix header could look like the
     28 following:
     29 @code{.objc}
     30 //
     31 // Prefix header for all source files of the 'VideoFilters' target in the 'VideoFilters' project
     32 //
     33 
     34 #import <Availability.h>
     35 
     36 #ifndef __IPHONE_4_0
     37 #warning "This project uses features only available in iOS SDK 4.0 and later."
     38 #endif
     39 
     40 #ifdef __cplusplus
     41 #import <opencv2/opencv.hpp>
     42 #endif
     43 
     44 #ifdef __OBJC__
     45     #import <UIKit/UIKit.h>
     46     #import <Foundation/Foundation.h>
     47 #endif
     48 @endcode
     49 ### Example video frame processing project
     50 
     51 #### User Interface
     52 
     53 First, we create a simple iOS project, for example Single View Application. Then, we create and add
     54 an UIImageView and UIButton to start the camera and display the video frames. The storyboard could
     55 look like that:
     56 
     57 ![](images/xcode_hello_ios_viewcontroller_layout.png)
     58 
     59 Make sure to add and connect the IBOutlets and IBActions to the corresponding ViewController:
     60 @code{.objc}
     61 @interface ViewController : UIViewController
     62 {
     63     IBOutlet UIImageView* imageView;
     64     IBOutlet UIButton* button;
     65 }
     66 
     67 - (IBAction)actionStart:(id)sender;
     68 
     69 @end
     70 @endcode
     71 #### Adding the Camera
     72 
     73 We add a camera controller to the view controller and initialize it when the view has loaded:
     74 @code{.objc}
     75 #import <opencv2/videoio/cap_ios.h>
     76 using namespace cv;
     77 
     78 
     79 @interface ViewController : UIViewController
     80 {
     81     ...
     82     CvVideoCamera* videoCamera;
     83 }
     84 ...
     85 @property (nonatomic, retain) CvVideoCamera* videoCamera;
     86 
     87 @end
     88 @endcode
     89 @code{.objc}
     90 - (void)viewDidLoad
     91 {
     92     [super viewDidLoad];
     93     // Do any additional setup after loading the view, typically from a nib.
     94 
     95     self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
     96     self.videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionFront;
     97     self.videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset352x288;
     98     self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
     99     self.videoCamera.defaultFPS = 30;
    100     self.videoCamera.grayscale = NO;
    101 }
    102 @endcode
    103 In this case, we initialize the camera and provide the imageView as a target for rendering each
    104 frame. CvVideoCamera is basically a wrapper around AVFoundation, so we provie as properties some of
    105 the AVFoundation camera options. For example we want to use the front camera, set the video size to
    106 352x288 and a video orientation (the video camera normally outputs in landscape mode, which results
    107 in transposed data when you design a portrait application).
    108 
    109 The property defaultFPS sets the FPS of the camera. If the processing is less fast than the desired
    110 FPS, frames are automatically dropped.
    111 
    112 The property grayscale=YES results in a different colorspace, namely "YUV (YpCbCr 4:2:0)", while
    113 grayscale=NO will output 32 bit BGRA.
    114 
    115 Additionally, we have to manually add framework dependencies of the opencv framework. Finally, you
    116 should have at least the following frameworks in your project:
    117 
    118 -   opencv2
    119 -   Accelerate
    120 -   AssetsLibrary
    121 -   AVFoundation
    122 -   CoreGraphics
    123 -   CoreImage
    124 -   CoreMedia
    125 -   CoreVideo
    126 -   QuartzCore
    127 -   UIKit
    128 -   Foundation
    129 
    130     ![](images/xcode_hello_ios_frameworks_add_dependencies.png)
    131 
    132 #### Processing frames
    133 
    134 We follow the delegation pattern, which is very common in iOS, to provide access to each camera
    135 frame. Basically, the View Controller has to implement the CvVideoCameraDelegate protocol and has to
    136 be set as delegate to the video camera:
    137 @code{.objc}
    138 @interface ViewController : UIViewController<CvVideoCameraDelegate>
    139 @endcode
    140 @code{.objc}
    141 - (void)viewDidLoad
    142 {
    143     ...
    144     self.videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
    145     self.videoCamera.delegate = self;
    146     ...
    147 }
    148 @endcode
    149 @code{.objc}
    150 #pragma mark - Protocol CvVideoCameraDelegate
    151 
    152 #ifdef __cplusplus
    153 - (void)processImage:(Mat&)image;
    154 {
    155     // Do some OpenCV stuff with the image
    156 }
    157 #endif
    158 @endcode
    159 Note that we are using C++ here (cv::Mat). Important: You have to rename the view controller's
    160 extension .m into .mm, so that the compiler compiles it under the assumption of Objective-C++
    161 (Objective-C and C++ mixed). Then, __cplusplus is defined when the compiler is processing the file
    162 for C++ code. Therefore, we put our code within a block where __cplusplus is defined.
    163 
    164 #### Basic video processing
    165 
    166 From here you can start processing video frames. For example the following snippet color-inverts the
    167 image:
    168 @code{.objc}
    169 - (void)processImage:(Mat&)image;
    170 {
    171     // Do some OpenCV stuff with the image
    172     Mat image_copy;
    173     cvtColor(image, image_copy, COLOR_BGR2GRAY);
    174 
    175     // invert image
    176     bitwise_not(image_copy, image_copy);
    177 
    178     //Convert BGR to BGRA (three channel to four channel)
    179     Mat bgr;
    180     cvtColor(image_copy, bgr, COLOR_GRAY2BGR);
    181 
    182     cvtColor(bgr, image, COLOR_BGR2BGRA);
    183 }
    184 @endcode
    185 #### Start!
    186 
    187 Finally, we have to tell the camera to actually start/stop working. The following code will start
    188 the camera when you press the button, assuming you connected the UI properly:
    189 @code{.objc}
    190 #pragma mark - UI Actions
    191 
    192 - (IBAction)actionStart:(id)sender;
    193 {
    194     [self.videoCamera start];
    195 }
    196 @endcode
    197 #### Hints
    198 
    199 Try to avoid costly matrix copy operations as much as you can, especially if you are aiming for
    200 real-time. As the image data is passed as reference, work in-place, if possible.
    201 
    202 When you are working on grayscale data, turn set grayscale = YES as the YUV colorspace gives you
    203 directly access the luminance plane.
    204 
    205 The Accelerate framework provides some CPU-accelerated DSP filters, which come handy in your case.
    206