1. 程式人生 > >Unity 影象識別 接入Face++ 進行 場景識別 和 文字識別

Unity 影象識別 接入Face++ 進行 場景識別 和 文字識別

首先需要去Face++註冊一個賬號:(https://console.faceplusplus.com.cn/login)註冊非常簡單這裡就不講了。建立完我們登入後悔進入如下介面。



接著我們去建立一個應用(也就是建立一個API Key,這個非常重要)如下:


現在我們去找到我們需要的API,找到影象識別中的Detect Scene & Object API (Beta)如圖:


點選 API文件進入當前API介紹和如何使用介面在這裡我們只需要知道如何使用和返回值就行了:如圖(它使用的是post方法)




到這一步準備工作就完成了,下面開啟unity建立場景,這個過程就不講了,如圖:



直接上程式碼:

using UnityEngine;
using System.Collections;
using System.IO;
using LitJson;
using Vuforia;
using UnityEngine.UI;
using System.Text.RegularExpressions;

public class Demo : MonoBehaviour 
{
	public bool ImageOrWord = true;

	public string ImageOrWordURL="";

	//中英互譯
	string CHENUrl = "http://fanyi.youdao.com/openapi.do?keyfrom=UnityFY&key=自己的有道key&type=data&doctype=json&version=1.1&q=";

	//相機/用於截圖使用
	public Camera Cam;

	//按鈕上的文字
	public Text Btn_PaiZhaoText;

	//顯示結果
	public GameObject ShowResult;

	//物體資訊陣列
	public ArrayList ObjArr = new ArrayList();
	public ArrayList ObjArrKXD = new ArrayList();

	//結果顯示時間
	public float myTimer = 2.0f;

	ArrayList TempArr = new ArrayList ();
	bool QueRen = false;
	// Use this for initialization
	void Start () 
	{
		CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
	}
	
	// Update is called once per frame
	void Update () {
		if (myTimer > 0) 
		{
			myTimer = myTimer - Time.deltaTime;
		}
		if (myTimer <= 0) 
		{
			ShowResult.SetActive(false);
		}
	}

	//提交資料進行識別
	IEnumerator SendPost(string _url, WWWForm _wForm)  
	{  
		WWW postData = new WWW(_url, _wForm);  
		yield return postData;  
		if (postData.error != null)  
		{  
			Debug.Log(postData.error);  
			ShowResult.SetActive (true);
			Btn_PaiZhaoText.text = "識別";
			ShowResult.transform.Find ("Text").GetComponent<Text> ().text = "識別失敗!";
            GameObject.Find("DebugText").GetComponent<Text>().text = postData.error;
			myTimer = 2.0f;
		}  
		else  
		{  
			Btn_PaiZhaoText.text = "識別";
			Debug.Log(postData.text); 
			GameObject.Find ("DebugText").GetComponent<Text> ().text = postData.text;
			JsonJieXi (postData.text);
		}  
	}

	public void TestHttpSend()  
	{  
		if (ImageOrWord == true) 
		{
			//識別圖片場景中的物體
			WWWForm form = new WWWForm ();
            form.AddField("api_key", "你自己申請的api_key");
            form.AddField("api_secret", "你自己申請的api_secret"); 
			//form.AddField ("image_url", ImageOrWordURL);
			form.AddField ("image_file", ImageOrWordURL);
			StartCoroutine (SendPost ("https://api-cn.faceplusplus.com/imagepp/beta/detectsceneandobject", form));
		} 
		else
		{
			//識別文字
			WWWForm form = new WWWForm ();
            form.AddField("api_key", "你自己申請的api_key");
            form.AddField("api_secret", "你自己申請的api_secret");  
			form.AddField ("image_url", ImageOrWordURL);
			StartCoroutine (SendPost ("https://api-cn.faceplusplus.com/imagepp/beta/recognizetext", form));
		}     
	}

	void JsonJieXi(string str)
	{
		JsonData jd = JsonMapper.ToObject (str);
		//圖片
		if (QieHuanShiBieMoShiBool == true) 
		{
			Debug.Log ("使用時間(time_used)" + jd ["time_used"].ToString ());
			/*
		if (jd ["scenes"].Count>0) 
		{
			for (int i = 0; i < jd ["scenes"].Count; i++) {
				Debug.Log ("場景資訊陣列-名稱(scenes)" + jd ["scenes"] [i] ["value"].ToString ());
				Debug.Log ("場景資訊陣列-置信度(scenes)" + jd ["scenes"] [i] ["confidence"].ToString ());
				Debug.Log ("");
			}
		} else {
			Debug.Log ("沒有識別出場景");
		}
		*/
			if (jd ["objects"].Count > 0) {
				for (int i = 0; i < jd ["objects"].Count; i++) {
					Debug.Log ("物體資訊陣列-名稱(objects)" + jd ["objects"] [i] ["value"].ToString ());
					Debug.Log ("物體資訊陣列-置信度(objects)" + jd ["objects"] [i] ["confidence"].ToString ());
					Debug.Log ("");
					ObjArr.Add (jd ["objects"] [i] ["value"].ToString ());//物體名稱
					ObjArrKXD.Add (float.Parse (jd ["objects"] [i] ["confidence"].ToString ()));//對應的可信度
				}
				//TempArr.Clear ();
				ShowResultToUser (ObjArr, ObjArrKXD);

			} else {
				Debug.Log ("沒有識別物體");
				ShowResult.SetActive (true);
				ShowResult.transform.Find ("Text").GetComponent<Text> ().text = "我不知道這是什麼呢";
				myTimer = 2.0f;
			}
		}
		//文字
		else 
		{
			Debug.Log (jd ["result"].Count);
			for (int i = 0; i < jd ["result"].Count; i++) 
			{
				for (int j = 0; j < jd ["result"] [i] ["child-objects"].Count; j++)
				{
					Debug.Log (jd ["result"] [i] ["child-objects"][j]["type"].ToString());
					Debug.Log (jd ["result"] [i] ["child-objects"][j]["value"].ToString());
				}
				//Debug.Log ("__________"+jd ["result"] [i] ["child-objects"]["type"].ToString());
				//Debug.Log ("----------"+jd ["result"] [i] ["child-objects"]["value"].ToString());
			}
		}
	}

	/// <summary>
	/// 正則表示式刪除指定的字串
	/// <並且返回一個string型別>
	/// <"value">原字串>
	/// <"delStr">需要去除的字元>
	/// <"b">布林值 如果為真表示去除標點
	/// <@"\d"-表示刪除字串中的所有數字>
	/// <@"[^\d]*"-表示刪除字串中的非數字>
	/// </summary>
	public static string RegexStringManipulation(string value,string delStr,bool b)
	{
		string str;
		Regex re = new Regex (delStr);
		str = re.Replace (value, "");
		if (b == true) //去標點
		{
			str = Regex.Replace (str,@"\w+","");
		}

		return str;
	}

	void ShowResultToUser(ArrayList Arr,ArrayList Arra)
	{

		TempArr = Arra;

		for (int i =0 ;i<Arr.Count;i++) {
			Debug.Log ("Arr = "+Arr[i].ToString()+" 下標:"+i);
		}

		for (int j =0 ;j<Arra.Count;j++) {
			Debug.Log ("Arra = "+Arra[j].ToString()+" 下標:"+j);
		}

		//排序取最大值
		Arra.Sort ();
		float Max =float.Parse( Arra [Arra.Count - 1].ToString());

		Debug.Log ("MAX = "+Max);
		if (Max > 92) {
			QueRen = true;
		} else {
			QueRen = false;
		}
		if (Arra.Count > 1) {
			for (int i = 0; i < TempArr.Count; i++) {
				if (float.Parse (TempArr [i].ToString ()) == Max) {
					Debug.Log (float.Parse (TempArr [i].ToString ()) + "在TempArr陣列中 下標為 " + i);
					if (i > 0) {
						StartCoroutine (FanYi (Arr [i - 1].ToString ()));
					} 
					break;
				}
			}
		} else {
			Debug.Log ("----------------"+Arr [0].ToString ());
			StartCoroutine (FanYi (Arr [0].ToString ()));
		}
	}

	//翻譯
	IEnumerator FanYi(string str)
	{
		WWW www = new WWW (CHENUrl + str);
		yield return www;
		if (www.error != null) 
		{
			Debug.Log (">>>>>>>>>>>>>>"+www.error);
		} else {
			Debug.Log ("++++++++++++++"+www.text);
			FanYiJSONJieXi (www.text);
		}
	}

	/// <summary>
	/// 翻譯xml解析
	/// </summary>
	void FanYiJSONJieXi(string str)
	{
		//Debug.Log (str);
		ShowResult.SetActive (true);
		JsonData jd = JsonMapper.ToObject (str);
		Debug.Log ("翻譯結果:"+jd["translation"][0].ToString ());
		if (QueRen == true) {
			ShowResult.transform.Find ("Text").GetComponent<Text> ().text = "這一定是 " + jd ["translation"] [0].ToString () + " 呢!";
		} else {
			ShowResult.transform.Find ("Text").GetComponent<Text> ().text = "我猜這是 " + jd ["translation"] [0].ToString () + " 呢!";
		}

		myTimer = 2.0f;
	}

	/// <summary>
	/// 拍照按鈕
	/// </summary>
	public void Btn_JieTu()
	{
		Btn_PaiZhaoText.text = "識別中";
		TempArr.Clear ();
		ObjArr.Clear ();
		ObjArrKXD.Clear ();
		CaptureCamera (Cam,new Rect(0,0,Screen.width*0.5f,Screen.height*0.5f));
	}

	/// <summary>
	/// 顯示debug資訊在螢幕上
	/// </summary>
	bool Btn_DebugBool = false;
	public void Btn_Debug()
	{
		if (Btn_DebugBool == true) {
			GameObject.Find ("DebugText").GetComponent<Text> ().enabled = false;
			Btn_DebugBool = false;
		} else {
			GameObject.Find ("DebugText").GetComponent<Text> ().enabled = true;
			Btn_DebugBool = true;
		}
	}

	/// <summary>
	/// 切換識別模式
	/// </summary>
	bool QieHuanShiBieMoShiBool = true;
	public void Btn_QieHuanShiBieMoShi()
	{
		QieHuanShiBieMoShiBool =! QieHuanShiBieMoShiBool;
		Debug.Log ("------"+QieHuanShiBieMoShiBool);

		if (QieHuanShiBieMoShiBool == true) {
			GameObject.Find ("Btn_ImageOrWord").transform.Find ("Text").GetComponent<Text> ().text = "圖片";
		} else {
			GameObject.Find ("Btn_ImageOrWord").transform.Find ("Text").GetComponent<Text> ().text = "文字";
		}
	}

	//截圖並且識別
	void CaptureCamera(Camera camera, Rect rect)   
	{  
		// 建立一個RenderTexture物件  
		RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0);  
		// 臨時設定相關相機的targetTexture為rt, 並手動渲染相關相機  
		camera.targetTexture = rt;  
		camera.Render();  
		//ps: --- 如果這樣加上第二個相機,可以實現只截圖某幾個指定的相機一起看到的影象。  
		//ps: camera2.targetTexture = rt;  
		//ps: camera2.Render();  
		//ps: -------------------------------------------------------------------  
		  
		RenderTexture.active = rt;  
		Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24,false);  
		screenShot.ReadPixels(rect, 0, 0);  
		screenShot.Apply();  

		// 重置相關引數,以使用camera繼續在螢幕上顯示  
		camera.targetTexture = null;  
		RenderTexture.active = null; 
		GameObject.Destroy(rt);  
//		// 最後將這些紋理資料,成一個png圖片檔案  
        byte[] bytes = screenShot.EncodeToPNG();
        string filename = Application.dataPath + "/Screenshot.png";
        System.IO.File.WriteAllBytes(filename, bytes);
        Debug.Log(string.Format("截圖了一張照片: {0}", filename));  


	
		if (QieHuanShiBieMoShiBool == true) 
		{
			Debug.Log ("圖片");
			//識別圖片場景中的物體
			WWWForm form = new WWWForm ();
            		
form.AddField("api_key", "你自己申請的api_key"); form.AddField("api_secret", "你自己申請的api_secret"); form.AddBinaryData ("image_file", screenShot.EncodeToPNG()); StartCoroutine (SendPost ("https://api-cn.faceplusplus.com/imagepp/beta/detectsceneandobject", form)); } else { Debug.Log ("文字"); //識別文字 WWWForm form = new WWWForm ();
form.AddField("api_key", "你自己申請的api_key"); form.AddField("api_secret", "你自己申請的api_secret"); form.AddBinaryData ("image_file",screenShot.EncodeToPNG()); StartCoroutine (SendPost ("https://api-cn.faceplusplus.com/imagepp/beta/recognizetext", form)); } } }



這裡我們用到LitJson.dll來解析返回的Json資料:(LitJson下載地址:連結: http://pan.baidu.com/s/1miOB6go 密碼: ktcm


完美!