OpenCV是一个开源跨平台的的计算机视觉和机器学习库,可以用来做图片视频的处理、图形识别、机器学习等应用。本文将介绍OpenCV iOS开发中的Hello World起步。
安装
OpenCV安装的方式有三种:
- 下载源代码编译
- 使用CocoaPods安装
- 使用官方的framework
第一种方式太麻烦,而且我也不熟悉,想要自己编译的可以去github下载编译。
第二种方式很简单,再podfile中加入pod 'OpenCV-iOS', '~> 3.1'
,然后运行pod install
就行,但是问题Cocoapods上面OpenCV的版本只有3.x的,没有我想要的2.x的,而且我尝试安装了几次,都因为坑爹的网络以失败告终。
第三种方式就是去官网下载,我下载的最新的2.4.13,后续的例子都是使用此版本进行开发,不过使用的时候还是有不少的坑,后面会提到。
使用 OpenCV
首先将下载好的opencv2.framework
添加到项目中,并且将OpenCV所需的依赖库添加到项目中。
- libc++.tbd
- AVFoundation.framework
- CoreImage.framework
- CoreGraphics.framework
- QuartzCore.framework
- Accelerate.framework
如果要使用摄像头做视频处理,还需要添加以下两个依赖库:
- CoreVideo.framework
- CoreMedia.framework
- AssetsLibrary.framework
添加完依赖库后我们就正式开始写第一个Hello World了,因为OpenCV是C++写的,所以引入项目中的文件需要使用Object-C++的兼容方式来写,具体的做法就是将需要导入OpenCV头文件的m
文件改成mm
文件,后续会先使用Object-C++对OpenCV进行封装,然后就可以在Object-C中正常导入了。不熟悉C++语法的可以使用一下链接进行快速学习。
下面要正式添加代码了,在这个例子中我们可以给摄像头做一个黑白反向的滤镜。
第一步是在我们修改成的mm
的文件中导入OpenCV的库。
#import <opencv2/opencv.hpp>
#import <opencv2/highgui/cap_ios.h>
然后添加一个UIImageView作为显示内容,然后使用OpenCV的CvVideoCamera对象来从摄像头中获取图片显示在UIImageView中,代码如下:
@interface ViewController ()<CvVideoCameraDelegate>{
UIImageView *cameraView;
CvVideoCamera *videoCamera;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
cameraView = [[UIImageView alloc] initWithFrame:self.view.frame];
[self.view addSubview:cameraView];
videoCamera = [[CvVideoCamera alloc] initWithParentView:cameraView];
videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionFront;
videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480;
videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
videoCamera.defaultFPS = 30;
videoCamera.grayscaleMode = NO;
videoCamera.delegate = self;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[videoCamera start];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[videoCamera stop];
}
#pragma mark - CvVideoCameraDelegate
- (void)processImage:(cv::Mat&)image {
//在这儿我们将要添加图形处理的代码
}
要将一个图片进行黑白反转,需要两个步骤,首先将图片转成灰度图片,然后将黑色和白色进行交换, 详细的代码如下:
- (void)processImage:(cv::Mat&)image {
//在这儿我们将要添加图形处理的代码
cv::Mat image_copy;
//首先将图片由RGBA转成GRAY
cv::cvtColor(image, image_copy, cv::COLOR_BGR2GRAY);
//反转图片
cv::bitwise_not(image_copy, image_copy);
//将处理后的图片赋值给image,用来显示
cv::cvtColor(image_copy, image, cv::COLOR_GRAY2BGR);
}
其中Mat
是矩阵对象,在OpenCV中一张图片信息在C++中使用Mat
对象来进行存储,而在C语言中则使用IplImage
指针来存储,cvtColor
就是就是图片的内容进行指定格式的复制。
加上以上代码后,运行后的视频就会出现下面的效果了。
图片反转效果可能碰到的问题
以前的版本,比如我以前使用的2.4.11的版本,在导入``opencv2.framework```添加到项目后,运行可能碰到以下错误:
Undefined symbols for architecture x86_64:
"_jpeg_free_large", referenced from:
_free_pool in opencv2(jmemmgr.o)
"_jpeg_free_small", referenced from:
_free_pool in opencv2(jmemmgr.o)
_self_destruct in opencv2(jmemmgr.o)
"_jpeg_get_large", referenced from:
_alloc_large in opencv2(jmemmgr.o)
_alloc_barray in opencv2(jmemmgr.o)
"_jpeg_get_small", referenced from:
_jinit_memory_mgr in opencv2(jmemmgr.o)
_alloc_small in opencv2(jmemmgr.o)
"_jpeg_mem_available", referenced from:
_realize_virt_arrays in opencv2(jmemmgr.o)
"_jpeg_mem_init", referenced from:
_jinit_memory_mgr in opencv2(jmemmgr.o)
"_jpeg_mem_term", referenced from:
_jinit_memory_mgr in opencv2(jmemmgr.o)
_self_destruct in opencv2(jmemmgr.o)
"_jpeg_open_backing_store", referenced from:
_realize_virt_arrays in opencv2(jmemmgr.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
经过网上搜索得知是缺少了libjpeg.a
依赖库,你可以在网上搜索这个a文件,下载后使用lipo -info libjpeg.a
查看是否包含armv6 armv7 armv7s arm64
支持。当然也可以直接下载libjpeg-turbo,安装后直接从此路径/opt/libjpeg-turbo/lib/libjpeg.a
复制加入到项目中。不过在最新的OpenCV 2.4.13版本已经不会这个错误提示了。
如果运行上面的例子出现出现以下错误:
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_ALAssetsLibrary", referenced from:
objc-class-ref in opencv2(cap_ios_video_camera.o)
"_CMSampleBufferGetPresentationTimeStamp", referenced from:
-[CvVideoCamera captureOutput:didOutputSampleBuffer:fromConnection:] in opencv2(cap_ios_video_camera.o)
"_CMTimeMake", referenced from:
-[CvVideoCamera createVideoDataOutput] in opencv2(cap_ios_video_camera.o)
"_CMSampleBufferGetImageBuffer", referenced from:
-[CaptureDelegate captureOutput:didOutputSampleBuffer:fromConnection:] in opencv2(cap_avfoundation.o)
-[CvVideoCamera captureOutput:didOutputSampleBuffer:fromConnection:] in opencv2(cap_ios_video_camera.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
这是因为我们使用了摄像头和视频, 需要导入CoreVideo.framework
,CoreMedia.framework
,AssetsLibrary.framework
三个库即不会出错了。
网友评论
pod 'OpenCV-iOS', '~> 3.1.1'
- Homepage: https://github.com/edc1591/opencv-ios
- Source: https://github.com/edc1591/opencv-ios.git
- Versions: 3.1.1 [master repo]
我建了一个videoFromCamVC,导入了<opencv2/videoio/cap_ios.h>,并在viewdidload里面只写一句:
CvVideoCamera* testCam = [[CvVideoCamera alloc] init];
报错:
Apple Mach-O Linker (ld) Error Group
"_OBJC_CLASS_$_CvVideoCamera", referenced from:
clang: error: linker command failed with exit code 1 (use -v to see invocation)
这里还没找到原因,请问你有没有解决过这个问题
PS:
1、我用cocoapod导入的opencv:pod 'OpenCV-iOS','~> 3.1.1’;
2、已经使用过canny算法处理图片,且跑成功了;