Skip to content

Commit

Permalink
upload more userdata to firebase database and firebase storage, based…
Browse files Browse the repository at this point in the history
… on the current users and the time uploaded
  • Loading branch information
superzzp committed Feb 10, 2019
1 parent 5c4b634 commit 0ea805d
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 48 deletions.
12 changes: 12 additions & 0 deletions VisualEyes.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
0B2DB115220FF3320092F828 /* Login.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B2DB114220FF3320092F828 /* Login.storyboard */; };
0B2DB1172210033F0092F828 /* UploadService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B2DB1162210033F0092F828 /* UploadService.swift */; };
0B2DB119221008240092F828 /* CreateUserNameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B2DB118221008240092F828 /* CreateUserNameViewController.swift */; };
0B2DB11B2210CD970092F828 /* AzureCognitiveService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B2DB11A2210CD970092F828 /* AzureCognitiveService.swift */; };
0B2DB11D2210E2C50092F828 /* UIImage+Size.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B2DB11C2210E2C50092F828 /* UIImage+Size.swift */; };
0B2DB11F2210E5140092F828 /* StorageReference+Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B2DB11E2210E5140092F828 /* StorageReference+Post.swift */; };
0B6166E4220D683C006EDA27 /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6166E3220D683C006EDA27 /* StorageService.swift */; };
0B6166E6220D6914006EDA27 /* UserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6166E5220D6914006EDA27 /* UserService.swift */; };
0B6166E8220D6A09006EDA27 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6166E7220D6A09006EDA27 /* LoginViewController.swift */; };
Expand All @@ -35,6 +38,9 @@
0B2DB114220FF3320092F828 /* Login.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Login.storyboard; sourceTree = "<group>"; };
0B2DB1162210033F0092F828 /* UploadService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadService.swift; sourceTree = "<group>"; };
0B2DB118221008240092F828 /* CreateUserNameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateUserNameViewController.swift; sourceTree = "<group>"; };
0B2DB11A2210CD970092F828 /* AzureCognitiveService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AzureCognitiveService.swift; sourceTree = "<group>"; };
0B2DB11C2210E2C50092F828 /* UIImage+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Size.swift"; sourceTree = "<group>"; };
0B2DB11E2210E5140092F828 /* StorageReference+Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StorageReference+Post.swift"; sourceTree = "<group>"; };
0B6166E3220D683C006EDA27 /* StorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = "<group>"; };
0B6166E5220D6914006EDA27 /* UserService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserService.swift; sourceTree = "<group>"; };
0B6166E7220D6A09006EDA27 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -85,6 +91,7 @@
0B6166E3220D683C006EDA27 /* StorageService.swift */,
0B6166E5220D6914006EDA27 /* UserService.swift */,
0B2DB1162210033F0092F828 /* UploadService.swift */,
0B2DB11A2210CD970092F828 /* AzureCognitiveService.swift */,
);
path = Services;
sourceTree = "<group>";
Expand Down Expand Up @@ -159,6 +166,8 @@
children = (
0BF9B2E5220772F300A3CDCF /* Extensions.swift */,
0B2DB112220FF2BA0092F828 /* Storyboard+Utility.swift */,
0B2DB11C2210E2C50092F828 /* UIImage+Size.swift */,
0B2DB11E2210E5140092F828 /* StorageReference+Post.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -349,8 +358,11 @@
0BF9B2D022076CF400A3CDCF /* ViewController.swift in Sources */,
0B2DB119221008240092F828 /* CreateUserNameViewController.swift in Sources */,
0B6166E6220D6914006EDA27 /* UserService.swift in Sources */,
0B2DB11D2210E2C50092F828 /* UIImage+Size.swift in Sources */,
0B2DB113220FF2BA0092F828 /* Storyboard+Utility.swift in Sources */,
0B2DB11B2210CD970092F828 /* AzureCognitiveService.swift in Sources */,
0BF9B2F4220C275F00A3CDCF /* UserSnapPos.swift in Sources */,
0B2DB11F2210E5140092F828 /* StorageReference+Post.swift in Sources */,
0BF9B2E6220772F300A3CDCF /* Extensions.swift in Sources */,
0BF9B2EE220773E200A3CDCF /* UserData.swift in Sources */,
0B6166E4220D683C006EDA27 /* StorageService.swift in Sources */,
Expand Down
Binary file not shown.
87 changes: 45 additions & 42 deletions VisualEyes/Controller/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,9 @@ class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate, UI
// self.azureFaceAnalysis(facePicsUrl: url)
// }
UploadService.create(for: image) { url in
self.azureFaceAnalysis(facePicsUrl: url)
//self.azureFaceAnalysis(facePicsUrl: url)


}
//uiImagetoURL(image: image)
}
Expand Down Expand Up @@ -304,48 +306,49 @@ class ViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate, UI
// }
// }

func azureFaceAnalysis (facePicsUrl: URL?) {
let headers: HTTPHeaders = [
"Content-Type" : "application/json",
"Ocp-Apim-Subscription-Key": Constants.Azure.SUBSCRIPTIONKEY,
]
print(facePicsUrl?.absoluteString)
//some parameters included in Constants.Azure.AZUREURL
let parameters: Parameters = [
// "returnFaceId":true,
// "returnFaceLandmarks": false,
// "returnFaceAttributes": "age, gender, emotion, hair, makeup, occlusion, accessories, blur",
"url" : facePicsUrl?.absoluteString
]

Alamofire.request(self.azureURL, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
if response.result.isSuccess {
print("successfully get JSON data!")
let jso: JSON = JSON(response.result.value!)
//print out the returned json for testing
print(jso)
self.updateUserData(json: jso)
}else{
print("fail to get JSON response!")
DispatchQueue.main.async {
self.navigationItem.title = "Fail to get image infomation"
}
}
}
}
// func azureFaceAnalysis (facePicsUrl: URL?) {
// let headers: HTTPHeaders = [
// "Content-Type" : "application/json",
// "Ocp-Apim-Subscription-Key": Constants.Azure.SUBSCRIPTIONKEY,
// ]
// print(facePicsUrl?.absoluteString)
// //some parameters included in Constants.Azure.AZUREURL
// let parameters: Parameters = [
// // "returnFaceId":true,
// // "returnFaceLandmarks": false,
// // "returnFaceAttributes": "age, gender, emotion, hair, makeup, occlusion, accessories, blur",
// "url" : facePicsUrl?.absoluteString
// ]
//
// Alamofire.request(self.azureURL, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
// if response.result.isSuccess {
// print("successfully get JSON data!")
// let jso: JSON = JSON(response.result.value!)
// //print out the returned json for testing
// print(jso)
//
// //self.updateUserData(json: jso)
// }else{
// print("fail to get JSON response!")
// DispatchQueue.main.async {
// self.navigationItem.title = "Fail to get image infomation"
// }
// }
// }
// }

func updateUserData (json: JSON) {
self.userDataModel.age = json[0]["faceAttributes"]["age"].intValue
self.userDataModel.gender = json[0]["faceAttributes"]["gender"].stringValue
self.userDataModel.neutral = json[0]["faceAttributes"]["emotion"]["neutral"].doubleValue
self.userDataModel.happiness = json[0]["faceAttributes"]["emotion"]["happiness"].doubleValue
self.userDataModel.anger = json[0]["faceAttributes"]["emotion"]["anger"].doubleValue
self.userDataModel.disgust = json[0]["faceAttributes"]["emotion"]["disgust"].doubleValue
self.userDataModel.fear = json[0]["faceAttributes"]["emotion"]["fear"].doubleValue
self.userDataModel.sadness = json[0]["faceAttributes"]["emotion"]["sadness"].doubleValue
self.userDataModel.contempt = json[0]["faceAttributes"]["emotion"]["contempt"].doubleValue
self.userDataModel.surprise = json[0]["faceAttributes"]["emotion"]["surprise"].doubleValue
}
// func updateUserData (json: JSON) {
// self.userDataModel.age = json[0]["faceAttributes"]["age"].intValue
// self.userDataModel.gender = json[0]["faceAttributes"]["gender"].stringValue
// self.userDataModel.neutral = json[0]["faceAttributes"]["emotion"]["neutral"].doubleValue
// self.userDataModel.happiness = json[0]["faceAttributes"]["emotion"]["happiness"].doubleValue
// self.userDataModel.anger = json[0]["faceAttributes"]["emotion"]["anger"].doubleValue
// self.userDataModel.disgust = json[0]["faceAttributes"]["emotion"]["disgust"].doubleValue
// self.userDataModel.fear = json[0]["faceAttributes"]["emotion"]["fear"].doubleValue
// self.userDataModel.sadness = json[0]["faceAttributes"]["emotion"]["sadness"].doubleValue
// self.userDataModel.contempt = json[0]["faceAttributes"]["emotion"]["contempt"].doubleValue
// self.userDataModel.surprise = json[0]["faceAttributes"]["emotion"]["surprise"].doubleValue
// }

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "toData") {
Expand Down
22 changes: 22 additions & 0 deletions VisualEyes/Extensions/StorageReference+Post.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// StorageReference.swift
// VisualEyes
//
// Created by Alex Zhang on 2019-02-10.
// Copyright © 2019 Alex Zhang. All rights reserved.
//

import Foundation
import FirebaseStorage

// generate a new location for each new post image that is created by the current ISO timestamp.
extension StorageReference {
static let dateFormatter = ISO8601DateFormatter()

static func newPostImageReference() -> StorageReference {
let uid = User.current.uid
let timestamp = dateFormatter.string(from: Date())

return Storage.storage().reference().child("images/posts/\(uid)/\(timestamp).jpg")
}
}
20 changes: 20 additions & 0 deletions VisualEyes/Extensions/UIImage+Size.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// UIImage+Size.swift
// VisualEyes
//
// Created by Alex Zhang on 2019-02-10.
// Copyright © 2019 Alex Zhang. All rights reserved.
//
import UIKit

extension UIImage {

//aspect height calculated base on the width and height of the device
//currently ipad pro 11
var aspectHeight: CGFloat {
let heightRatio = size.height / 1112
let widthRatio = size.width / 834
let aspectRatio = fmax(heightRatio, widthRatio)
return size.height / aspectRatio
}
}
49 changes: 45 additions & 4 deletions VisualEyes/Model/UserData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import Foundation
import UIKit

class UserData {

//image of user
let imageURL: String
let imageHeight: CGFloat
var imageURL: String
var imageHeight: CGFloat

//information gathering date
let creationDate: Date
var creationDate: Date

//emotion data
var fear : Double
Expand All @@ -32,9 +33,27 @@ class UserData {
var gender: String
var age : Int

var dictValue: [String : Any] {
let createdAgo = creationDate.timeIntervalSince1970

return ["image_url" : imageURL,
"image_height" : imageHeight,
"created_at" : createdAgo,
"fear" : fear,
"happiness": happiness,
"contempt" : contempt,
"disgust" : disgust,
"surprise" : surprise,
"sadness" : sadness,
"anger" : anger,
"neutral" : neutral,
"smile" : smile,
"gender" : gender,
"age" : age]
}

init() {

imageURL = ""
imageHeight = CGFloat()
creationDate = Date()
Expand All @@ -51,4 +70,26 @@ class UserData {
age = 0
}



init(imageURL: String, imageHeight: CGFloat, date: Date, fear: Double, happiness: Double, contempt: Double, disgust: Double, surprise: Double, sadness: Double, anger: Double, neutral: Double, smile: Double, gender: String, age: Int) {

self.imageURL = imageURL
self.imageHeight = CGFloat()
self.creationDate = Date()

self.fear = 0.0
self.happiness = 0.0
self.contempt = 0.0
self.disgust = 0.0
self.surprise = 0.0
self.sadness = 0.0
self.anger = 0.0
self.neutral = 0.0
self.smile = 0.0
self.gender = ""
self.age = 0
}


}
51 changes: 51 additions & 0 deletions VisualEyes/Services/AzureCognitiveService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// AzureCognitiveService.swift
// VisualEyes
//
// Created by Alex Zhang on 2019-02-10.
// Copyright © 2019 Alex Zhang. All rights reserved.
//
// class for sending or receving data from / to Microsoft Azure Cognitive Service API

import Foundation
import Alamofire
import SwiftyJSON

class AzureCognitiveService {

//let azureURL: String = Constants.Azure.AZUREURL
//let azureSubscriptionKey: String = Constants.Azure.SUBSCRIPTIONKEY


static func azureFaceAnalysis (facePicsUrl: URL?, completion: @escaping (JSON?) -> Void) {
let headers: HTTPHeaders = [
"Content-Type" : "application/json",
"Ocp-Apim-Subscription-Key": Constants.Azure.SUBSCRIPTIONKEY,
]
print(facePicsUrl?.absoluteString)
//some parameters included in Constants.Azure.AZUREURL
let parameters: Parameters = [
// "returnFaceId":true,
// "returnFaceLandmarks": false,
// "returnFaceAttributes": "age, gender, emotion, hair, makeup, occlusion, accessories, blur",
"url" : facePicsUrl?.absoluteString
]

Alamofire.request(Constants.Azure.AZUREURL, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
if response.result.isSuccess {
print("successfully get JSON data!")
let jso: JSON = JSON(response.result.value!)
//json from azure is returned!
return completion(jso)

//self.updateUserData(json: jso)
}else{
print("fail to get JSON response!")
return completion(nil)
//DispatchQueue.main.async {
// self.navigationItem.title = "Fail to get image infomation"
//}
}
}
}
}
57 changes: 55 additions & 2 deletions VisualEyes/Services/UploadService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ import Foundation
import UIKit
import FirebaseStorage
import FirebaseDatabase
import SwiftyJSON

struct UploadService {



static func create(for image: UIImage, completion: @escaping (URL?) -> Void) {
let imageRef = Storage.storage().reference().child("test_image.jpg")
//generate a unique imageRef for every uploads based on the UID and current time
let imageRef = StorageReference.newPostImageReference()
StorageService.uploadImage(image, at: imageRef) { (downloadURL) in
guard let downloadURL = downloadURL else {
return completion(nil)
Expand All @@ -23,7 +28,55 @@ struct UploadService {

//print("image url: \(urlString)")
print("successfully returned downloadURL in Upload Service")
return completion(downloadURL)

AzureCognitiveService.azureFaceAnalysis(facePicsUrl: downloadURL, completion: { json in

if let jso = json {
//print out the returned json for testing
print("==============json data in Upload service =======")
print(jso)
let userDataModel = UserData()
userDataModel.age = jso[0]["faceAttributes"]["age"].intValue
userDataModel.gender = jso[0]["faceAttributes"]["gender"].stringValue
userDataModel.neutral = jso[0]["faceAttributes"]["emotion"]["neutral"].doubleValue
userDataModel.happiness = jso[0]["faceAttributes"]["emotion"]["happiness"].doubleValue
userDataModel.anger = jso[0]["faceAttributes"]["emotion"]["anger"].doubleValue
userDataModel.disgust = jso[0]["faceAttributes"]["emotion"]["disgust"].doubleValue
userDataModel.fear = jso[0]["faceAttributes"]["emotion"]["fear"].doubleValue
userDataModel.sadness = jso[0]["faceAttributes"]["emotion"]["sadness"].doubleValue
userDataModel.contempt = jso[0]["faceAttributes"]["emotion"]["contempt"].doubleValue
userDataModel.surprise = jso[0]["faceAttributes"]["emotion"]["surprise"].doubleValue
print("==============json data in Upload service =======")
print("gender: \(userDataModel.gender)")

let urlString = downloadURL.absoluteString
//calculate the aspect height base on the physical size of the device
let aspectHeight = image.aspectHeight
create(forURLString:urlString, aspectHeight: aspectHeight, userDataModel: userDataModel)

return completion(downloadURL)
}else{
print("fail to get json data from Azure")
return completion(nil)
}
})
}
}

private static func create(forURLString urlString: String, aspectHeight: CGFloat, userDataModel: UserData) {
// find the current user
let currentUser = User.current
// get the userdate
let userData = userDataModel
// add image url to userData
userData.imageURL = urlString
// add image height to the image for future display
userData.imageHeight = aspectHeight
// transform an object to json format
let dict = userData.dictValue
//childByAutoId generates a new child location using a unique key and returns a FIRDatabaseReference to it. This is useful when the children of a Firebase Database location represent a list of items.
let postRef = Database.database().reference().child("Analysis").child(currentUser.uid).childByAutoId()

postRef.updateChildValues(dict)
}
}

0 comments on commit 0ea805d

Please sign in to comment.