Computer Vision

How to develop an OpenCV C++ algorithm in Xcode

Everything you need to get up and running to develop and debug an OpenCV C++ algorithm

Getting Started

In this section we’ll setup a new C++ command line tool project in Xcode. Then we’ll add OpenCV to the project. Then we’ll look at three ways of capturing images using OpenCV; reading image from disk, reading frames from a video and capturing frames from the webcam. This is the point you’ll have a chance to process the image. For this post we’ll simply display the image back to the user.

  1. Installing OpenCV
  2. Linking OpenCV
  3. Reading images from disk
  4. Reading video from disk
  5. Streaming the camera feed
  6. Running the tool from the command line

1. Create new Xcode project

Let’s start by create a new Xcode project. From menu select File > New > Project…

Command line tool run output

2. Installing OpenCV

To install OpenCV we’ll be making use of command line tool Homebrew. Open Terminal app and run the following command:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install opencv
OpenCV installation path

3. Linking OpenCV

In this step we will link OpenCV to our MyOpenCVAlgorithm command line tool target. Here is what we need to do to link OpenCV:

  1. Tell Xcode where the library modules live or rather where to look for them (Library Search Paths)
  2. Tell Xcode where to find the public interfaces for the functionality contained within the library (Header Search Paths)
brew install pkg-config
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
OpenCV package config file
pkg-config --libs-only-l opencv4 | pbcopy
Open project navigator on the right hand side pane
Select the project configuration file from the project navigator pane
Linking OpenCV library
pkg-config --libs-only-L opencv4 | cut -c 3- | pbcopy
Settings Library search paths in Xcode
pkg-config --cflags opencv4 | cut -c 3- | pbcopy
Setting Header search paths in Xcode
dyld: Library not loaded:
/usr/local/opt/gcc/lib/gcc/10/libgfortran.5.dylib
Referenced from: /usr/local/opt/openblas/lib/libopenblas.0.dylib
Reason: no suitable image found. Did find:
/usr/local/opt/gcc/lib/gcc/10/libgfortran.5.dylib: code signature in
...

3. Reading images from disk

In this step we’ll use OpenCV to read an image from disk and display it to the screen.

#include <opencv2/opencv.hpp>
int showImageFromDisk(std::string imagePath) {
cv::Mat image = cv::imread(imagePath);
// process image
cv::imshow("Image from disk", image);
cv::waitKey();
return 0;
}
int main(int argc, const char * argv[]) {
if (argc == 3) {
std::string readType(argv[1]);
std::string filePath(argv[2]);
if (readType == "--image") {
return showImageFromDisk(filePath);
}
}
return 0;
}
--image <PATH_TO_IMAGE>

4. Reading video from disk

In this step we’ll learn how stream the frames from a video to the user using OpenCV.

int showVideoFromDisk(std::string videoPath) {
cv::VideoCapture videoCapture(videoPath);
if (!videoCapture.isOpened()) {
std::cout << "Error opening video stream of file" << std::endl;
return -1;
}
while (true) {
cv::Mat frame;
videoCapture >> frame;
// process frame here
if (frame.empty()) break;
cv::imshow("Video frame", frame);
if (cv::waitKey(10) == 27) break;
}
videoCapture.release();
cv::waitKey();
return 0;
}
int main(int argc, const char * argv[]) {
if (argc == 3) {
std::string readType(argv[1]);
std::string filePath(argv[2]);
if (readType == "--image") {
return showImageFromDisk(filePath);
} else if (readType == "--video") {
return showVideoFromDisk(filePath);
}
}
return 0;
}
--video <PATH_TO_VIDEO_FILE>
Video playing

5. Streaming the camera feed

In this step we’ll use OpenCV functionality to stream the camera feed back to the user.

int streamWebcamFeed() {
cv::VideoCapture videoCapture(0);
if (!videoCapture.isOpened()) {
std::cout << "Unable to connect to webcam" << std::endl;
return -1;
}
while(true) {
cv::Mat frame;
videoCapture >> frame;
if(frame.empty()) break;
cv::imshow("Camera feed", frame);
if (cv::waitKey(10) == 27) break;
}
videoCapture.release();
return 0;
}
int main(int argc, const char * argv[]) {
if (argc == 3) {
std::string readType(argv[1]);
std::string filePath(argv[2]);
if (readType == "--image") {
return showImageFromDisk(filePath);
} else if (readType == "--video") {
return showVideoFromDisk(filePath);
} else {
return streamWebcamFeed();
}
} else {
return streamWebcamFeed();
}
return 0;
}
This app has crashed because it attempted to access privacy-sensitive data without a usage description.  The app's Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.
Create a new file
cp ${PROJECT_DIR}/${INFOPLIST_FILE} ${CONFIGURATION_BUILD_DIR}/
OpenCV displaying camera feed

7. Running the tool from the command line

So far we have been running the C++ algorithm through Xcode. However we can also run the tool from the command line. This step will teach you how.

cd ~/PATH/TO/MyOpenCVAlgorithm
xcodebuild -scheme MyOpenCVAlgorithm -derivedDataPath .derived_data
Executable location built through Terminal
./.derived_data/Build/Products/Debug/MyOpenCVAlgorithm
Terminal requesting camera permission

Summary

In this post we have learnt:

  • How to install OpenCV in MacOS
  • How to display images from disk to the user using OpenCV
  • How to stream frames from a video on disk using OpenCV
  • How to stream the camera feed using OpenCV
  • Building and running the algorithm from Xcode
  • Building and running the algorithm from Terminal

Final Notes

You can find the full source code in my Github repositories:

Senior iOS Engineer @ Onfido. Writing weekly blogs on iOS and programming. Follow me to stay tuned!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store