iPhoneアプリでOpenCV（CocoaPodsを使用しないVer）

#はじめに
研究で画像処理を使う機会が多く，iOSでも何かしらの画像処理をしたかったためSwiftでOpenCVを使う方法を調べたのでそのメモ．

#必要なもの
・Xcode
・OpneCVフレームワーク（以下のリンクから任意のバージョンをDL）
・[OpenCV公式サイト](https://opencv.org/releases.html)
・オススメは3.x系
・**画像処理に対する熱意**

#実装方法
##1.フレームワークをぶち込む
先ほどダウンロードしたフレームワークを，OpneCVを使いたいプロジェクトフォルダに投げる．

<img width="272" alt="image01.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/830db177-d768-5fad-ece2-e57dc465c2dc.png">

次に，「Copy items if needed」にチェックを入れる．

<img width="716" alt="image02.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/bd2ff7e0-077a-8277-f09a-95e21e3ccb3e.png">

##2.コードを書くファイルを作成する
OpenCVを書くためのファイルを作成する．
「⌘ + N」または「File」→「New」→「File...」で以下のような画面が出現する．
そして「Cocoa Touch Class」を選択して「Next」

<img width="717" alt="image03.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/3730a9b1-53c7-8dac-e807-646ec3f33685.png">

クラス名は何でもいいが， Subclassは「NSObject」，**Languageは「Objective-C」**を選択して「Next」

<img width="711" alt="image04.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/80f1f7b9-ad92-2ce3-d78a-c3f3a95b4dac.png">

ファイルを任意の場所へ「Create」したら，以下のメッセージが出るので「Creat
e Bridging Header」を選択してObjective-Cのブリッジヘッダーを作成する（bridging headerについての細かい説明は省略）

<img width="550" alt="image05.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/dc7fc2e3-3594-af77-415d-9120d788c60d.png">

以下のようにファイルが3つ作成される．

<img width="270" alt="image06.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/cf8a42be-150b-dc07-173c-269cd02c6015.png">

「opencvTest-Bridging-Header.h」を選択して「opnecvWrapper.h」をインポート．

<img width="987" alt="image07.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/1612aa70-4232-7f88-555e-2f616f70709d.png">

こんな感じ．


##3.拡張子を変更
Objective-CとC++を使うので「opencvWrapper.m」を「opencvWrapper.mm」へ変更．

<img width="268" alt="image08.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/55efff78-1803-0a4e-005b-962390bd5f3d.png">
↓
<img width="270" alt="image09.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/936b5e24-fb11-05dd-da2e-63048c32cf4a.png">

##4.ヘッダーファイルをインポート
OpenCVのヘッダーファイルを「opnecvWrapper.mm」に追加
<img width="228" alt="image10.png" src="https://qiita-image-store.s3.amazonaws.com/0/173720/84ac559a-ec8a-f055-96f8-a702e6e6f911.png">

以上でOpenCVを使う準備は完了

##5.試しに何かやってみる
では，早速何かしらの画像処理をやってみる．
今回はサクッと画像のグレースケール化．
グレースケール化程度ならSwiftのみでも可能だが今回は動作確認のためにやってみる．
画像は例にならって[レナ](https://goo.gl/images/6iM6Bc)さん．
![lena.jpg](https://qiita-image-store.s3.amazonaws.com/0/173720/28f7946e-bed2-a9f8-7e94-cda8eb1589f8.jpeg)


##6.storyboardを編集
UIImageViewを配置してレナさんを表示，Buttonを配置する．
**関連付けを忘れないように**
![image11.png](https://qiita-image-store.s3.amazonaws.com/0/173720/48a3e9ff-b28f-a81f-e4b4-ca99322d5498.png)

##7.コードを書いていく
まずは「opnecvWrapper.h」から

```objective-c++:opencvWrapper.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface opencvWrapper : NSObject
//(返り値の型 *)関数名:(引数の型 *)引数名;
- (UIImage *)toGray:(UIImage *)input_img;

@end
```

**#import < UIKit/UIKit.h >を忘れずに！！**

次に「opencvWrapper.mm」の編集

```objective-c++:opencvWrapper.mm
#import <opencv2/opencv.hpp>
//-------------------------------これも忘れずに書く
#import <opencv2/imgcodecs/ios.h> //---①
//-------------------------------
#import "opencvWrapper.h"

@implementation opencvWrapper

-(UIImage *)toGray:(UIImage *)input_img {
    // 変換用Matの宣言
    cv::Mat gray_img;
    // input_imageをcv::Mat型へ変換
    UIImageToMat(input_img, gray_img); //---②
    
    cv::cvtColor(gray_img, gray_img, CV_BGR2GRAY); //---③
    
    input_img = MatToUIImage(gray_img); //---④
    
    return input_img; //---⑤
}

@end
```
①　これがないとUIImageToMatとかが使えない
②　引数のinput_imgをcv::Mat型のgray_imgへ変換
③　gray_imgをRGB画像からグレースケール画像へ変換
④　cv::Mat型からUIImage型へ変換し，input_imgへ入れる
⑤　ViewController.swiftへ返す

最後に「ViewController.swift」の編集

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    //--------------------------OpenCVファイルのインポート
    let openCV = opencvWrapper()
    //--------------------------
    
    // レナ嬢を表示するUIImageView
    @IBOutlet var image : UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // グレースケール化ボタン
    @IBAction func toGray() {
        // UIImageViewに表示するUIImage
        let gray_img : UIImage!
        // gray_imgにグレースケール化したimageを入れる
        gray_img  = openCV.toGray(image.image) //---①
        // imageにgray_imageを表示
        image.image = gray_img //---②
    }
}
```

①　openWrapperのtoGray関数へUIImageに表示されている画像を渡し，返ってきた画像をgray_imgに入れる
②　返ってきたgray_imgをUIImageViewへ表示

##8.完成図
![togray.gif](https://qiita-image-store.s3.amazonaws.com/0/173720/d4ae0aba-d275-28fb-48ba-c55df36d4bfd.gif)

OpenCVで画像処理を行うことが確認できた．
以上．