Translate

bloggerads內文

2017年4月18日 星期二

IOS開發 第一次接觸OpenCV 就上手

由於之後專案可能會做到影像辨識的功能,但小弟真的沒接觸過啊,但是身為一個App工程師,就是要實現需求者的願望啊,於是只好上網搜尋相關資料,以下是我的步驟,讓想學習的人節省一些找資料的時間.


步驟:

1.下載 OpenCV for iOS 套件: OpenCV 官網,會看到如下圖所示.
螢幕快照 2014-12-12 下午4.56.35

2.在專案 Target 下 Build Phases 的 Link Binary with Libraries 中將下載來的程式庫加進來,加入剛剛下載framework

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

4.在 MainViewController.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
5.在 ViewController.h 檔中加入 UIImagePickerControllerDelegate 與 UINavigationControllerDelegate 委派,最後會如下圖所示.

6.接著要開始寫碼了。OpenCV 使用 cv::Mat 來存放影像資料,所以先要編寫 UIImage 與 cv::Mat 的資料轉存方法。
7.因為在 Xcode 中 OpenCV 各個常式是以 C++ 的型式存在的,要使用這些常式的話,要將 MainViewController.m 的名稱改成 MainViewController.mm 才行。請直接在 MainViewController.m 上更改其名稱(點按-間隔長一點-再點按)即可。
8.接下來做好 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];
}
9.實作二個 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);
}
10.還記得我們有一個載入影像的按鈕嗎?為它寫個方法,loadButtonPressed,來接收 Action message,讓按鈕被按下後,請 ImagePicker 去載入影像。別忘了,要將 Load 按鈕的 Target 連接到 ㄩMainViewController 這裡來。
– (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];
}
11.至此就完成準備工作,可以將影像傳進 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 測邊法處理後的影像:

範例檔案:下載
結論:以上只是先了解OpenCV 應用,但最終還不是我要的結果,得再繼續study了.Q.Q
參考來源:https://bobffin.wordpress.com/2014/12/12/在-ios-上進行-opencv-的開發/

沒有留言:

張貼留言