質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Google Cloud Platform

Google Cloud Platformは、Google社がクラウド上で提供しているサービス郡の総称です。エンドユーザー向けサービスと同様のインフラストラクチャーで運営されており、Webサイト開発から複雑なアプリ開発まで対応可能です。

Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1331閲覧

APIリクエスト自体は成功している(※画像をURLで渡した場合)が、画像をbase64でエンコードした途端にAPIリクエストが送信されなくなる。

退会済みユーザー

退会済みユーザー

総合スコア0

Google Cloud Platform

Google Cloud Platformは、Google社がクラウド上で提供しているサービス郡の総称です。エンドユーザー向けサービスと同様のインフラストラクチャーで運営されており、Webサイト開発から複雑なアプリ開発まで対応可能です。

Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2019/08/20 11:32

編集2019/08/20 11:51

【ゴール】

Alamofireを用いてGoogle Cloud Vision APIに画像をPOSTし、画像から検出されて返される文字列を取得すること。

ただし、画像はiOSアプリから起動したiPhoneカメラで撮ったものを、base64でSrting型に変換したものを渡すこととする。

【できたこと①】

・以下のように"source"に画像URLを渡すと、APIリクエストが成功し、画像に含まれる文字列を認識してちゃんと返してくれました。

Swift

1let parameters: Parameters = [ 2 "requests": [ 3 "image": [ 4 "source": ["https://1.bp.blogspot.com/-DS_mPoCrYrQ/XVDZ7TPubmI/AAAAAAAASyI/Z7Dl29IkmQwtoiQc5g8a_eqILvpihY9RQCLcBGAs/s1600/fullsizeoutput_5bf.jpeg" 5 ] 6 ], 7 "features": [ 8 "type": "TEXT_DETECTION", 9 "maxResults": 1 10 ] 11 ] 12 ] 13

【できたこと②】

・iPhoneカメラで撮った画像をbase64でString型に変換することも、できていました。

Swift

1// 画像をbae64でエンコードする 2 private func base64EncodeImage(_ image: UIImage) -> String? { 3 return image.pngData()?.base64EncodedString(options: .endLineWithCarriageReturn) 4 }

Swift

1// 画像に含まれるテキストを検出する 2func detect(from image: UIImage, completion: @escaping (OCRResult?) -> Void) { 3 4 guard let base64Image = base64EncodeImage(image) else { 5 completion(nil) 6 return 7 } 8 9// Google Vision APIに、base64でエンコード済みのデータを渡す 10 callGoogleVisionAPI(with: base64Image, completion: completion) 11 12 print ("The type of base64Image is (type(of: base64Image))") 13 14 } 15

↓コンソール

The type of base64Image is String // 画像がString型になっている

【できなかったこと】

iOSアプリから起動したiPhoneカメラで撮ったものを、base64でSrting型に変換したものをAlamofireを使ってAPIリクエストした。

実行前・実行中(runtime)エラーのいずれもなく(エラーが何も出てこない)、Build Succeedとなり、正常にアプリが起動する。

しかし全くの無反応で、403や404などのエラーも返ってきません。

Swift

1let parameters: Parameters = [ 2 "requests": [ 3 "image": ["content": base64EncodedImage], 4 "features": [ 5 "type": "TEXT_DETECTION", 6 "maxResults": 1] 7 ] 8 ]

Google Cloud Platformコンソール画面に行ってAPIリクエストが届いているか確認しても、APIリクエストの数が増えていないので、リクエスト自体が、届いていないと思われます。

【その他のコード】

カメラを起動し、写真を撮るコード

Swift

1// 2// 3// CameraViewController.swift 4// 5// 6 7// MARK: AVCapturePhotoCaptureDelegateデリゲートメソッド 8extension CameraViewController: AVCapturePhotoCaptureDelegate{ 9 // 撮影した画像データが生成されたときに呼び出されるデリゲートメソッド 10 func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { 11 if let imageData = photo.fileDataRepresentation() { 12 // Data型をUIImageオブジェクトに変換 13 let uiImage = UIImage(data: imageData) 14 // 写真ライブラリに画像を保存 15 UIImageWriteToSavedPhotosAlbum(uiImage!, nil,nil,nil) // 正常にライブラリに保存されることを確認済みです 16 17 // こっから下はGoogle Cloud Vision APIのdetectBoundingBoxes()を呼び出している 18 GoogleCloudOCR().detect(from: uiImage!) { ocrResult in 19 20 // self.activityIndicator.stopAnimating() //読み込み中画面を使う場合はコメントアウトを消す 21 guard let ocrResult = ocrResult else { 22 fatalError("Did not recognize any text in this image") 23 } 24 print(ocrResult) 25 } 26 } 27 } 28} 29

【Google CloudにAPIリクエストするコード】

Swift

1// 2// GoogleCloudOCR.swift 3// 4// 5 6import Foundation 7import Alamofire 8import UIKit 9 10class GoogleCloudOCR { 11 12 // Google Cloud Vision API 13 var apiKey = "<My API Key>" 14 var apiURL: URL { 15 return URL(string: "https://vision.googleapis.com/v1/images:annotate?key=(apiKey)")! 16 } 17 18 func detect(from image: UIImage, completion: @escaping (OCRResult?) -> Void) { 19 20 guard let base64Image = base64EncodeImage(image) else { 21 completion(nil) 22 return 23 } 24 callGoogleVisionAPI(with: base64Image, completion: completion) 25 26 print ("The type of base64Image is (type(of: base64Image))") 27 print ("callGoogleVisionAPI(with: base64Image, completion: completion) has been called") 28 } 29 30 private func callGoogleVisionAPI( 31 with base64EncodedImage: String, completion: @escaping (OCRResult?) -> Void) { 32 print ("func callGoogleVisionAPI() has been called") 33 34// APIリクエストが送れなかったparameters(【できなかったこと】) 35 /* 36 let parameters: Parameters = [ 37 "requests": [ 38 "image": ["content": base64EncodedImage], 39 "features": [ 40 "type": "TEXT_DETECTION", 41 "maxResults": 1] 42 ] 43 ] 44 */ 45 46// 以下のparametersならAPIリクエストが成功し、画像に含まれる文字列が返された(【できたこと①】) 47 let parameters: Parameters = [ 48 "requests": [ 49 "image": [ 50 "source": ["imageUri": "https://1.bp.blogspot.com/-DS_mPoCrYrQ/XVDZ7TPubmI/AAAAAAAASyI/Z7Dl29IkmQwtoiQc5g8a_eqILvpihY9RQCLcBGAs/s1600/fullsizeoutput_5bf.jpeg" 51 ] 52 ], 53 "features": [ 54 "type": "TEXT_DETECTION", 55 "maxResults": 1 56 ] 57 ] 58 ] 59 60 let headers: HTTPHeaders = [ 61 "Content-Type": "application/json", 62 "X-Ios-Bundle-Identifier": Bundle.main.bundleIdentifier ?? ""] 63 64 Alamofire.request( 65 apiURL, 66 method: .post, 67 parameters: parameters, 68 encoding: JSONEncoding.default, 69 headers: headers) 70 .responseJSON { response in 71 if response.result.isFailure { 72 completion(nil) 73 return 74 } 75 print(response.result.debugDescription) 76 debugPrint(response) 77 } 78 } 79 80 private func base64EncodeImage(_ image: UIImage) -> String? { 81 return image.pngData()?.base64EncodedString(options: .endLineWithCarriageReturn) 82 } 83 84 struct Vertex: Codable { 85 let x: Int? 86 let y: Int? 87 enum CodingKeys: String, CodingKey { 88 case x = "x", y = "y" 89 } 90 init(from decoder: Decoder) throws { 91 let container = try decoder.container(keyedBy: CodingKeys.self) 92 x = try container.decodeIfPresent(Int.self, forKey: .x) 93 y = try container.decodeIfPresent(Int.self, forKey: .y) 94 } 95 96 func toCGPoint() -> CGPoint { 97 return CGPoint(x: x ?? 0, y: y ?? 0) 98 } 99 } 100 101 struct BoundingBox: Codable { 102 let vertices: [Vertex] 103 enum CodingKeys: String, CodingKey { 104 case vertices = "vertices" 105 } 106 init(from decoder: Decoder) throws { 107 let container = try decoder.container(keyedBy: CodingKeys.self) 108 vertices = try container.decode([Vertex].self, forKey: .vertices) 109 } 110 } 111 112 struct Annotation: Codable { 113 let text: String 114 let boundingBox: BoundingBox 115 enum CodingKeys: String, CodingKey { 116 case text = "description" 117 case boundingBox = "boundingPoly" 118 } 119 init(from decoder: Decoder) throws { 120 let container = try decoder.container(keyedBy: CodingKeys.self) 121 text = try container.decode(String.self, forKey: .text) 122 boundingBox = try container.decode(BoundingBox.self, forKey: .boundingBox) 123 } 124 } 125 126 struct OCRResult: Codable { 127 let annotations: [Annotation] 128 enum CodingKeys: String, CodingKey { 129 case annotations = "textAnnotations" 130 } 131 init(from decoder: Decoder) throws { 132 let container = try decoder.container(keyedBy: CodingKeys.self) 133 annotations = try container.decode([Annotation].self, forKey: .annotations) 134 } 135 } 136 137 struct GoogleCloudOCRResponse: Codable { 138 let responses: [OCRResult] 139 enum CodingKeys: String, CodingKey { 140 case responses = "responses" 141 } 142 init(from decoder: Decoder) throws { 143 let container = try decoder.container(keyedBy: CodingKeys.self) 144 responses = try container.decode([OCRResult].self, forKey: .responses) 145 } 146 } 147} 148

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takabosoft

2019/08/21 00:53 編集

当てずっぽうですが、.endLineWithCarriageReturn無しでbase64エンコードしてみるとどうでしょうか? (改行が入ってJSONとしての構文エラーになったのかな?と。ただ、何にせよレスポンスが無いのは不思議ですね)
退会済みユーザー

退会済みユーザー

2019/08/21 03:55

ありがとうございます! 一旦、.endLineWithCarriageReturnを消して実行したところ、5分程度何も起こらず、その後、Code=-1001 "The request timed out."が現れました。 ここで.endLineWithCarriageReturnを戻して再度実行したところ、やはり5分程度何も起こらず、その後、Code=-1001 "The request timed out."が現れました。 したがって、真の原因はtime outだったと思われます(せっかちな性格のせいでエラーが返ってくるまで待てなかったせいで、お手数おかけし、すみません)。 試しに print (base64EncodedImage) // bae64でエンコード後の文字列を出力 してみると、数百行、いや1000行以上ありそうな文字列が出力され、ハイスペックなMacBookPro(↓)がフリーズしながらコンソールに5分以上出力を続けました。 【利用MacBookPro】 13-inch, 2019, Four Thunderbolt 3 ports プロセッサ 2.8 GHz Intel Core i7 メモリ 16 GB 2133 MHz LPDDR3 なのでデータが重過ぎたのが原因かと、素人ながらに思っています。 画像を圧縮などして、time outにならない方向性を探ってみます(もし、この点に見当違いあればご指摘いただけると幸いです)。 解決次第、追記したいと思います。 回答がない中で、takabosoftさんのコメントが励みになりました! ありがとうございます(^^)
guest

回答1

0

ベストアンサー

Stack Overflowのページに、画像の圧縮方法が載っていて、これを試すと約20秒で正常な結果が返ってきました♡

How do I resize the UIImage to reduce upload image size

https://stackoverflow.com/questions/29137488/how-do-i-resize-the-uiimage-to-reduce-upload-image-size

実際に追加したコードは、以下です。

Swift

1extension UIImage { 2 func resized(withPercentage percentage: CGFloat) -> UIImage? { 3 let canvas = CGSize(width: size.width * percentage, height: size.height * percentage) 4 return UIGraphicsImageRenderer(size: canvas, format: imageRendererFormat).image { 5 _ in draw(in: CGRect(origin: .zero, size: canvas)) 6 } 7 } 8}

↓ 圧縮のために呼び出す

Swift

1private func base64EncodeImage(_ image: UIImage) -> String? { 2 // データを軽くするために画像を圧縮 3 let resizedImage = image.resized(withPercentage: 0.2) 4 5 // base64でエンコード 6 return resizedImage?.pngData()?.base64EncodedString() 7 }

↓返ってきたレスポンス(抜粋)

description = "Boris Johnson is in Paris for Brexit\nwith the French president saying the\nrespected.\nBut he added that the Ireland-Northern\n\"indispensable\" to preserving political st\nThe backstop, opposed by Mr Johnson,\nthe island of Ireland after Brexit\nMr Johnson said that with \"energy and c\nforward\".\nOn Wednesday German Chancellor Ange\nthe UK to find a workable plan.\n"; locale = en;

投稿2019/08/22 12:19

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問