Azure Computer Vision API-v3.0(OCR) をSwiftで

# 概要

[Azure Computer Vision API](https://westcentralus.dev.cognitive.microsoft.com/docs/services/computer-vision-v3-ga/operations/56f91f2e778daf14a499f20d)をSwiftにてサンプルコードを作成しました。
リファレンスにてObjCはあるもののSwiftがないため参考になれば幸いです。

> APIをcallするだけなので、どの言語でもできます

# 環境
Swift 5
xcode11

```swift:Podfile
pod 'Alamofire', '~> 4.7.3'
```

# 事前準備
GUIにて`subscription key`と`endpoint`を取得

# サンプルコード

```swift:ViewController
private func executeOCR() {
    // imageViewにて表示しているものをOCR処理する想定
    guard let image = self.imageView.image else { return }

    // それぞれ取得したものをStringで
    let subscriptionKey = "subscription key"
    let endpoint = "endpoint"

    let urlString = endpoint + "vision/v3.0/ocr"
    var request = URLRequest(url: URL(string: urlString)!)
    request.addValue(subscriptionKey, forHTTPHeaderField: "Ocp-Apim-Subscription-Key")

    // languageは適切なものに変更
    let params: [String: String] = [
        "language":"ja",
        "detectOrientation":"true"
    ]

    Alamofire.upload(multipartFormData: { multipartFormData in
        var compressionQuality: CGFloat = 1.0
        if var imageData = image.jpegData(compressionQuality: compressionQuality) {
            var imageDataCount = imageData.count
            
            repeat {
                imageData = image.jpegData(compressionQuality: compressionQuality)!
                imageDataCount = imageData.count
                compressionQuality -= 0.1
            } while imageDataCount > 4000000
            multipartFormData.append(imageData, withName: "image", fileName: "file.jpeg", mimeType: "image/jpeg")
        }
        
        for (key, value) in params {
            multipartFormData.append(value.data(using: .utf8)!, withName: key)
        }
    }, with: request) { encodingResult in
        switch encodingResult {
        case.success(let upload, _ ,_):
            upload
                .responseData { responseData in
                    let parsedResponse = try? JSONDecoder().decode(OCRResponse.self, from: responseData.data!)
                    // 後述
                    let output = self.getResponseWord(response: parsedResponse)
                    print(output)
            }
        case.failure(let _): break
        }
    }
}

```

```swift:OCRResponse
struct OCRResponse: Codable {
    var language: String?
    var orientation: String?
    var regions: [Regions]?
//  textAngleはIntのはずだがStringで返される時もあったため消しています
}

struct Regions: Codable {
    var boundingBox: String?
    var lines: [Lines]?
}

struct Lines: Codable {
    var boundingBox: String?
    var words: [Words?]
}

struct Words: Codable {
    var boundingBox: String?
    var text: String?
}
```

# iPhoneの画像拡張子事情
SS: `.png`
カメラ: `.heic`

Q:
・・・heic?

A:
iOS11から実装されていたもので「HEIF」形式の拡張子、それまでは「JPEG」形式
この形式は「高画質のまま軽量化」した写真の保存形式
その拡張子が`.heic`

# 一部コード解説

## repeat
```swift
repeat {
    imageData = image.jpegData(compressionQuality: compressionQuality)!
    imageDataCount = imageData.count
    compressionQuality -= 0.1
} while imageDataCount > 4000000
```
リファレンスにも記載があるが、4MBが上限となっている。
HEIF形式で保存される`.heic`ですら4MBを超えることがある。(せっかく軽量化しているのに・・・
そのため、4MBを超えるようであれば10％ずつ質をさげている。

## updataメソッド
```swift
Alamofire.upload
```
これはDefaultでHTTPメソッドがPOSTで行ってくれる

## getResponseWord
```swift
private func getResponseWord(response: OCRResponse?) -> String {
    guard let response = response else { return "" }
    var output = ""

    response.regions?.forEach { regions in
        regions.lines?.forEach { lines in
            lines.words.forEach { words in
                output += words?.text ?? ""
            }
            output += "\n"
        }
    }
}
```

ここで各自必要なものを取得。
上記サンプルは１ワード毎に改行したものを返している。

# 補足
無料期間は30日
文字読み取れて嬉しい

質問等あればお気軽に！
速さ重視で作ったのでOptinal関連やrepeat文なぜ？等は目を瞑って下さい。