Unity利用ZXing库 生成和识别二维码
2023-12-15 11:29:34
    		ZXing 创建及识别二维码
生成二维码
目标
- 能够生成任意大小的二维码
- 生成的二维码可调整背景颜色和码点的颜色
- 生成的二维码中心可带有小Icon
- 生成的二维码可带边框并可调整边框宽度和颜色
实现
using System.Collections.Generic;
using UnityEngine;
using ZXing;
using ZXing.Common;
namespace S
{
    public class QRCreater
    {
        /// <summary>
        /// 二维码信息
        /// </summary>
        public string Content;
        /// <summary>
        /// 二维码宽度
        /// </summary>
        public int Width=256;
        /// <summary>
        /// 二维码高度
        /// </summary>
        public int Height=256;
        /// <summary>
        /// 二维码外边距
        /// </summary>
        public int Margin=1;
        /// <summary>
        /// 二维码背景颜色
        /// </summary>
        public Color BgColor=Color.white;
        /// <summary>
        /// 二维码内容颜色
        /// </summary>
        public Color ContentColor=Color.black;
        private Texture2D mIcon;
        /// <summary>
        /// 二维码中间小图标
        /// </summary>
        public Texture2D Icon
        {
            get { return mIcon; }
            set
            {
                mIcon = value;
                if (mIcon.width>Width*0.2f||mIcon.height>Height*0.2f)
                {
                    Debug.LogWarning("小图标大小超过二维码大小的1/5,识别精度降低,或可能无法被识别!!!");
                }
            }
        }
        /// <summary>
        /// 编码方式
        /// </summary>
        public string Encode = "UTF-8";
        /// <summary>
        /// 边界线宽度
        /// </summary>
        public int BorderWidth = 0;
        /// <summary>
        /// 边界线颜色
        /// </summary>
        public Color BorderColor = Color.black;
        /// <summary>
        /// 二维码容错级别
        /// </summary>
        private ZXing.QrCode.Internal.ErrorCorrectionLevel ErrorCorrectionLevel =
            ZXing.QrCode.Internal.ErrorCorrectionLevel.M;
        public QRCreater()
        {
        }
        public QRCreater(int width,int height,string content)
        {
            Width = width;
            Height = height;
            Content = content;
        }
        public QRCreater(int width,int height,string content,Texture2D icon)
        {
            Width = width;
            Height = height;
            Content = content;
            Icon = icon;
        }
        
        private BitMatrix GetBitMatrix()
        {
            MultiFormatWriter mw = new MultiFormatWriter();
            Dictionary<EncodeHintType, object> hints = new Dictionary<EncodeHintType, object>()
            {
                {EncodeHintType.CHARACTER_SET, Encode},
                {EncodeHintType.MARGIN, Margin},
                {EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel}
            };
            BitMatrix bitMatrix = mw.encode(Content, BarcodeFormat.QR_CODE, Width, Height, hints);
            return bitMatrix;
        }
        /// <summary>
        /// 是否是边界线区域
        /// </summary>
        /// <param name="x">像素x坐标</param>
        /// <param name="y">像素y坐标</param>
        public bool IsBorderArea(int x,int y)
        {
            if (BorderWidth <= 0) return false;
            bool xTrue = x <= BorderWidth || x >= Width - BorderWidth;
            bool yTrue = y <= BorderWidth || y >= Height - BorderWidth;
            return xTrue || yTrue;
        }
        /// <summary>
        /// 是否是Icon区域
        /// </summary>
        /// <param name="x">像素x坐标</param>
        /// <param name="y">像素y坐标</param>
        /// <param name="color">Icon对应的像素颜色</param>
        public bool IsIconArea(int x,int y,out Color color)
        {
            color = default;
            if (Icon == null) return false;
            int halfWidth = (int) (Width * 0.5f);
            int halfHeight = (int) (Height * 0.5f);
            int iconHalfWidth = (int) (Icon.width * 0.5f);
            int iconHalfHeight = (int) (Icon.height * 0.5f);
            int minX = halfWidth - iconHalfWidth;
            int maxX = halfWidth + iconHalfWidth;
            int minY = halfHeight - iconHalfHeight;
            int maxY = halfHeight + iconHalfHeight;
            if (x < minX || x > maxX || y < minY || y > maxY) return false;
            color = Icon.GetPixel(x - minX, y - minY);
            return true;
        }
        
        /// <summary>
        /// 创建二维码的Texture2D
        /// </summary>
        /// <returns>二维码的Texture2D</returns>
        public Texture2D CreateTexture2D()
        {
            Texture2D texture2D=new Texture2D(Width,Height);
            BitMatrix bitMatrix = GetBitMatrix();
            Color iconColor;
            for (int i = 0; i < bitMatrix.Width; i++)
            {
                for (int j = 0; j < bitMatrix.Height; j++)
                {
                    if (IsBorderArea(i,j))//在边界线区域内
                    {
                        texture2D.SetPixel(i,j,BorderColor);
                    }
                    else if (IsIconArea(i,j,out iconColor))//在Icon区域内
                    {
                        if (iconColor.a==0)//icon 透明处填充背景色
                        {
                            texture2D.SetPixel(i, j, BgColor);
                        }
                        else//写入icon像素颜色
                        {
                            texture2D.SetPixel(i, j, iconColor);
                        }
                    }
                    else// 不在Icon区域内
                    {
                        if (bitMatrix[i, j]) texture2D.SetPixel(i, j, ContentColor);
                        else texture2D.SetPixel(i, j, BgColor);
                    }
                }
            }
            texture2D.Apply();
            return texture2D;
        }
        /// <summary>
        /// 创建二维码的Sprite
        /// </summary>
        /// <returns>二维码的Sprite</returns>
        public Sprite CreateSprite()
        {
            Texture2D texture2D = CreateTexture2D();
            if (texture2D == null) return null;
            return Sprite.Create(texture2D,new Rect(0,0,texture2D.width,texture2D.height),Vector2.zero);
        }
        public void Dispose()
        {
            Width = 0;
            Height = 0;
            Margin = 0;
            BorderWidth = 0;
            Encode = null;
            Icon = null;
        }
    }
}
结果
达成全部既定目标
识别二维码
目标
- 能够快速识别二维码内容
- 识别二维码时可定位二维码中心位置
- 多码共存时可多码识别并定位
实现
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using ZXing;
public class QRScan:MonoBehaviour
{
    [SerializeField]
    private Button scanBtn;
    [SerializeField]
    private RawImage cameraImg;
    
    private WebCamTexture webCamTexture;
    
    public bool IsScaning { get; private set; }
    public float Interval = 0.1f;
    
    private float curInterval;
    private BarcodeReader barCodeReader;
    private Color32[] scanData;
    private void Start()
    {
        WebCamDevice[] devices = WebCamTexture.devices;
        string deviceName = devices[0].name;
        Vector2 cameraImgSize = (cameraImg.transform as RectTransform).sizeDelta;
        webCamTexture=new WebCamTexture(deviceName,(int)cameraImgSize.x,(int)cameraImgSize.y);
        barCodeReader=new BarcodeReader();
        scanBtn.onClick.AddListener(Open);
    }
    public void Update()
    {
        if (IsScaning)
        {
            curInterval += Time.deltaTime;
            if (curInterval>Interval)
            {
                curInterval = 0;
                Scan();
            }
        }
    }
    public void Open()
    {
        webCamTexture.Play();
        cameraImg.texture = webCamTexture;
        cameraImg.SetNativeSize();
        IsScaning = true;
    }
    public void Close()
    {
        webCamTexture.Stop();
        IsScaning = false;
    }
    
    void Scan()
    {
        if (!IsScaning) return;
        scanData = webCamTexture.GetPixels32();
        Result[] results = barCodeReader.DecodeMultiple(scanData, webCamTexture.width,webCamTexture.height);
        if (results!=null)
        {
            ScanSuccess(results);
        }
    }
    void ScanSuccess(Result[] results)
    {
        Close();
        StringBuilder resultSb = new StringBuilder();
        resultSb.Append("识别结果为:");
        foreach (var result in results)
        {
            resultSb.Append($"【{result.Text}】 ");
        }
        Debug.Log(resultSb);
        cameraImg.texture = CreateResultTexture(results);
    }
    /// <summary>
    /// 创建带有定位点的Texture2D
    /// </summary>
    /// <param name="results"></param>
    /// <returns></returns>
    Texture2D CreateResultTexture(Result[] results)
    {
        Texture2D tex = new Texture2D(webCamTexture.width,webCamTexture.height);
        tex.SetPixels32(scanData);
        Color[] pointColors = new Color[100];
        for (int i = 0; i < pointColors.Length; i++)
        {
            pointColors[i] = Color.red;
        }
        foreach (var result in results)
        {
            Vector2 centerPos = GetCenterPos(result);
            tex.SetPixels((int)centerPos.x,(int)centerPos.y,10,10,pointColors);
        }
        tex.Apply();
        return tex;
        
    }
    public Vector2 GetCenterPos(Result result)
    {
        if (result == null) return default;
        float totalX=0, totalY=0;
        int Count = result.ResultPoints.Length;
        foreach (var position in result.ResultPoints)
        {
            totalX += position.X;
            totalY += position.Y;
        }
        return new Vector2(totalX/Count,totalY/Count);
    }
}
结果
能够正常识别二维码,也可多识别,也能够进行定位,但是定位准确度有待提高。
    			文章来源:https://blog.csdn.net/weixin_42498461/article/details/135011588
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
    	本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!