《Instant OpenCV for iOS》 学习笔记(3)

连接OpenCV到iOS项目中

本文学习在项目中添加OpenCV库的设置方法和调用OpenCV库函数的方法。
学习UIImage和cv::Mat之间相互转换。

准备

下载ios版本的 opencv库文件 opencv2.framework本例中使用3.0。解压。

步骤

  • 继续使用学习笔记(2)的工程。将解压所得的framework拖入项目侧边栏中
    2015-10-09-10.40.58.jpg
  • 在ViewController.h中加入opencv头文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #import <UIKit/UIKit.h>
    #import <opencv2/opencv.hpp>
    #import <opencv2/imgcodecs/ios.h>

    using namespace cv;

    @interface ViewController : UIViewController{
    UIImage* image;
    Mat cvImage;
    }

    @property (weak, nonatomic) IBOutlet UIImageView *imageView;

    @end
  • 修改ViewController.m文件名为ViewController.mm\.mm*表示object c++ 文件。因为opencv是用c++写的。
  • 编辑ViewController.mm中的viewDidLoad()方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    	- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    image = [UIImage imageNamed:@"lena_std.tif"];
    if (image!=nil) {
    //转换image中的UIImage * 格式图像到Mat格式,结果存到cvImage中
    UIImageToMat(image, cvImage);
    }

    if (!cvImage.empty()) {
    Mat cvGrayImage;
    //转换cvImage中的图像到单通道灰度图像,结果存到cvGrayImage中
    cvtColor(cvImage, cvGrayImage, COLOR_BGR2GRAY);
    //高斯模糊去除cvGrayImage中微小的边缘,结果存到cvGrayImage中
    GaussianBlur(cvGrayImage, cvGrayImage, cv::Size(5,5), 1.2, 1.2);
    //Canny算法得到cvGrayImage中图像的边缘,结果存到cvGrayImage中
    Canny(cvGrayImage, cvGrayImage, 0, 50);
    //设置cvImage中图像的所有像素为灰度色
    cvImage.setTo(Scalar::all(255));
    //设置cvImage中图像的边缘部分像素为蓝色
    cvImage.setTo(Scalar(0,128,255,255),cvGrayImage);
    //转换cvImage中的Mat格式图像到UIImage* 格式并且在imageView组件显示
    imageView.image=MatToUIImage(cvImage);
    }
    }
  • 运行程序查看效果。
    2015-10-10-8.58.07.jpg

解释

  1. framework 简化了处理依赖关系的过程。framework封装了头文件和bin文件,这些文件的依赖关系由xcode处理,我们无须手动处理include 路径。我们也不需要手动处理不同架构(比如armv7,armv7s和x86),xcode会根据不同的编译配置自动寻找合适的库。
  2. 通常ios应用程序用Objective-C语言,头文件是 *.h , 源代码文件 *.m。Objective-C语言是C语言的超集,所以可以在Objective-C文件中加入C语言。同理,Objective-C++文件中可以加入C++。OpenCv是用C++写的,所以需要使用Objective-C++。Objective-C++文件的后缀名是 *.mm
  3. 加入using namespace cv;声明使用opencv的命名域空间。这样可以在后续调用opencv方法时显得简化一些。例如cv::Mat 只要写成 Mat就好了。
  4. 在viewDidLoad()中,我们调用UImageToMat方法转换UIImage对象到cv::Mat对象。但请不要频繁调用这个方法,这样做会消耗内存影响程序性能。UImageToMatMatToUIImage方法在头文件中定义。
  5. 在转换完成图像后,使用opencv做了一些简单的图像处理。首先是转换cvImage中的图像到单通道灰度图像。然后使用高斯模糊去除cvGrayImage中微小的边缘;接着使用Canny算法检测cvGrayImage中图像的边缘。为了显示效果,创建了一幅白色背景,边缘像素设置为蓝色的图像。最后调用MatToUIImagecv::Mat对象转回UIImage并在屏幕上显示。
  6. 在viewDidLoad()中,使用:

image = [UIImage imageNamed:@"lena_std.tif"];
方法加载图片有内存溢出的风险。
可以使用如下两句替代:

1
2
NSString * path = [[NSBundle mainBundle] pathForResource:@"lena_std" ofType:@"tif"];
image = [UIImage imageWithContentsOfFile:path];