開發(fā)環(huán)境:
- Xcode 8.3.2
- iPhone 6
- OpenVC 3.2.0
配置環(huán)境
- 到 OpenVC官網(wǎng)下載iOS用的庫。
- 新建一個空工程 OpenCVExample。
- 把下載好的 opencv2.framework 拖進工程(記得勾上 Copy item if need)。
- Build 一下,沒有錯誤則準備完成。
注意:
如果遇到 linker command failed with exit code 1 (use -v to see invocation) 錯誤,可以在 Build Settings 里面查看 Header Search Paths 和Library Search Paths 有沒有配置正確。
驗證配置
1、拖一張圖到工程里。
【注意】不能把圖片放到 Assets.xcassets
里面。Assets.xcassets
里面的圖片會被打包到 Assets.car
文件中,無法獲取圖片路徑,也就不能通過文件路徑的方式讀取圖片。
這里我選了一張月球的圖片做測試。
2、創(chuàng)建一個工具類 JNOpenCVUtils
,然后寫一個通過 OpenCV 讀取本地圖片的方法。
在 JNOpenCVUtils.h
聲明方法
+ (UIImage *)imageWithPath:(NSString *)path;
在 JNOpenCVUtils.m
引入需要用到的 OpenCV 頭文件,實現(xiàn) imageWithPath:
方法
// 使用 imread() 需要引入 “imgcodecs.hpp”
#import <opencv2/imgcodecs.hpp>
// 使用 MatToUIImage() 需要引入 “ imgcodecs/ios.h”
// 只有 iOS 版的 OpenCV.framerwork 才會包含這個頭文件
#import <opencv2/imgcodecs/ios.h>
+ (UIImage *)imageWithPath:(NSString *)path {
if (!path) {
return nil;
}
cv::String str = cv::String(path.UTF8String);
// OpenVC 可以使用 imread() 讀取圖片
cv::Mat mat = imread(str);
// 將 cv::Mat 類型轉(zhuǎn)為 UIImage 類型
UIImage *image = MatToUIImage(mat);
return image;
}
由于這里使用了 C++ 的代碼,所以需要將 JNOpenCVUtils.m
的后綴名改為 .mm
3、在 ViewController 里面引入 JNOpenCVUtils.h
,然后在 viewDidLoad
方法里面寫上讀取并顯示圖片的方法
#import "JNOpenCVUtils.h"
// 根據(jù)文件路徑讀取圖片
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"moon" ofType:@"png"];
UIImage *image = [JNOpenCVUtils imageWithPath:imagePath];
// 創(chuàng)建 UIImageView 來顯示讀取到的圖片
UIImageView *imageView = [[UIImageView alloc] initWithImage: image];
imageView.frame = self.view.bounds;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.backgroundColor = [UIColor grayColor];
[self.view addSubview:imageView];
4、OK!現(xiàn)在我們來運行一下 Command + R
,然后神奇的事情出現(xiàn)了。。。
納尼???圖片呢???怎么只剩下一片灰?看下控制臺打印了什么
libpng error: CgBI: unhandled critical chunk
May 17 15:11:56 OpenVCExample[6816] <Error>: CGImageCreate: invalid image size: 0 x 0.
看到 libpng error
和 unhandled critical chunk
,看來大概是解析 PNG 圖片的時候出錯了,導致無法創(chuàng)建圖片。
幾經(jīng)周折后終于找到原因了,Xcode 在打包的時候會壓縮處理 PNG 圖片,導致 OpenCV 解析出錯。現(xiàn)在我們就把壓縮處理 PNG 圖片的選項去掉。
在 Build Setting
里面搜索 png
,然后把 Compress PNG Files
和 Remove Text Metadata From PNG Files
兩個選項都改為 No
OK!讓我們在來 Command + R
一下
歐耶圖片終于出來了
等等!怎么感覺顏色好像有點不對?我記得我的月球明明是藍色才對啊?
其實 imread()
方法的顏色通道是 BGR 的,而 UIImage
使用的顏色通道是 RGB 的,所以會導致顏色和原圖不一樣。我們把顏色通道改回 RGB 的就好了。方法如下:
#import <opencv2/imgproc.hpp>
// 在 imread() 讀取完圖片后調(diào)用 cvtColor() 方法
// 該方法就可以改變 cv::Mat 對象的顏色通道
cvtColor(mat, mat, CV_BGRA2RGBA);
重新運行一下
好了,大功告成!
下面是 JNOpenCVUtils
的全部代碼
//
// JNOpenCVUtils.h
// OpenVCExample
//
// Created by leung on 16/5/17.
// Copyright ? 2017年 Juno. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface JNOpenCVUtils : NSObject
+ (UIImage *)imageWithPath:(NSString *)path;
@end
//
// JNOpenCVUtils.m
// OpenVCExample
//
// Created by leung on 16/5/17.
// Copyright ? 2017年 Juno. All rights reserved.
//
#import "JNOpenCVUtils.h"
#import <opencv2/imgproc.hpp>
#import <opencv2/imgcodecs.hpp>
#import <opencv2/imgcodecs/ios.h>
using namespace cv;
@implementation JNOpenCVUtils
+ (UIImage *)imageWithPath:(NSString *)path {
if (!path) {
return nil;
}
String str = String(path.UTF8String);
Mat mat = imread(str);
// imread使用的顏色通道是 BGR,而 UIImage 使用的是 RGB,所以會導致圖片顏色不一致,這里需要轉(zhuǎn)換一下
// 使用 cvtColor 必須引入 imgproc.hpp
cvtColor(mat, mat, CV_BGRA2RGBA);
// 將 cv::Mat 類型轉(zhuǎn)為 UIImage 類型
UIImage *image = MatToUIImage(mat);
return image;
}
@end