OpenCV with Swift - step by step

Yiwei Ni
Yiwei Ni
Aug 2, 2017 · 6 min read

A small iOS project using OpenCV with Swift.

Just several weeks ago during my summer internship, my supervisor asked me to include OpenCV into an existing iOS project. It sounded so simple to me at that time. However, after reading each one of the Google search results through the sixth page and trying out every possible example, I was still not able to write anything :(

How come other people can do it and I’m getting these weird errors and warnings all over the screen?

Well. I finally figured it out after hours of trying, and to all you folks out there who want to write CV projects in iOS, here is how I did it. I’m trying to be super detailed, so feel free to skip around.

Setup

  1. Download opencv2.framework. I’m using the current newest version 3.2.0 for iOS.
  2. Create a new Xcode project. I’m using Xcode 8.3.3.

Choose “Single View Application”.

I’m gonna call it “OpenCVproject” and choose Swift for language.

Let’s start coding

1. Add opencv2.framework to Xcode project

You can simply drag the opencv2.framework file into the project navigator on the left side in Xcode. However, I will walk through the more complicated way to make sure it is properly linked.

1.1 Click on your project in the left navigator and go to Build Phases -> Link Binary With Libraries. Click the “+”.

1.2 Then “Add Other …”.

1.2 Direct to opencv2.framework and add it. This should automatically copy the framework file into your project directory. In order for OpenCV to work properly, you might need to link several other frameworks into the project. For my project, I added the following ones:

  • AssetsLibrary
  • CoreGraphics
  • CoreMedia
  • CoreFoundation
  • Accelerate

If that doesn’t work out, try UIKit, Foundation, CoreVideo, CoreImage...

Now in the left navigator, a new folder called “Framework” should appear and contain all of the frameworks you just added. If any of these frameworks is not listed under Build Phases -> Link Binary With Libraries, simply drag it from the navigator and add it into the list.

1.3 Under Build Settings ->Framework Search Paths, add the correct path for opencv2.framework. You can use $(PROJECT_DIR)/ for root directory of your project.

This is important. Go to the actual folder and make sure the path match the location of the physical file.

2. Create wrapper class and bridge header

2.1 Go to File -> New -> File...

2.2 Create a new Cocoa Touch Class. Let’s name it OpenCVWrapper and choose objective-C for Language.

2.3 Save it under your project directory and hit “Create Bridging Header”.

2.4 Go back to the project navigator on the left. There are 3 new files you just created: OpenCVWrapper.h, OpenCVWrapper.m and OpenCVproject-Bridging-Header.h. Now, add the following import statement into OpenCVproject-Bridging-Header.h.

#import "OpenCVWrapper.h"

2.5 Click on OpenCVWrapper.m and rename the file extension to “.mm”. If you want, manually change OpenCVWrapper.m to OpenCVWrapper.mm in the file as well.

Now, Xcode should recognize this file as a Objective-C++ file.

2.6 Go to OpenCVWrapper.mm and add the following import statement on the top.

#import <opencv2/opencv.hpp>

Xcode will complain it cannot find the file. Don’t worry. It will be fixed soon.

3. Add Prefix Header file

3.1 Go to File -> New -> File… (again). Scroll to the bottom where you will find PCH File. Create and save it in your project directory.

3.2 Add the following lines in the newly created PrefixHeader.pch file.

#ifdef __cplusplus
#include <opencv2/opencv.hpp>
#endif

So now the file content looks like this:

3.3 Click your project on the left navigator. Under Build Settings -> Prefix Header, add the correct path for your PrefixHeader.pch file. It should be one of the following lines depending on where you created the file.

$(SRCROOT)/OpenCVproject/PrefixHeader.pch
or 
$(SRCROOT)/PrefixHeader.pch

Again, this is important. Go to the actual folder and make sure the path match the location of the physical file.

4. Print OpenCV version

To test if we set up everything correctly, let’s try to print the OpenCV version in ViewController.swift.

4.1 Write a simple function that returns the OpenCV version you are using. Inside OpenCVWrapper.mm right below @implementation OpenCVWrapper, add the following function.

+ (NSString *)openCVVersionString {return [NSString stringWithFormat:@"OpenCV Version %s",  CV_VERSION];}

4.2 Don’t forget to add the function header into OpenCVWrapper.h. Below @Interface OpenCVWrapper:NSObject add the following line.

+ (NSString *)openCVVersionString;

4.3 Now go to ViewController.swift and write the following line inside viewDidLoad() after super.viewDidLoad():

print("\(OpenCVWrapper.openCVVersionString())")

4.4 Run the project and you should see Optional("OpenCV Version 3.2.0") printed in the console if everything is correct.

5. Process image with OpenCV

Luckily, OpenCV’s official tutorial page has provided us with some functions to convert between cv:Mat and UIImage.

(Examples are coming soon)

Tips

If you are getting “opencv2/opencv.hpp not found” or other errors...

  • Put #import <opencv2/opencv.hpp> above all other import statements.
  • Make sure you checked “Copy items if needed” when you drag opencv2.framework into your Xcode project.
  • Make sure nothing is not red in the navigator on the left. If it is red, you will need to delete that and add the file back again, because Xcode cannot find the actual file in the given path.
  • Make sure the actual opencv2.framework file exists under the path you put for Build Settings ->Framework Search Paths.
  • Make sure the actual PrefixHeader.pch file exists under the path your put for Build Settings ->Prefix Header.
  • Make sure you correctly import OpenCVWrapper.h in OpenCVproject-Bridging-Header.h.
  • Try Clean and Clean Build Path. Press “Option” Key while the dropdown menu is open, and “Clean” will become “Clean Build Path”.

More...

Here are some other cool Medium stories about OpenCV and iOS, which I found very helpful. Hope you guys enjoyed reading this :)

670