Unity AR+ 百度AI 实现 物体识别与对应英文翻译

发布于:2025-06-19 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、前言

我目前实现了拍照保存到手机的功能

我想进一步优化,实现通过手机摄像头实时识别眼前的物体,显示对应的英文的功能。

1.项目技术栈:Unity 2022.3.53+ Vuforia 11+ 百度物体识别API + 百度翻译API

2.功能目标:使用手机摄像头识别现实中的物体,返回物体识别结果和物体英文翻译,UI 实时展示翻译结果。

二、实现思路

用户点击按钮 → 截图当前画面 → 上传到百度物体识别API  → 获取中文物体名称 →

调用百度翻译API  → 得到英文单词 → 在 UI 显示英文 + 中文。

三、实现代码

脚本名 功能说明 应该挂在哪个物体上
CameraCapture.cs 采集 AR 摄像头画面截图 ARCamera(Vuforia 默认相机)
BaiduAuth.cs 获取百度 Access Token 新建空物体 BaiduManager
BaiduObjectRecognition.cs 调用百度物体识别 API BaiduAuth.cs 放同一个物体即可
BaiduTranslate.cs 调用百度翻译 API 也放在同一个  BaiduManager 上
ARRecognitionController.cs 管理完整识别逻辑和 UI 更新 新建空物体挂载 RecognitionController

1.CameraCapture.cs

using UnityEngine;

public class CameraCapture : MonoBehaviour
{
    public Camera arCamera;

    public Texture2D CaptureImage()
    {
        int captureWidth = 1280;
        int captureHeight = 720;

        RenderTexture rt = new RenderTexture(captureWidth, captureHeight, 24);
        arCamera.targetTexture = rt;
        arCamera.Render();
        RenderTexture.active = rt;

        Texture2D screenShot = new Texture2D(captureWidth, captureHeight, TextureFormat.RGB24, false);
        screenShot.ReadPixels(new Rect(0, 0, captureWidth, captureHeight), 0, 0);
        screenShot.Apply();

        arCamera.targetTexture = null;
        RenderTexture.active = null;
        Destroy(rt);

        return screenShot;
    }
}

2.BaiduAuth.cs

public class BaiduAuth : MonoBehaviour
{
    public string clientId = "你的API Key";
    public string clientSecret = "你的Secret Key";
    public string accessToken;

    public IEnumerator GetAccessToken(System.Action onSuccess)
    {
        string url = $"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={clientId}&client_secret={clientSecret}";
        UnityWebRequest www = UnityWebRequest.Get(url);
        yield return www.SendWebRequest();

        if (!www.result.Equals(UnityWebRequest.Result.ConnectionError))
        {
            var response = JsonUtility.FromJson<TokenResponse>(www.downloadHandler.text);
            accessToken = response.access_token;
            onSuccess?.Invoke();
        }
        else
        {
            Debug.LogError(www.error);
        }
    }

    [System.Serializable]
    public class TokenResponse { public string access_token; }
}

3.BaiduObjectRecognition.cs

public class BaiduObjectRecognition : MonoBehaviour
{
    public string accessToken;

    public IEnumerator RecognizeObject(Texture2D image, System.Action<string> callback)
    {
        byte[] imageData = image.EncodeToJPG();
        string imageBase64 = System.Convert.ToBase64String(imageData);
        string url = $"https://aip.baidubce.com/rest/2.0/image-classify/v2/advanced_general?access_token={accessToken}";

        WWWForm form = new WWWForm();
        form.AddField("image", imageBase64);

        UnityWebRequest www = UnityWebRequest.Post(url, form);
        www.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        yield return www.SendWebRequest();

        if (!www.result.Equals(UnityWebRequest.Result.ConnectionError))
        {
            callback?.Invoke(www.downloadHandler.text);
        }
        else
        {
            Debug.LogError(www.error);
        }
    }
}

4.BaiduTranslate.cs

public class BaiduTranslate : MonoBehaviour
{
    public string appId = "你的翻译AppId";
    public string secretKey = "你的翻译密钥";

    public IEnumerator Translate(string query, System.Action<string> callback)
    {
        string salt = Random.Range(10000, 99999).ToString();
        string sign = GetMD5(appId + query + salt + secretKey);
        string url = $"https://fanyi-api.baidu.com/api/trans/vip/translate?q={UnityWebRequest.EscapeURL(query)}&from=zh&to=en&appid={appId}&salt={salt}&sign={sign}";

        UnityWebRequest www = UnityWebRequest.Get(url);
        yield return www.SendWebRequest();

        if (!www.result.Equals(UnityWebRequest.Result.ConnectionError))
        {
            callback?.Invoke(www.downloadHandler.text);
        }
        else
        {
            Debug.LogError(www.error);
        }
    }

    string GetMD5(string str)
    {
        using var md5 = System.Security.Cryptography.MD5.Create();
        byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(str);
        byte[] hashBytes = md5.ComputeHash(inputBytes);
        return System.BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
    }
}

5.ARRecognitionController.cs

public class ARRecognitionController : MonoBehaviour
{
    public CameraCapture cameraCapture;
    public BaiduAuth auth;
    public BaiduObjectRecognition recognition;
    public BaiduTranslate translator;
    public TextMeshProUGUI resultText;

    public void StartRecognition()
    {
        StartCoroutine(auth.GetAccessToken(() =>
        {
            StartCoroutine(StartRecognitionFlow());
        }));
    }

    IEnumerator StartRecognitionFlow()
    {
        yield return new WaitForSeconds(0.3f);
        Texture2D img = cameraCapture.CaptureImage();

        if (img == null)
        {
            resultText.text = "无法获取图像";
            yield break;
        }

        yield return recognition.RecognizeObject(img, json =>
        {
            var result = JObject.Parse(json);
            string chineseName = result["result"]?[0]?["keyword"]?.ToString();

            if (!string.IsNullOrEmpty(chineseName))
            {
                StartCoroutine(translator.Translate(chineseName, transJson =>
                {
                    var transResult = JObject.Parse(transJson);
                    string english = transResult["trans_result"]?[0]?["dst"]?.ToString();
                    resultText.text = $"{english}\n({chineseName})";
                }));
            }
            else
            {
                resultText.text = "未识别出物体";
            }
        });
    }
}

四、unity中具体实现

1.最终ARRecognitionController上的内容参考如下:

2.UI设计(最基本的就是一个按钮,一个text)

(1)TextMeshProUGUI

a.在 Canvas 里创建一个 TextMeshPro - Text 组件

命名为 ResultText。设置一个大点的字体、颜色醒目一些。

b.在 Canvas 创建一个 Button

命名为识别按钮

按钮点击事件绑定 RecognitionController.StartRecognition() 方法。

五、最终实现效果

操作 系统行为
用户点击“识别”按钮 调用百度授权,获取 access token(如果已有可跳过)
系统截图 AR 相机当前画面 使用 RenderTexture 稳定截图
后端自动处理,上传截图至百度物体识别 API 返回识别出的中文关键词
中文词汇传给翻译 API 得到对应英文单词
显示 UI 结果 Monitor screen  显示器屏幕” 这样显示在界面上

六、探索过程的一些问题

整个流程的串通其实实现的比较顺利。

一直卡在拍照的图片效果不好,百度识别不出来或者不准确上。

        一个就是要处理好ar camera的摄像头像素帧,之前博客提到的gallery screenshot我没有用,直接新写了脚本。

        第二个报错是百度返回 access token 无效,需要每次识别前先动态获取 access token。

        第三个是照片图像老是重复,每次点击时重新采图,延时 0.3 秒防止摄像头卡帧。


网站公告

今日签到

点亮在社区的每一天
去签到