作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Josip Bernat's profile image

Josip Bernat

Josip从iOS 4测试版就开始为iOS开发了,但他更喜欢用Objective-C和Swift开发iOS.

Years of Experience

13

Share

Swift has been with us for a while now, and through its iterations, 它给我们带来了现代面向对象编程语言的所有特性. These include optionals, generics, tuples, structs that support methods, extensions and protocols, and many more. 但如果你的应用依赖于一个用c++编写的库,那么你就不能再指望Swift了. Luckily Objective-C++ is here to help us.

Since its introduction, Swift与Objective-C有很好的互操作性,我们将使用Objective-C来桥接Swift与c++. objective - c++只不过是具有与c++代码链接能力的Objective-C, and using that, in this blog post, 我们将创建一个简单的应用程序,该应用程序将使用OpenCV识别图像中的Toptal徽标. When we detect that logo, we’ll open the Toptal home page.

As stated on the OpenCV web page:

“OpenCV是为计算效率而设计的,并且非常关注实时应用程序. 该库使用优化的C/ c++编写,可以利用多核处理的优势."

这是一个伟大的解决方案,如果你想快速开发和可靠的计算机视觉.

Creating the OpenCV Objective-C++ Wrapper

In this tutorial, 我们将设计的应用程序将匹配一个图像内的Toptal标志,并打开Toptal web page. To begin, create a new Xcode project and set up CocoaPods using pod init. Add OpenCV to Podfile pod 'OpenCV and run pod install in Terminal. Be sure to uncomment use_frameworks! statement inside Podfile.

当我们在Xcode项目中有OpenCV时,我们需要连接它和Swift. Here is a quick outline of the steps involved:

Step 1: Create a new Objective-C class OpenCVWrapper. When Xcode asks you “Would you like to configure an Objective-C bridging header?” choose “Create bridging header.桥接头是你导入Objective-C类的地方, and then they are visible inside Swift.

Step 2: 为了在Objective-C中使用c++,我们必须将文件扩展名从 OpenCVWrapper.m to OpenCVWrapper.mm. 你可以通过在Xcode的项目导航器中重命名文件来实现. Adding .mm 作为扩展名将文件类型从Objective-C更改为objective - c++.

Step 3: Import OpenCV into OpenCVWrapper.mm using the following import. It’s important to write the given import above #import "OpenCVWrapper.h" because this way we avoid a well-known BOOL conflict. OpenCV contains enum that has the value NO which causes a conflict with the Objective-C BOOL NO value. 如果不需要使用这种enum的类,那么这是最简单的方法. Otherwise, you have to undefine BOOL before importing OpenCV.


#ifdef __cplusplus 

#import  

#import  

#import  

#endif

Step 4: Add #import "OpenCVWrapper.h" to your bridging header.

Open OpenCVWrapper.mm 并创建一个私有接口,我们将在其中声明私有属性:


@interface OpenCVWrapper() 

@property (strong, nonatomic) CvVideoCamera *videoCamera;

@property (assign, nonatomic) cv::Mat logoSample;

@end

In order to create CvVideoCamera, we have to pass UIImageView to it, and we will do that through our designator initializer.


- (instancetype)initWithParentView:(UIImageView *)parentView delegate:(id)delegate {

    

    if (self = [super init]) {

        self.delegate = delegate;

        

        parentView.contentMode = UIViewContentModeScaleAspectFill;

        

        self.videoccamera = [[cvvideoccamera alloc] initWithParentView:parentView];

        self.videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack;

        self.videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPresetHigh;

        self.videoCamera.defaultAVCaptureVideoOrientation = avcapturevideoorientation;

        self.videoCamera.defaultFPS = 30;

        self.videoCamera.grayscaleMode = [NSNumber numberWithInt:0].boolValue;

        self.videoCamera.delegate = self;

        

        // Convert UIImage to Mat and store greyscale version

        UIImage *templateImage = [UIImage imageNamed:@"toptal"];

        cv::Mat templateMat;

        UIImageToMat(templateImage, templateMat);

        cv::Mat grayscaleMat;

        cv::cvtColor(templateMat, grayscaleMat, CV_RGB2GRAY);

        self.logoSample = grayscaleMat;

        

        [self.videoCamera start];

    }

    return self;

}

Inside it, we configure CvVideoCamera that renders video inside the given parentView and through delegate sends us cv::Mat image for analysis.

processImage: method is from CvVideoCameraDelegate protocol, and inside it, we will do template matching.


- (void)processImage:(cv::Mat&)image {

    

    cv::Mat gimg;

    

    // Convert incoming img to greyscale to match template

    cv::cvtColor(image, gimg, CV_BGR2GRAY);

    

    // Get matching

    cv::Mat res(image.rows-self.logoSample.rows+1, self.logoSample.cols-self.logoSample.cols+1, CV_32FC1);

    cv::matchTemplate(gimg, self.logoSample, res, CV_TM_CCOEFF_NORMED);

    cv::threshold(res, res, 0.5, 1., CV_THRESH_TOZERO);

    

    double minval, maxval, threshold = 0.9;

    cv::Point minloc, maxloc;

    cv::minMaxLoc(res, &minval, &maxval, &minloc, &maxloc);

    

    // Call delegate if match is good enough

    if (maxval >= threshold)

    {

        // Draw a rectangle for confirmation

        cv::rectangle(image, maxloc, cv::Point(maxloc.x + self.logoSample.cols, maxloc.y + self.logoSample.rows), CV_RGB(0,255,0), 2);

        cv::floodFill(res, maxloc, cv::Scalar(0), 0, cv::Scalar(.1), cv::Scalar(1.));

        

        [self.delegate openCVWrapperDidMatchImage:self];

    }

}

First, 我们将给定的图像转换为灰度图像,因为在init方法中我们将Toptal徽标模板匹配图像转换为灰度. 下一步是检查匹配与一定的阈值,这将有助于我们缩放和角度. 我们必须检查的角度,因为你可以捕捉照片在不同的角度,我们仍然要检测的标志. 在达到给定的阈值后,我们将调用委托并打开Toptal的网页.

Don’t forget to add NSCameraUsageDescription to your Info.plist otherwise, your application will crash right after calling [self.videoCamera start];.

Now Finally Swift

到目前为止,我们关注的是objective - c++,因为所有的逻辑都是在它里面完成的. Our Swift code will be fairly simple:

  1. Inside ViewController.swift, create UIImageView where CvVideoCamera will render content.
  2. Create an instance of OpenCVWrapper and pass the UIImageView instance to it.
  3. Implement OpenCVWrapperDelegate protocol to open Toptal’s web page when we detect the logo.

class ViewController: UIViewController {

    

    var wrapper: OpenCVWrapper!

    

    @IBOutlet var imageView: UIImageView!

    override func viewDidLoad() {

        super.viewDidLoad()

        //加载视图后做任何额外的设置,通常从一个nib.

    

        wrapper = OpenCVWrapper.init(parentView: imageView, delegate: self)

    }

}

extension ViewController: OpenCVWrapperDelegate {

    //MARK: - OpenCVWrapperDelegate

    

    func openCVWrapperDidMatchImage(_ wrapper: OpenCVWrapper) {

        UIApplication.shared.open(URL.init(string: "http://ngskmc-eis.net")!, options: [:], completionHandler: nil)

    }

}

OpenCV Swift in Action

In this article, 我们已经展示了如何将c++代码与Swift集成,并创建包装器类,这些包装器类用于桥接c++代码与Swift. 现在,当我们通过摄像头检测到Toptal Logo时,我们打开了Toptal的主页.

Detecting Toptal's Logo with OpenCV Swift

对于将来的更新,您可能希望在后台线程中运行CV模板匹配. 这样,你就不会阻塞主线程,UI将保持响应. Because this is a simple example of OpenCV, template matching may not be extra successful, 但本文的目的是向您展示如何开始使用它.

如果你仍然有兴趣学习OpenCV及其在iOS中的更复杂的用途,我推荐 Real-time Object Detection Using MSER in iOS,它会教你如何使用iPhone的后置摄像头进行图像检测.

Understanding the basics

  • What is OpenCV?

    OpenCV(开源计算机视觉库)是一个开源的计算机视觉和机器学习软件库,包含超过2个,500 optimized algorithms

  • What is OpenCV used for?

    OpenCV algorithms can be used to detect and recognize faces, identify objects, classify human actions in videos, track camera movements, track moving objects, extract 3D models of objects, find similar images from image databases, remove red eyes from images taken using flash, follow eye movements, and much more.

  • Can OpenCV be used commercially?

    Yes. OpenCV是一个bsd许可的产品,这意味着它可以在开放和闭源项目中使用, hobby, or commercial products.

  • Does OpenCV use machine learning?

    尽管在文档中没有直接说明OpenCV内部不使用机器学习, OpenCV can be used for training machine learning models. 它支持TensorFlow、Torch/PyTorch和Caffe等深度学习框架.

  • What language is OpenCV written in?

    OpenCV是一个用C/ c++编写的跨平台库,它有c++接口, Python, and MatLab.

  • What platforms are supported?

    目前支持的桌面平台有Windows、Linux、MacOS、FreeBSD和OpenBSD. The mobile platforms are Android, Maemo, and iOS.

  • Does OpenCV use CUDA parallel computing?

    Yes. In 2010, there was a new module that provided GPU acceleration. 它涵盖了库功能的重要部分,并且仍在积极开发中.

  • Does OpenCV support OpenCL?

    Yes. In 2011, 一个提供OpenCV算法的OpenCL加速的新模块被添加到库中,这使得基于OpenCV的代码能够利用异构硬件.

Tags

Consult the author or an expert on this topic.
Schedule a call
Josip Bernat's profile image
Josip Bernat

Located in Zagreb, Croatia

Member since July 30, 2018

About the author

Josip从iOS 4测试版就开始为iOS开发了,但他更喜欢用Objective-C和Swift开发iOS.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Years of Experience

13

World-class articles, delivered weekly.

Subscription implies consent to our privacy policy

World-class articles, delivered weekly.

Subscription implies consent to our privacy policy

Toptal Developers

Join the Toptal® community.