跳到主要內容

在 iOS 上使用 OpenCV 程式庫

螢幕快照 2014-12-12 下午4.54.30

圖片截自 OpenCV 官網

最近在做一個手機上影像辨識的案子。要進行影像處理方面的工作,當然要先找到工具,而這方面的軟體工具最知名的應該就是 OpenCV 了。OpenCV 所指的是 Open Source Computer Vision Library,這是一套由 Intel 發展的跨平台電腦視覺程式庫,適合用來進行影像處理、電腦視覺等方面的應用,當然用這個程式庫是可以通過上架審核的。下文是在 iOS 平台上進行 OpenCV 應用開發的起手式,即如何透過 Xcode 來叫用 OpenCV 的操作方法。這是小弟的一個工作紀錄,希望整理一下網路上的資料,讓有這方面需求的朋友節省一下時間。

步驟如下:

1。下載 OpenCV for iOS 套件:可以在 OpenCV 官網上下載此套件。下載後,您應該可以看到如下的圖示。

螢幕快照 2014-12-12 下午4.56.35

2。開啟 Xcode 並新增一個 iOS Single View Application 專案:小弟所使用的是 Xcode  6.1.1。

螢幕快照 2014-12-12 下午4.59.42

螢幕快照 2014-12-12 下午5.00.09

3。在專案 Target 下 Build Phases 的 Link Binary with Libraries 中將下載來的程式庫加進來。

螢幕快照 2014-12-12 下午5.06.58

螢幕快照 2014-12-12 下午5.07.13

點按 Add Other...

螢幕快照 2014-12-12 下午5.07.30

選取檔案

螢幕快照 2014-12-12 下午5.08.07

加入完成

4。在 Storyboard 上加入一個 ImageView 與一個 Button View,並進行 outlet 的連結,小弟將 outlet 名稱分別設定成 imageRect 與 loadButton。

螢幕快照 2014-12-12 下午5.13.43

螢幕快照 2014-12-12 下午5.16.51

螢幕快照 2014-12-12 下午5.17.20

5。在 ViewController.h 檔中加入下列編譯器指令:

#ifndef __IPHONE_8_1

#warning "This project uses features only availablein iOS SDK 5.0 and later."

#endif

#ifdef __cplusplus

#import<opencv2/opencv.hpp>

#endif

#ifdef __OBJC__

#import<UIKit/UIKit.h>

#import<Foundation/Foundation.h>

#endif

螢幕快照 2014-12-12 下午5.22.42

6。在 ViewController.h 檔中加入 UIImagePickerControllerDelegate 與 UINavigationControllerDelegate 委派:

螢幕快照 2014-12-12 下午5.26.27

7。接著要開始寫碼了。OpenCV 使用 cv::Mat 來存放影像資料,所以先要編寫 UIImage 與 cv::Mat 的資料轉存方法。在 ViewController.h 中宣告二個方法:

static UIImage* MattoUIImage(const cv::Mat& m);

static void UIImagetoMat(const UIImage* image, cv::Mat& m);

然後再宣告一個要用來叫用 OpenCV 進行影像處理的方法:

-(void)operateWithOpenCV:(UIImage*)image;

8。因為在 Xcode 中 OpenCV 各個常式是以 C++ 的型式存在的,要使用這些常式的話,要將 ViewController.m 的名稱改成 ViewController.mm 才行。請直接在 ViewController.m 上更改其名稱(點按-間隔長一點-再點按)即可。

螢幕快照 2014-12-12 下午5.41.27

9。先做好 UIImagePickerControllerDelegate 所需的委派方法:

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{

[picker dismissViewControllerAnimated:YES completion:nil];

UIImage* image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];

if (image != nil)

[self operateWithOpenCV:image];

}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

{

[picker dismissViewControllerAnimated:YES completion:nil];

}

10。實作二個 UIImage <-> cv::Mat 的方法:

static UIImage* MattoUIImage(const cv::Mat& m)

{

if (m.depth() != CV_8U)

return nil;

NSData* data = [NSData dataWithBytes:m.data length:m.elemSize()*m.total()];

CGColorSpaceRef colorSpace = m.channels() ==1 ? CGColorSpaceCreateDeviceGray():CGColorSpaceCreateDeviceRGB();

CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

CGImageRef imageRef = CGImageCreate(m.cols, m.rows, m.elemSize1()*8, m.elemSize()*8, m.step[0], colorSpace, kCGImageAlphaNoneSkipLast|kCGBitmapByteOrderDefault, provider, NULL, false, kCGRenderingIntentDefault);

UIImage* finalImage = [UIImage imageWithCGImage:imageRef];

CGImageRelease(imageRef);

CGDataProviderRelease(provider);

CGColorSpaceRelease(colorSpace);

return  finalImage;

}

static void UIImagetoMat(const UIImage* image, cv::Mat& m)

{

CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);

CGFloat cols = image.size.width;

CGFloat rows = image.size.height;

m.create(rows, cols, CV_8UC4);

CGContextRef contextRef = CGBitmapContextCreate(m.data, cols, rows, 8, m.step[0], colorSpace, kCGImageAlphaNoneSkipLast|kCGBitmapByteOrderDefault);

CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);

CGContextRelease(contextRef);

}

11。還記得我們有一個載入影像的按鈕嗎?為它寫個方法,loadButtonPressed,來接收 Action message,讓按鈕被按下後,請 ImagePicker 去載入影像。別忘了,要將 Load 按鈕的 Target 連接到 ViewController 這裡來。

- (IBAction)loadButtonPressed:(id)sender {

UIImagePickerController* picker = [[UIImagePickerController alloc] init];

picker.delegate = self;

if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary])

return;

picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

[self presentViewController:picker animated:YES completion:nil];

}

12。至此就完成準備工作,可以將影像傳進 operateWithOpenCV 方法中去處理了。小弟從網路上找了一段應用 Canny 測邊法的程式為例,載入影像讓 OpenCV 幫我們處理。

-(void)operateWithOpenCV:(UIImage*)image{

if (image == nil)

return;

cv::Mat m, gray;

UIImagetoMat(image, m);

cv::cvtColor(m, gray, CV_BGR2GRAY);

cv::GaussianBlur(gray, gray, cv::Size(5,5), 1.2,1.2);

cv::Canny(gray, gray, 0, 50);

m = cv::Scalar::all(255);

m.setTo(cv::Scalar(0, 128, 255, 255), gray);

_imageRect.contentMode = UIViewContentModeScaleAspectFit;

_imageRect.image = MattoUIImage(m);

}

以 OpenCV Canny 測邊法處理後的影像:

FullSizeRender

留言

這個網誌中的熱門文章

何謂博士?

在 簡睿隨筆網誌 中閒逛,無意間發現了這一篇文章,個人覺得寫得很好,特此引用其中一張圖,希望傳佈給更多朋友知道。 這張圖是該文章提到 Ph.D 是什麼時所用的圖,黑線是表示人類目前所瞭解的知識領域,而紅色區域的部份就是個人透過不斷學習所累積的知識,而所謂的 Ph.D. 就是在知識領域的某一點有特別的進展,進而讓人類的知識領域又擴展「一點點」的人。 個人從這篇文章以及自身的體驗中看到至少三件事。首先,大自然是浩瀚無涯的,不管人類再怎麼發展進步,總還是會有未知的地方,所以人要謙卑。其次,要不斷地努力,才能有所突破。最後,在人類的知識領域中,既使您已經是某個領域或一些領域的 Ph.D 了,您不知道的事情還多著呢! 努力、謙卑,就是小弟看完這篇文章後感受到的。

iPod、iPhone 與 iPad 的螢幕自動亮度問題

許多使用 iDevice 的網友應該有注意到螢幕自動亮度的問題,約在 iOS 5 或 iOS 6 時,自動亮度的運作方式似乎有些調整,不會再像以前那樣,螢幕亮度會隨環境不同而即時自動調整。目前觀察到的現象是,會自動調亮但不會自動調暗。 要確認您的 iDevice 裝置上的自動亮度運作是否有問題,可以依照下列的操作檢查看看,雖然有網友說這叫校正,但個人並不覺得下列操作是在進行亮度感應器的校正。 1。將機子帶到暗處(也可以將光感應器遮起來),將亮度滑桿拉到最暗的位置,並將自動調整亮度關閉。 2。將機子帶到亮處,開啟自動亮度。此時應可看到螢幕會漸漸變亮,而亮度滑桿也會往右滑。如果您的機子不會變亮,請 Reset 後(久按睡眠/開啟鍵與 Home 鍵至白蘋果出現)再試看看。如果您的機子像小弟的一樣亮度會變化,那應該就是正常的。如果 Reset 後還是不會作動,可能就是機子的問題。 但如果您又將機子帶到暗處,很抱歉,這時螢幕就不會變暗了。有人說這是 Bugs,有人說這是阿婆怕使用者將機器橫拿時遮到感應器而特別設定的,不論如何,不能自動變暗會讓習慣在晚上使用機子的朋友感到困擾,而這到底是蟲還是故意設定成如此,這就有待證實。 如果環境的照明條件變了但機子不會調暗時,您可以按一下睡眠/開啟鍵讓機子進入休眠,然後再開啟,這時畫面亮度應該就會停在適當的亮度狀態了。 後記:小弟在 iPad mini 與 iPad 2 上測試,iPad mini 運作正常(如大多數朋友所觀察到的狀況),但 iPad 2 在升級到 iOS 6 之後,亮度感應器就都沒有作動,不管怎麼調整都沒有辦法讓亮度自動改變。小弟的 iPad 2 是整修機,而且也過保了,如果您手頭上現還有 iPad 2 而且沒有過保,建議您測看看,有問題且這問題很困擾您的話,請換修吧!

HTC Snap 發表

圖片來源:cNet 網站 被黑莓機帶動,有愈來愈多的商務人士喜歡拿帶有硬體鍵盤 QWERTY 的 PDA 手機。HTC 最近在 美國無線通訊展 CTIA Wireless 2009 上發表一款 QWERTY 的 PDA 手機預計今年第二季中發售。 這款名為 HTC Snap 的手機處理器為 Qualcomm MSM 7225 528 MHz,並有 192MB 的 RAM,256MB 的 ROM,支援 MicroSD 卡。既然定位為 Smartphone,當然內建有 QWERTY 鍵盤另外還附有軌跡球,螢幕為 2.4 吋的 QVGA,預計搭載 Windows Mobile 6.1 Standard (即 Smartphone 版本,無觸控螢幕) 作業系統,有 200 萬畫素的相機,並支援藍牙、AGPS等。為了應付商業人士的通訊需求,電池容量為 1500 mAh,可供八小時的通話與長達十五天的待機之需。 預料這款新機又會帶來一股 QWERTY 風潮。有興趣的網友可以連上各新聞網站找找訊息。