ARCore for Unity保存相机图像识别二维码异常:图像比例失真重复
解决Unity ARCore相机图像转RGB后比例异常、二维码无法识别的问题
我之前也踩过这个坑!ARCore通过Frame.CameraImage.AcquireCameraImageBytes()获取的是YUV_420_888格式的原始图像数据,不是直接可用的RGB格式。如果直接粗暴转换,会因为YUV的4:2:0采样特性导致像素排列错误,出现图像拉伸、重复的情况,二维码自然就识别不了了。
下面给你一步步解决:
核心问题拆解
- 格式不匹配:YUV_420_888是平面格式,Y、U、V分量分开存储,且U/V分量的分辨率是Y的一半,直接转RGB会导致像素映射错误。
- 尺寸不匹配:如果你的Texture2D尺寸和相机原始图像尺寸不一致,拉伸后会让二维码变形,无法被识别器正确解析。
修正后的完整代码示例
using UnityEngine; using GoogleARCore; using ZXing; using ZXing.Common; using System.Collections.Generic; public class ARQRCodeScanner : MonoBehaviour { private Texture2D _cameraTexture; private BarcodeReader _barcodeReader; void Update() { // 每3帧处理一次,优化性能(可选) if (Time.frameCount % 3 != 0) return; using (var cameraImage = Frame.CameraImage.AcquireCameraImageBytes()) { if (!cameraImage.IsAvailable) return; // 初始化/更新纹理:确保尺寸和相机图像完全一致 if (_cameraTexture == null || _cameraTexture.width != cameraImage.Width || _cameraTexture.height != cameraImage.Height) { // 用RGBA32格式,兼容大多数识别库 _cameraTexture = new Texture2D(cameraImage.Width, cameraImage.Height, TextureFormat.RGBA32, false); // 初始化二维码识别器,指定只识别QR码 _barcodeReader = new BarcodeReader { Options = new DecodingOptions { TryHarder = true, // 提高识别成功率 PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE } } }; } // 用ARCore官方方法转换YUV到Color32,避免手动计算出错 var colorPixels = new Color32[cameraImage.Width * cameraImage.Height]; cameraImage.CopyToColor32(colorPixels); // 更新纹理并应用 _cameraTexture.SetPixels32(colorPixels); _cameraTexture.Apply(); // 执行二维码识别 var scanResult = _barcodeReader.Decode( _cameraTexture.GetPixels32(), _cameraTexture.width, _cameraTexture.height); if (scanResult != null) { Debug.Log($"识别到二维码内容:{scanResult.Text}"); // 这里添加你的业务逻辑,比如跳转、显示内容等 } } } // 销毁时释放资源 void OnDestroy() { if (_cameraTexture != null) Destroy(_cameraTexture); } }
关键注意事项
- 用官方转换方法:
cameraImage.CopyToColor32()是ARCore提供的原生转换方法,能完美处理YUV_420_888到RGB的映射,这是解决比例和重复问题的核心,别自己手动计算YUV分量,容易出错。 - 严格匹配尺寸:必须保证Texture2D的宽高和
cameraImage.Width/cameraImage.Height完全一致,任何拉伸都会导致二维码变形。 - 性能优化:每帧处理相机图像和二维码识别会比较耗性能,建议隔几帧处理一次(比如示例中的每3帧),根据你的需求调整频率。
- 资源释放:用
using包裹CameraImage确保及时释放,销毁脚本时记得销毁Texture2D,避免内存泄漏。
内容的提问来源于stack exchange,提问作者balaji
相关产品推荐
相关产品推荐

