How do you add data to Firestore without over-writing previous data for the same key? For example, I want to add a document called "Player 1" to the Collections "Trajectory Log." I want to keep track of all the positions for Player 1 throughout one game into a single doc. In other words, how do you append data to a Firestore document?
This is the code I have for writing the data to Firestore. How do I make sure that the "data" is not over-written every time this code runs for the same user? Any help in how to implement this would be appreciated:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Firebase.Firestore;
using System.Threading.Tasks;
using UnityEngine.UI;
using System.Linq;
using System.Threading;
using Firebase.Auth;
public class TrajectoryToFirebase : MonoBehaviour
{
protected bool operationInProgress;
protected Task previousTask;
protected CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
// name of the collection container that documents get stored into
protected string collectionPath = "Trajectory Log";
protected string documentId = "";
public float samplingRate = 1f;
private System.DateTime dt;
private Vector3 lastpos = Vector3.zero;
private Quaternion lastrot = Quaternion.identity;
//public GameStats gameStats;
public Text text;
//Boilerplate taskmanagement code made by the Firebase People
////////////////////////////////////////////////////////////////////////////
class WaitForTaskCompletion : CustomYieldInstruction
{
Task task;
TrajectoryToFirebase dbManager;
protected CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
// Create an enumerator that waits for the specified task to complete.
public WaitForTaskCompletion(TrajectoryToFirebase dbManager, Task task)
{
dbManager.previousTask = task;
dbManager.operationInProgress = true;
this.dbManager = dbManager;
this.task = task;
}
// Wait for the task to complete.
public override bool keepWaiting
{
get
{
if (task.IsCompleted)
{
dbManager.operationInProgress = false;
dbManager.cancellationTokenSource = new CancellationTokenSource();
if (task.IsFaulted)
{
string s = task.Exception.ToString();
Debug.Log(s);
}
return false;
}
return true;
}
}
}
////////////////////////////////////////////////////////////////////////////
//Get the instance of the Firestore database
protected FirebaseFirestore db
{
get
{
return FirebaseFirestore.DefaultInstance;
}
}
private CollectionReference GetCollectionReference()
{
return db.Collection(collectionPath);
}
//Gets the reference to the docuement in Firstore
//Here I am just setting the document manually to the userID of the sign in user
private DocumentReference GetDocumentReference()
{
//documentId = FirebaseAuth.DefaultInstance.CurrentUser.UserId;
documentId = "User 1";
return GetCollectionReference().Document(documentId);
}
// Need function here that sends log data to firestore
// make this so that it checks to see if the document is null, and if it is not, it appends to the previous entry
// Firebase transaction?
public void TrackTrajectory()
{
Debug.Log("Trajectory Tracker Called");
if (transform.position != lastpos || transform.rotation != lastrot)
{
var data = new Dictionary<string, object>
{
{"Time", System.Math.Round(Time.time, 2)},
{"Pos X", System.Math.Round(transform.position.x, 3)},
{"Pos Y", System.Math.Round(transform.position.y, 3)},
{"Pos Z", System.Math.Round(transform.position.z, 3)},
{"Rot X", System.Math.Round(transform.rotation.x, 3)},
{"Rot Y", System.Math.Round(transform.rotation.y, 3)},
{"Rot Z", System.Math.Round(transform.rotation.z, 3)},
};
StartCoroutine(WriteDoc(GetDocumentReference(), data));
Debug.Log("I recorded trajectory data");
// append here? firestore transaction?
lastpos = transform.position;
lastrot = transform.rotation;
}
}
// starts "timer" to start recording position and orientation?
public void Start()
{
dt = System.DateTime.Now;
Debug.Log(dt.ToString("yyyy-MM-dd-H-mm-ss"));
InvokeRepeating("TrackTrajectory", 0f, 1f / samplingRate);
}
// *** what does this do?
public void readDataButton()
{
StartCoroutine(ReadDoc(GetDocumentReference()));
}
private static string DictToString(IDictionary<string, object> d)
{
return "{ " + d
.Select(kv => "(" + kv.Key + ", " + kv.Value + ")")
.Aggregate("", (current, next) => current + next + ", ")
+ "}";
}
//Writes the data
private IEnumerator WriteDoc(DocumentReference doc, IDictionary<string, object> data)
{
Task setTask = doc.SetAsync(data);
yield return new WaitForTaskCompletion(this, setTask);
if (!(setTask.IsFaulted || setTask.IsCanceled))
{
Debug.Log("Data written");
}
else
{
Debug.Log("Error");
}
}
private IEnumerator ReadDoc(DocumentReference doc)
{
Task<DocumentSnapshot> getTask = doc.GetSnapshotAsync();
yield return new WaitForTaskCompletion(this, getTask);
if (!(getTask.IsFaulted || getTask.IsCanceled))
{
DocumentSnapshot snap = getTask.Result;
IDictionary<string, object> resultData = snap.ToDictionary();
text.text = DictToString(resultData);
Debug.Log("Data read");
}
else
{
text.text = "Error";
}
}
}
You have to use UpdateAsync() instead of SetAsync()
You can read here the Firebase documentation on updates
Related
Here is the code i am currently using to send data and receive data:
all the plugins have been downloaded to the latest version.we are trying to use firebase real time database is send and receive scores that have to be implemented in the game.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Firebase.Auth;
using Firebase;
using Google;
using Firebase.Database;
using System.Linq;
public class LBnew : MonoBehaviour
{
private GoogleSignInConfiguration configuration;
private FirebaseAuth auth;
public string userID;
private DatabaseReference reference;
public string webClientId = " <your client id>";
private void Awake()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
var dependencyStatus = task.Result;
if (dependencyStatus == DependencyStatus.Available)
{
FirebaseApp app;
app = FirebaseApp.DefaultInstance;
Initialize();
}
else
{
Debug.Log(" not resolve firebase dependencies");
}
});
}
void Initialize()
{
configuration = new GoogleSignInConfiguration { WebClientId = webClientId, RequestEmail = true, RequestIdToken = true };
auth = FirebaseAuth.DefaultInstance;
userID = FirebaseAuth.DefaultInstance.CurrentUser.DisplayName;
reference = FirebaseDatabase.DefaultInstance.RootReference;
Debug.Log(" initiallized");
sendscore();
}
public void sendscore()
{
StartCoroutine(UpdateScore(10));
}
private IEnumerator UpdateScore(int _score)
{
Debug.Log(" Your userID " + userID);
//Set the currently logged in user score
var DBTask = reference.Child("user").Child(userID).Child("score").SetValueAsync(_score);
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register score task with {DBTask.Exception}");
// Debug.Log(" failed to reg score ");
}
else
{
Debug.Log(" success to reg score ");
}
StartCoroutine(LoadScoreboardData());
}
private IEnumerator LoadScoreboardData()
{
var DBTask = reference.Child("users").OrderByChild("score").GetValueAsync();
yield return new WaitUntil(predicate: () => DBTask.IsCompleted);
if (DBTask.Exception != null)
{
Debug.LogWarning(message: $" load leaderboard task with {DBTask.Exception}");
Debug.Log(" srinu failed to load leaderScoreboardData ");
}
else
{
//Data has been retrieved
DataSnapshot snapshot = DBTask.Result;
//Destroy any existing scoreboard elements
//foreach (Transform child in scoreboardContent.transform)
//{
// Destroy(child.gameObject);
//}
//Loop through every users UID
//foreach (DataSnapshot childSnapshot in snapshot.Children)
//{
foreach (DataSnapshot childSnapshot in snapshot.Children.Reverse<DataSnapshot>())
{
// Instantiate new scoreboard elements
// GameObject scoreboardElement = Instantiate(scoreElement, scoreboardContent);
// scoreboardElement.GetComponent<LbAllList>().NewDataElement(username, Schoolname, score);
Debug.Log(" leaderScoreboardData " + childSnapshot.Child("score"));
}
//}
}
}
}
we are using unity 2020.1.17f as the version of unity
Any help would be appreciated thanks
So, I am using Firebase Realtime Database for fetching a user values. I first check using DataSnapShot if a certain user exists or not. And then, if it exists, I call SceneManager.LoadScene (index). All the logs are correctly shown in the console. But SceneManager.LoadScene method won't work.
Here is the code block:
void authWithFirebaseFacebook(string accessToken)
{
Firebase.Auth.Credential credential =
Firebase.Auth.FacebookAuthProvider.GetCredential(accessToken);
auth.SignInWithCredentialAsync(credential).ContinueWith(task => {
if (task.IsCanceled) {
return;
}
if (task.IsFaulted) {
return;
}
loginSuccesful();
});
}
void loginSuccesful()
{
// SOME CODE HERE THEN (ONLY ASSIGNMENTS, NO TASK OR ANYTHING)
SaveUser();
}
public async void SaveUser()
{
DataSnapshot snapShot = await playerExistsAlready();
if (snapShot.Exists)
{
Debug.Log("Continue Fetching the details for user");
Debug.Log("Values fetched for new player...:" + snapShot.GetValue(true));
Debug.Log("Convert JSON to Object");
string json = snapShot.GetValue(true).ToString();
PlayerData newPlayer = JsonUtility.FromJson<PlayerData>(json);
UserManager.instance.player = newPlayer;
Debug.Log("User Creaated!");
Debug.Log("New Values are:" + newPlayer.DisplayName + " .." + newPlayer.PhotoURL) ;
Debug.Log("Load Main Menu Scene Now...");
SceneManager.LoadScene(1);
}
else
{
saveNewUser();
}
}
async Task<DataSnapshot> playerExistsAlready()
{
DataSnapshot dataSnapShot = await _database.GetReference("users/" + UserManager.instance.currentUserID ).GetValueAsync();
return dataSnapShot;
}
The output:
Continue Fetching the details for user
Values fetched for new player...: (player data here)
Convert JSON to Object
User Created!
New Values are : (values here)
Load Main Menu Scene Now...
The issue is that your code is running on a separate background thread. Your main thread will not "know" that anything was called by a thread. In general most of the Unity API can not be called from a thread .. and it makes no sense to do.
Firebase specifically for that provides an extension method ContinueWithOnMainThread which does exactly that: Makes sure that the callback is executed in the Unity main thread.
void authWithFirebaseFacebook(string accessToken)
{
Firebase.Auth.Credential credential = Firebase.Auth.FacebookAuthProvider.GetCredential(accessToken);
auth.SignInWithCredentialAsync(credential).ContinueWithOnMainThread(task =>
{
if (task.IsCanceled || task.IsFaulted)
{
return;
}
loginSuccesful();
});
}
void loginSuccesful()
{
// SOME CODE HERE THEN (ONLY ASSIGNMENTS, NO TASK OR ANYTHING)
SaveUser();
}
public void SaveUser()
{
_database.GetReference("users/" + UserManager.instance.currentUserID ).GetValueAsync().ContinueWithOnMainThread(task =>
{
if (task.IsCanceled || task.IsFaulted)
{
return;
}
var snapShot = task.Result;
if (snapShot.Exists)
{
Debug.Log("Continue Fetching the details for user");
Debug.Log("Values fetched for new player...:" + snapShot.GetValue(true));
Debug.Log("Convert JSON to Object");
string json = snapShot.GetValue(true).ToString();
PlayerData newPlayer = JsonUtility.FromJson<PlayerData>(json);
UserManager.instance.player = newPlayer;
Debug.Log("User Creaated!");
Debug.Log("New Values are:" + newPlayer.DisplayName + " .." + newPlayer.PhotoURL) ;
Debug.Log("Load Main Menu Scene Now...");
SceneManager.LoadScene(1);
}
else
{
saveNewUser();
}
}
}
Alternatively an often used pattern is a so called "main thread dispatcher" (I know there is an asset for that but this one requires a lot of refactoring actually ;) ).
But you can easily create one yourself. Usually it looks somewhat like
public class YourClass : MonoBehaviour
{
private ConcurrentQueue<Action> mainThreadActions = new ConcurrentQueue<Action>();
private void Update()
{
while(mainThreadActions.Count > 0 && mainThreadActions.TryDequeue(out var action))
{
action?.Invoke();
}
}
}
so any thread can just add an action to be executed on the main thread via e.g.
void authWithFirebaseFacebook(string accessToken)
{
Firebase.Auth.Credential credential = Firebase.Auth.FacebookAuthProvider.GetCredential(accessToken);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
if (task.IsCanceled || task.IsFaulted)
{
return;
}
// either as method call
mainThreadActions.Enqueue(loginSuccesful);
});
}
void loginSuccesful()
{
// SOME CODE HERE THEN (ONLY ASSIGNMENTS, NO TASK OR ANYTHING)
SaveUser();
}
public void SaveUser()
{
// or as lambda exopression
database.GetReference("users/" + UserManager.instance.currentUserID ).GetValueAsync().ContinueWith(task =>
{
mainThreadActions.Enqueue(() =>
{
if (task.IsCanceled || task.IsFaulted)
{
return;
}
var snapShot = task.Result;
if (snapShot.Exists)
{
Debug.Log("Continue Fetching the details for user");
Debug.Log("Values fetched for new player...:" + snapShot.GetValue(true));
Debug.Log("Convert JSON to Object");
string json = snapShot.GetValue(true).ToString();
PlayerData newPlayer = JsonUtility.FromJson<PlayerData>(json);
UserManager.instance.player = newPlayer;
Debug.Log("User Creaated!");
Debug.Log("New Values are:" + newPlayer.DisplayName + " .." + newPlayer.PhotoURL) ;
Debug.Log("Load Main Menu Scene Now...");
SceneManager.LoadScene(1);
}
else
{
saveNewUser();
}
})
});
}
So the problem was the method was not being executed on Main Thread. I guess Unity Methods like SceneManager.Load() etc are only called on a Main Thread.
So, I used a class named UnityMainThreadDispatcher
And then I wrote
IEnumerator loadMainMenuScene()
{
SceneManager.LoadScene(1);
yield return null;
}
And called
UnityMainThreadDispatcher.Instance().Enqueue(loadMainMenuScene());
instead of
SceneManager.LoadScene(1);
Sorry for my bad english. The application reads data from the accelerometer of the smartphone. He has a server in which when a smartphone is connected, a pair of id-data about the position in space is created. At the moment, data from all users come to the server. The task is to do the opposite: each time a user connects, a separate space is created that receives data from only one id.
Server code:
var express = require('express');
var compression = require('compression');
var http = require('http');
var path = require('path');
var socketIO = require('socket.io');
const port = process.env.PORT || 5000;
var cors = require('cors');
var app = express();
var server = http.Server(app);
var io = socketIO(server);
app.use(cors()) ;// Use this after the variable declaration
app.set('port', port);
app.use(compression());
app.use(express.static(__dirname + '/'));
app.use('/static', express.static(__dirname + '/static'));
// Routing
app.get('/', function (request, response) {
response.sendFile(path.join(__dirname, 'view.html'));
console.log(Object.keys(player_move).length);
if (Object.keys(player_move).length >= 1){
let data = {
id: socketId,
x: player_move[socketId].x,
z: player_move[socketId].z,
};
response.send(data);
console.log('connected');
}else{
response.send("no");
console.log('not connected');
};
});
app.use(express.static(__dirname + '/client/'));
// Routing
app.get('/view', function (request, response) {
response.sendFile(path.join(__dirname, '/client/index.html'));
});
server.listen(port, function () {
console.log('Старт сервера по адресу localhost:' + port);
console.log('Старт просмотра по адресу localhost: ' + port + ' /view');
});
var player_move = {};
var socketId;
io.on('connection', function (socket) {
socket.on('new player', function () {
console.log('new player');
socket.emit('ok');
});
socket.on('disconnect', function () {
});
socket.on('movement', function () {
console.log('movement');
console.log('player_move', player_move);
if (player_move[socketId]) {
let data = {
id: socketId,
x: player_move[socketId].x,
z: player_move[socketId].z,
};
socket.emit('ok', data);
}
});
socket.on('phone_data', function (data) {
console.log('phone_date', data);
socketId = socket.id;
player_move[socket.id] = {
x: data.x,
z: data.z
};
});
// GET method route
app.get('/', function (req, res) {
res.send('Contact');
console.log("est kontakt");
});
});
socket code:
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
using UnityEngine.Networking;
public class SocketController : MonoBehaviour
{
[SerializeField]
PlayerController player;
// Start is called before the first frame update
void Start()
{
StartCoroutine(GetRequest("http://plantgo.ru:5000"));
}
private void Awake()
{
//socket.url = "ws://127.0.0.1:5000/socket.io/?EIO=4&transport=websocket";
}
// Update is called once per frame
void Update()
{
}
//private IEnumerator Connector()
//{
// while (true)
// {
// socket.Emit("movement");
// yield return new WaitForSeconds(0.10f);
// }
// wait 1 seconds and continue
// }
class PlayerInfo
{
public string id;
public string x;
public string z;
}
IEnumerator GetRequest(string uri)
{
while (true)
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
{
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
string[] pages = uri.Split('/');
int page = pages.Length - 1;
if (webRequest.isNetworkError)
{
Debug.Log(pages[page] + ": Error: " + webRequest.error);
}
else
{
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
if (webRequest.downloadHandler.text == "no")
{
continue;
}
else
{
PlayerInfo playerInfo = (PlayerInfo)JsonUtility.FromJson<PlayerInfo>(webRequest.downloadHandler.text);
Debug.Log(playerInfo);
player.PlayerMove(float.Parse(playerInfo.x, CultureInfo.InvariantCulture), float.Parse(playerInfo.z, CultureInfo.InvariantCulture));
}
}
}
//yield return new WaitForSeconds(0.1f);
}
}
}
when I start the server, several users can control the character at once, since they are in the same game space, it is necessary for each to have its own.
I am testing on a project on how to read text from objects and pictures using google cloud vision.Using mobile camera(iphone,ipad preferably or android phones)I would like to get the required text.Samsung bixby application is an example.After some reading I found out about OpenCV for unity and Google cloud vision.OpenCV for unity is around 95$.For testing I cannot use it.So I took the other option.
I downloaded this project. Github project .I created a google cloud vision api key and added to the inspector.I have set the option feature type to text detection.When I took a IOS build, the camera was ON but looks inverted.Nothing was happening.I see a missing script in the inspector.How to detect the text using device camera?
Unity Cloud Vision git repo contains the code for Face Detection. It is not suitable for OCR or Text Detection.
So, I have created a code for perform text detection from images using vision OCR api in Unity3D.
You can try to use the following script to detect the text from an image in Unity3D.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using SimpleJSON;
public class WebCamTextureToCloudVision : MonoBehaviour {
public string url = "https://vision.googleapis.com/v1/images:annotate?key=";
public string apiKey = ""; //Put your google cloud vision api key here
public float captureIntervalSeconds = 5.0f;
public int requestedWidth = 640;
public int requestedHeight = 480;
public FeatureType featureType = FeatureType.TEXT_DETECTION;
public int maxResults = 10;
public GameObject resPanel;
public Text responseText, responseArray;
WebCamTexture webcamTexture;
Texture2D texture2D;
Dictionary<string, string> headers;
[System.Serializable]
public class AnnotateImageRequests {
public List<AnnotateImageRequest> requests;
}
[System.Serializable]
public class AnnotateImageRequest {
public Image image;
public List<Feature> features;
}
[System.Serializable]
public class Image {
public string content;
}
[System.Serializable]
public class Feature {
public string type;
public int maxResults;
}
public enum FeatureType {
TYPE_UNSPECIFIED,
FACE_DETECTION,
LANDMARK_DETECTION,
LOGO_DETECTION,
LABEL_DETECTION,
TEXT_DETECTION,
SAFE_SEARCH_DETECTION,
IMAGE_PROPERTIES
}
// Use this for initialization
void Start () {
headers = new Dictionary<string, string>();
headers.Add("Content-Type", "application/json; charset=UTF-8");
if (apiKey == null || apiKey == "")
Debug.LogError("No API key. Please set your API key into the \"Web Cam Texture To Cloud Vision(Script)\" component.");
WebCamDevice[] devices = WebCamTexture.devices;
for (var i = 0; i < devices.Length; i++) {
Debug.Log (devices [i].name);
}
if (devices.Length > 0) {
webcamTexture = new WebCamTexture(devices[0].name, requestedWidth, requestedHeight);
Renderer r = GetComponent<Renderer> ();
if (r != null) {
Material m = r.material;
if (m != null) {
m.mainTexture = webcamTexture;
}
}
webcamTexture.Play();
StartCoroutine("Capture");
}
}
// Update is called once per frame
void Update () {
}
private IEnumerator Capture() {
while (true) {
if (this.apiKey == null)
yield return null;
yield return new WaitForSeconds(captureIntervalSeconds);
Color[] pixels = webcamTexture.GetPixels();
if (pixels.Length == 0)
yield return null;
if (texture2D == null || webcamTexture.width != texture2D.width || webcamTexture.height != texture2D.height) {
texture2D = new Texture2D(webcamTexture.width, webcamTexture.height, TextureFormat.RGBA32, false);
}
texture2D.SetPixels(pixels);
// texture2D.Apply(false); // Not required. Because we do not need to be uploaded it to GPU
byte[] jpg = texture2D.EncodeToJPG();
string base64 = System.Convert.ToBase64String(jpg);
// #if UNITY_WEBGL
// Application.ExternalCall("post", this.gameObject.name, "OnSuccessFromBrowser", "OnErrorFromBrowser", this.url + this.apiKey, base64, this.featureType.ToString(), this.maxResults);
// #else
AnnotateImageRequests requests = new AnnotateImageRequests();
requests.requests = new List<AnnotateImageRequest>();
AnnotateImageRequest request = new AnnotateImageRequest();
request.image = new Image();
request.image.content = base64;
request.features = new List<Feature>();
Feature feature = new Feature();
feature.type = this.featureType.ToString();
feature.maxResults = this.maxResults;
request.features.Add(feature);
requests.requests.Add(request);
string jsonData = JsonUtility.ToJson(requests, false);
if (jsonData != string.Empty) {
string url = this.url + this.apiKey;
byte[] postData = System.Text.Encoding.Default.GetBytes(jsonData);
using(WWW www = new WWW(url, postData, headers)) {
yield return www;
if (string.IsNullOrEmpty(www.error)) {
string responses = www.text.Replace("\n", "").Replace(" ", "");
// Debug.Log(responses);
JSONNode res = JSON.Parse(responses);
string fullText = res["responses"][0]["textAnnotations"][0]["description"].ToString().Trim('"');
if (fullText != ""){
Debug.Log("OCR Response: " + fullText);
resPanel.SetActive(true);
responseText.text = fullText.Replace("\\n", " ");
fullText = fullText.Replace("\\n", ";");
string[] texts = fullText.Split(';');
responseArray.text = "";
for(int i=0;i<texts.Length;i++){
responseArray.text += texts[i];
if(i != texts.Length - 1)
responseArray.text += ", ";
}
}
} else {
Debug.Log("Error: " + www.error);
}
}
}
// #endif
}
}
#if UNITY_WEBGL
void OnSuccessFromBrowser(string jsonString) {
Debug.Log(jsonString);
}
void OnErrorFromBrowser(string jsonString) {
Debug.Log(jsonString);
}
#endif
}
The demo project is available in github. codemaker2015/google-cloud-vision-api-ocr-unity3d-demo
I would like to do facial recognition with the feed of the camera of my computer with Unity and SDK Watson. I looked for some tutorials and demos in the internet and I think finally get it. This is one of my first projects in Unity so I would be so grateful if someone could help me to correct two errors I cannot fix.
I use this code for camera render and capture the image:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CameraRender : MonoBehaviour {
public Image overlay;
public FaceDetector fd;
// Use this for initialization
void Start () {
WebCamTexture backCam = new WebCamTexture();
backCam.Play();
overlay.material.mainTexture = backCam;
}
public void CaptureImage()
{
ScreenCapture.CaptureScreenshot(Application.persistentDataPath + "/screenshot.png");
fd.DetectFaces(Application.persistentDataPath + "/screenshot.png");
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0))
{
CaptureImage();
}
}
}
And this other one for face detection:
using IBM.Watson.DeveloperCloud.Connection;
using IBM.Watson.DeveloperCloud.Logging;
using IBM.Watson.DeveloperCloud.Services.VisualRecognition.v3;
using IBM.Watson.DeveloperCloud.Utilities;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class FaceDetector : MonoBehaviour {
public Text dataOutput;
private VisualRecognition _visualRecognition;
// Use this for initialization
void Start ()
{
Credentials credentials = new Credentials(apiKey: "key", url: "url");
_visualRecognition = new ExampleVisualRecognition(credentials)
{
VersionDate = "2016-05-20"
};
}
public void DetectFaces(string path)
{
// Classify using image url
//if (!_visualRecognition.DetectFaces("<image-url>", OnDetectFaces, OnFail))
// Log.Debug("ExampleVisualRecognition.DetectFaces()", "Detect faces failed!");
// Classify using image path
if (!_visualRecognition.DetectFaces(OnDetectFaces, OnFail, path)) {
Log.Debug("ExampleVisualRecognition.DetectFaces()", "Detect faces failed!");
} else
{
Debug.Log("Calling Watson");
dataOutput.text = "";
}
}
private void OnDetectFaces(DetectedFaces multipleImages, Dictionary<string, object> customData)
{
var data = multipleImages.images[0].faces[0]; //assume 1
dataOutput.text = "Age : " + data.age.min + "-" + data.age.max + " PROBABILITY: " + data.age.score + "\n" + "Gender" + data.gender.gender + " PROBABILITY: " + data.age.score + "\n";
Log.Debug("ExampleVisualRecognition.OnDetectFaces(): Detect faces result: {0}", customData["json"].ToString());
}
private void OnFail(RESTConnector.Error error, Dictionary<string,object> customData)
{
Debug.LogError("ExampleVisualRecognition.OnFail(): Error received: " + error.ToString());
}
// Update is called once per frame
void Update () {
}
}
But I cannot fix this two errors:
NotImplementedException: The requested feature is not implemented. IBM.Watson.DeveloperCloud.Services.VisualRecognition.v3.VisualRecognition.op_Implicit (.ExampleVisualRecognition v) (at Assets/Watson/Scripts/Services/VisualRecognition/v3/VisualRecognition.cs:1444)
FaceDetector.Start () (at Assets/FaceDetector.cs:21)
NullReferenceException: Object reference not set to an instance of an object
FaceDetector.DetectFaces (System.String path) (at Assets/FaceDetector.cs:35)
CameraRender.CaptureImage () (at Assets/CameraRender.cs:20)
CameraRender.Update () (at Assets/CameraRender.cs:27)
Could someone bring some help? Thank you all.
You are instantiating ExampleVisualRecognition when you should be instantiating VisualRecognition. Please see this gist.
private IEnumerator CreateService()
{
// Create tokenOptions
TokenOptions visualRecognitionTokenOptions = new TokenOptions()
{
IamApiKey = visualRecognitionApiKey
};
// Create credentials
Credentials visualRecognitionCredentials = new Credentials(visualRecognitionTokenOptions, visualRecognitionServiceUrl);
// Wait for tokendata
while (!visualRecognitionCredentials.HasIamTokenData())
yield return null;
// Instantiate service
visualRecognition = new VisualRecognition(visualRecognitionCredentials);
// Set version date
visualRecognition.VersionDate = versionDate;
// Classify
visualRecognition.DetectFaces(OnDetectFaces, OnFail, imagePath);
}
private void OnDetectFaces(DetectedFaces response, Dictionary<string, object> customData)
{
// Print response json to console
Log.Debug("ClassifyExample", "{0}", customData["json"].ToString());
// Print gender, age and confidence
Log.Debug("ClassifyExample", "gender: {0}, score: {1}, age: {2} - {3}, score: {4}", response.images[0].faces[0].gender.gender, response.images[0].faces[0].gender.score, response.images[0].faces[0].age.min, response.images[0].faces[0].age.max, response.images[0].faces[0].age.score);
}
// Fail callback
private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
Log.Debug("ClassifyExample", "Failed to classify");
}
}