Skip to content

Instantly share code, notes, and snippets.

@seven0525
Last active June 27, 2018 05:15
Show Gist options
  • Save seven0525/e18fb9d4f14842c2e4710def7ed04851 to your computer and use it in GitHub Desktop.
Save seven0525/e18fb9d4f14842c2e4710def7ed04851 to your computer and use it in GitHub Desktop.
一時停止してるし、レシート写真から情報を読みとるやつ自分で途中まで作ってみた ref: https://qiita.com/ahpjop/items/a36817bc5d8e25e634e3
// Build our API request
let jsonRequest = [
"requests": [
"image": [
"content": imageBase64
],
"features": [
[
"type": "TEXT_DETECTION",
"maxResults": 10
],
[
//"type": "FACE_DETECTION",
//"maxResults": 10
]
]
]
]
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import UIKit
import SwiftyJSON
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let imagePicker = UIImagePickerController()
let session = URLSession.shared
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var spinner: UIActivityIndicatorView!
@IBOutlet weak var labelResults: UITextView!
@IBOutlet weak var faceResults: UITextView!
var googleAPIKey = "YOUR_API_KEY"
var googleURL: URL {
return URL(string: "https://vision.googleapis.com/v1/images:annotate?key=\(googleAPIKey)")!
}
@IBAction func loadImageButtonTapped(_ sender: UIButton) {
imagePicker.allowsEditing = false
imagePicker.sourceType = .photoLibrary
present(imagePicker, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
imagePicker.delegate = self
labelResults.isHidden = true
faceResults.isHidden = true
spinner.hidesWhenStopped = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
/// Image processing
extension ViewController {
func analyzeResults(_ dataToParse: Data) {
// Update UI on the main thread
DispatchQueue.main.async(execute: {
// Use SwiftyJSON to parse results
let json = JSON(data: dataToParse)
let errorObj: JSON = json["error"]
self.spinner.stopAnimating()
self.imageView.isHidden = true
self.labelResults.isHidden = false
self.faceResults.isHidden = false
self.faceResults.text = ""
// Check for errors
if (errorObj.dictionaryValue != [:]) {
self.labelResults.text = "Error code \(errorObj["code"]): \(errorObj["message"])"
} else {
// Parse the response
print(json)
let responses: JSON = json["responses"][0]
/*
// Get face annotations
let faceAnnotations: JSON = responses["faceAnnotations"]
if faceAnnotations != nil {
let emotions: Array<String> = ["joy", "sorrow", "surprise", "anger"]
let numPeopleDetected:Int = faceAnnotations.count
self.faceResults.text = "People detected: \(numPeopleDetected)\n\nEmotions detected:\n"
var emotionTotals: [String: Double] = ["sorrow": 0, "joy": 0, "surprise": 0, "anger": 0]
var emotionLikelihoods: [String: Double] = ["VERY_LIKELY": 0.9, "LIKELY": 0.75, "POSSIBLE": 0.5, "UNLIKELY":0.25, "VERY_UNLIKELY": 0.0]
for index in 0..<numPeopleDetected {
let personData:JSON = faceAnnotations[index]
// Sum all the detected emotions
for emotion in emotions {
let lookup = emotion + "Likelihood"
let result:String = personData[lookup].stringValue
emotionTotals[emotion]! += emotionLikelihoods[result]!
}
}
// Get emotion likelihood as a % and display in UI
for (emotion, total) in emotionTotals {
let likelihood:Double = total / Double(numPeopleDetected)
let percent: Int = Int(round(likelihood * 100))
self.faceResults.text! += "\(emotion): \(percent)%\n"
}
} else {
self.faceResults.text = "No faces found"
}*/
// Get label annotations
let labelAnnotations: JSON = responses["textAnnotations"]
let numLabels: Int = labelAnnotations.count
var labels: Array<String> = []
if numLabels > 0 {
var labelResultsText:String = "Labels found: "
for index in 0..<1 {
let label = labelAnnotations[index]["description"].stringValue
labels.append(label)
}
for label in labels {
// if it's not the last item add a comma
if labels[labels.count - 1] != label {
labelResultsText += "\(label), "
} else {
labelResultsText += "\(label)"
}
}
self.labelResults.text = labelResultsText
}
//} else {
// self.labelResults.text = labelResultsText //"No labels found"
//}
}
})
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.contentMode = .scaleAspectFit
imageView.isHidden = true // You could optionally display the image here by setting imageView.image = pickedImage
spinner.startAnimating()
faceResults.isHidden = true
labelResults.isHidden = true
// Base64 encode the image and create the request
let binaryImageData = base64EncodeImage(pickedImage)
createRequest(with: binaryImageData)
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
func resizeImage(_ imageSize: CGSize, image: UIImage) -> Data {
UIGraphicsBeginImageContext(imageSize)
image.draw(in: CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
let resizedImage = UIImagePNGRepresentation(newImage!)
UIGraphicsEndImageContext()
return resizedImage!
}
}
/// Networking
extension ViewController {
func base64EncodeImage(_ image: UIImage) -> String {
var imagedata = UIImagePNGRepresentation(image)
// Resize the image if it exceeds the 2MB API limit
if (imagedata?.count > 2097152) {
let oldSize: CGSize = image.size
let newSize: CGSize = CGSize(width: 800, height: oldSize.height / oldSize.width * 800)
imagedata = resizeImage(newSize, image: image)
}
return imagedata!.base64EncodedString(options: .endLineWithCarriageReturn)
}
func createRequest(with imageBase64: String) {
// Create our request URL
var request = URLRequest(url: googleURL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue(Bundle.main.bundleIdentifier ?? "", forHTTPHeaderField: "X-Ios-Bundle-Identifier")
// Build our API request
let jsonRequest = [
"requests": [
"image": [
"content": imageBase64
],
"features": [
[
"type": "TEXT_DETECTION",
"maxResults": 1
]/*,
[
"type": "FACE_DETECTION",
"maxResults": 10
]*/
]
]
]
let jsonObject = JSON(jsonDictionary: jsonRequest)
// Serialize the JSON
guard let data = try? jsonObject.rawData() else {
return
}
request.httpBody = data
// Run the request on a background thread
DispatchQueue.global().async { self.runRequestOnBackgroundThread(request) }
}
func runRequestOnBackgroundThread(_ request: URLRequest) {
// run the request
let task: URLSessionDataTask = session.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "")
return
}
self.analyzeResults(data)
}
task.resume()
}
}
// FIXME: comparison operators with optionals were removed from the Swift Standard Libary.
// Consider refactoring the code to use the non-optional operators.
fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
switch (lhs, rhs) {
case let (l?, r?):
return l < r
case (nil, _?):
return true
default:
return false
}
}
// FIXME: comparison operators with optionals were removed from the Swift Standard Libary.
// Consider refactoring the code to use the non-optional operators.
fileprivate func > <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
switch (lhs, rhs) {
case let (l?, r?):
return l > r
default:
return rhs < lhs
}
}
© 2018 GitHub, Inc.
Terms
Privacy
Security
Status
Help
Contact GitHub
API
Training
Shop
Blog
About
Press h to open a hovercard with more details.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment