前言
之前做Easy AR的云识别功能,里面有一个上传手机相册的图片到云识别图库的功能,我当时在网上没找到相关的方法,EasyAR官方文档也没找到解决方案,后面自己结合文档加自己的推测,最终使用Http协议上传成功了,所以现在想把这个过程记录下来,也许对别人会有帮助。
开始制作
使用Unity 2019.2.3f1版本和Easy ARSense_3.0.1-final_Basic 版本的SDK。
一、 导入EasyAR SDK
二、注册Easy AR账号进入开发者中心,SDK授权和云识别管理创建图库,这里略过了,不明白的下方留言。
三、授权以后填写key
四、新建场景,场景信息如下,添加上传脚本,填写秘钥和上传的url地址等。
附上代码
// ImageInfo里面包含需要上传的图片的信息和一些方法
public class ImageInfo
{
public string AppKey;
public string Image;
public string Meta;
public string Name;
public string Size;
public string Timestamp;
public string Type;
public string Signature;
public string Secrect;
private string url;
public ImageInfo(string appKey, string secrect, string imagePath, string imageName, string imageSize, string url)
{
this.AppKey = appKey;
this.Image = ImageToBase64(imagePath);
this.Meta = ImageToBase64(imagePath);
this.Name = imageName;
this.Size = imageSize;
this.Timestamp = ConvertDateTimeToInt(DateTime.Now).ToString();
this.Type = "ImageTarget";
this.Secrect = secrect;
this.url = url;
string tempStr = "appKey" + appKey + "image" + Image + "meta" + Meta + "name" + Name + "size" + imageSize + "timestamp" + Timestamp + "type" + Type + secrect;
this.Signature = GetSHA256hash(tempStr);
}
/// <summary>
/// Determine if similar images already exist on the cloud severs
/// </summary>
/// <returns></returns>
public string DoesTheImageExist()
{
JsonData jsonData = new JsonData();
jsonData["appKey"] = AppKey;
jsonData["image"] = Image;
jsonData["timestamp"] = Timestamp;
string str = "appKey" + jsonData["appKey"] + "image" + jsonData["image"] + "timestamp" + jsonData["timestamp"] + Secrect;
jsonData["signature"] = GetSHA256hash(str);
JsonData re = JsonMapper.ToObject<JsonData>(UpLoadCloudManager._SInstance.DoPost(url + "/similar", jsonData.ToJson()));
if (string.IsNullOrEmpty(re["result"]["results"].ToJson()))
{
return "";
}
else
{
return re["result"]["results"][0]["targetId"].ToJson();
}
}
/// <summary>
/// Convert the image to Base64
/// </summary>
/// <param name="imagePath">Picture path</param>
/// <returns></returns>
private string ImageToBase64(string imagePath)
{
try
{
FileStream fs = new System.IO.FileStream(imagePath, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int)fs.Length);
string base64String = Convert.ToBase64String(buffer);
return base64String;
}
catch (Exception e)
{
return "";
}
}
/// <summary>
/// Converting strings to SHA256 format
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public string GetSHA256hash(string input)
{
byte[] clearBytes = Encoding.UTF8.GetBytes(input);
SHA256 sha256 = new SHA256Managed();
sha256.ComputeHash(clearBytes);
byte[] hashedBytes = sha256.Hash;
sha256.Clear();
string output = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
return output;
}
/// <summary>
/// Converting date format to timestamp
/// </summary>
/// <param name="time">system time</param>
/// <returns></returns>
private long ConvertDateTimeToInt(System.DateTime time)
{
System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
long t = (time.Ticks - startTime.Ticks) / 10000;
return t;
}
/// <summary>
/// Change picture information into JSON format
/// </summary>
/// <returns></returns>
public string ConvertToJson()
{
JsonData jsonData = new JsonData();
jsonData["appKey"] = AppKey;
jsonData["image"] = Image;
jsonData["meta"] = Meta;
jsonData["name"] = Name;
jsonData["size"] = Size;
jsonData["timestamp"] = Timestamp;
jsonData["type"] = Type;
jsonData["signature"] = Signature;
return jsonData.ToJson();
}
}
// UpLoadCloudManager主要上传的方法
using LitJson;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using UnityEngine;
using UnityEngine.Events;
public class UpLoadCloudManager : MonoBehaviour
{
public static UpLoadCloudManager _SInstance;
public string CloudKey;
public string CloudSecrect;
public string CloudSeverUrl;
[HideInInspector]
public string TargetId = "";
private UpLoadCloudManager() {
}
private ImageInfo imageInfo = null;
private void Awake()
{
_SInstance = this;
}
private void Start()
{
}
/// <summary>
/// Upload pictures to cloud servers
/// </summary>
/// <param name="imagePath"> The path of uploading pictures </param>
public void UpLoadToCloud(string imagePath)
{
if (File.Exists(imagePath))
{
imageInfo = new ImageInfo(CloudKey, CloudSecrect, imagePath, DateTime.Now.ToString(), 20.ToString(), CloudSeverUrl);
Thread thread = new Thread(UpLoadCloud);
thread.Start();
}
else
{
Debug.LogError("File not exist");
}
}
/// <summary>
/// Send images to the cloud
/// </summary>
/// <param name="json"> required parameter </param>
/// <returns></returns>
public string DoPost(string url, string jsonStr)
{
string _url = url;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url);
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-8";
byte[] byteData = Encoding.UTF8.GetBytes(jsonStr);
int length = byteData.Length;
request.ContentLength = length;
Stream writer = request.GetRequestStream();
writer.Write(byteData, 0, length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
return new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")).ReadToEnd();
}
private void UpLoadCloud()
{
string targetId = imageInfo.DoesTheImageExist();
if (targetId == "")
{
JsonData re = JsonMapper.ToObject<JsonData>(DoPost(CloudSeverUrl + "/targets", imageInfo.ConvertToJson()));
this.TargetId = (string)re["result"]["targetId"];
}
else
{
this.TargetId = targetId;
}
}
}
添加选择电脑上图片的功能
附上代码
// OpenFileName
using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
public int structSize = 0;
public IntPtr dlgOwner = IntPtr.Zero;
public IntPtr instance = IntPtr.Zero;
public String filter = null;
public String customFilter = null;
public int maxCustFilter = 0;
public int filterIndex = 0;
public String file = null;
public int maxFile = 0;
public String fileTitle = null;
public int maxFileTitle = 0;
public String initialDir = null;
public String title = null;
public int flags = 0;
public short fileOffset = 0;
public short fileExtension = 0;
public String defExt = null;
public IntPtr custData = IntPtr.Zero;
public IntPtr hook = IntPtr.Zero;
public String templateName = null;
public IntPtr reservedPtr = IntPtr.Zero;
public int reservedInt = 0;
public int flagsEx = 0;
}
public class LocalDialog
{
//链接指定系统函数 打开文件对话框
[DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
public static bool GetOFN([In, Out] OpenFileName ofn)
{
return GetOpenFileName(ofn);
}
//链接指定系统函数 另存为对话框
[DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
public static extern bool GetSaveFileName([In, Out] OpenFileName ofn);
public static bool GetSFN([In, Out] OpenFileName ofn)
{
return GetSaveFileName(ofn);
}
}
// UIManager
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class UIManager : MonoBehaviour
{
public void OpenFile() {
OpenFileName openFileName = new OpenFileName();
openFileName.structSize = Marshal.SizeOf(openFileName);
openFileName.filter = "\0*.png\0*.jpg";
openFileName.file = new string(new char[256]);
openFileName.maxFile = openFileName.file.Length;
openFileName.fileTitle = new string(new char[64]);
openFileName.maxFileTitle = openFileName.fileTitle.Length;
openFileName.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
openFileName.title = "窗口标题";
openFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;
if (LocalDialog.GetOpenFileName(openFileName))
{
UpLoadCloudManager._SInstance.UpLoadToCloud(openFileName.file);
}
}
}
总结
上面是大致的一个开发流程,只是简单的实现功能。
工程的链接:https://download.csdn.net/download/qq_33547099/12080266