Unity利用ZXing库 生成和识别二维码

ZXing 创建及识别二维码

生成二维码

目标

  1. 能够生成任意大小的二维码
  2. 生成的二维码可调整背景颜色和码点的颜色
  3. 生成的二维码中心可带有小Icon
  4. 生成的二维码可带边框并可调整边框宽度和颜色

实现

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;}}
}

结果

达成全部既定目标

识别二维码

目标

  1. 能够快速识别二维码内容
  2. 识别二维码时可定位二维码中心位置
  3. 多码共存时可多码识别并定位

实现

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);}
}

结果

能够正常识别二维码,也可多识别,也能够进行定位,但是定位准确度有待提高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/227633.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023了,前端实现AI电子秤思路分析

前景小知识&#xff1a; 这几年ai这个话题非常火爆&#xff0c;笔者从事零售行业软件开发也接到了新需求&#xff0c;希望实现ai电子秤&#xff0c;老规矩&#xff0c;先看需求 举个栗子&#xff1a; 或许&#xff0c;你已经留意到&#xff0c;当你在某些大型超市超市或生鲜类…

spring 基于注解管理bean @Autowired

目录结构&#xff1a; 代码示例&#xff1a; UserContronller.java package com.atguigu.spring6.autowired.controller;import com.atguigu.spring6.autowired.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springfra…

阿里云对象存储OSS外网流出流量异常增多导致费用上升的解决方法

本文介绍在使用阿里云的对象存储 OSS服务过程中&#xff0c;外网流量消耗异常增多并导致异常的费用支出这一情况的问题发现、问题定位与几种不同的问题解决方法。 细细数来&#xff0c;写博客已经有近3的历史了&#xff0c;这成为了一项已经陪伴我大半人生的工作&#xff1b;也…

二十章总结

一.线程简介 二.创建线程 1.继承Thread类 Thread类中常用的两个构造方法如下&#xff1a; public Thread():创建一个新的线程对象。 public Thread(String threadName):创建一个名称为threadName的线程对象。 继承Thread类创建一个新的线程的语法如下&#xff1a; p…

设计模式 简单工厂 工厂方法模式 抽象工厂模式

工厂模式介绍 工厂模式是我们最常用的实例化对象模式了&#xff0c;是用工厂方法代替new操作的一种模式。它是创建型模式。 简单工厂 简单工厂模式是指由一个工厂对象决定创建出哪一种产品类的实例, 但它不属于GOF 23种设计模式 简单工厂适用于工厂类负责创建的对象较少的场景,…

如何在Go中并发运行多个函数

引言 Go语言的一个流行特性是它对并发的一流支持,即一个程序可以同时做多件事。随着计算机从更快地运行单个代码流转向同时运行更多代码流,能够并发地运行代码正在成为编程的重要组成部分。为了让程序运行得更快,程序员需要把程序设计成并发运行,这样程序中并发的每一部分…

mmpose 使用笔记

目录 自己整理的可以跑通的代码&#xff1a; 图片demo&#xff1a; 检测加关键点 自己整理的可以跑通的代码&#xff1a; 最强姿态模型 mmpose 使用实例-CSDN博客 图片demo&#xff1a; python demo/image_demo.py \tests/data/coco/000000000785.jpg \configs/body_2d_k…

AE-制作绚丽的图形通道

目录 1.新建合成命名为四边形 2.在合成中新建纯色层命名为tao 3.在纯色层上添加RG Trapcode –>Tao 效果&#xff0c;设置Segment参数 4. 在合成中添加摄像机 5.设置Tao Repeat Paths 相关参数&#xff0c;并调整摄像机的位置 6.设置Tao的 Material & Lighting 等…

skynet笔记

1、skynet.newservice和skynet.uniqueservice的区别 skynet.newservice&#xff1a; 当调用skynet.newservice时&#xff0c;它会每次都创建一个新的服务实例&#xff0c;即使之前已经存在相同类型的服务实例。这意味着可以同时启动多个相同类型的服务实例&#xff0c;它们之…

基于Springboot的高校教学评价系统的设计与实现(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于Springboot的高校教…

【C++】std::bind与functional函数对象

functional 文章目录 functionalstd::bind使用示例 std::function类模板成员函数使用推导指引(C17 起) std::bind 原型&#xff1a; template< class R, class F, class... Args > constexpr /* 未指定 */ bind( F&& f, Args&&... args );函数模板 std…

如何通过TortoiseGit可视化工具查看Git管理的版本树和信息(工作树变更)内容

一、版本树 黑色直线&#xff1a;master分支和基于master分支拉取基础分支都在这条线上&#xff0c;是一条直线。 其他线条&#xff1a;新开分支一定会增加一条线&#xff0c;但不一定每一条线分别代表一个分支。 注&#xff1a;如果一直是一个人&#xff0c;在同一个本地分支…

(三)Java 基本数据类型

目录 一. 前言 二. 基本数据类型 2.1. char&#xff08;字符型&#xff09; 2.2. byte&#xff08;字节型&#xff09; 2.3. short&#xff08;短整型&#xff09; 2.4. int&#xff08;整型&#xff09; 2.5. long&#xff08;长整型&#xff09; 2.6. float&#xff…

powerbuilder游标的使⽤

在某些PowerBuilder应⽤程序的开发中,您可能根本⽤不到游标这样⼀个对象。因为在其它⼯具开发中很多需⽤游标实现的⼯作,在PowerBuilder中却已有DataWin-dow来代劳了。事实上,DataWindow不仅可以替代游标进⾏从后台数据库查询多条记录的复杂操作,⽽且还远不⽌这些。但是同DataW…

前端如何设置模板参数

1.背景&#xff1a; 最近接到一个需求&#xff0c;在一个类似chatGpt的聊天工具中&#xff0c;要在对话框中设置模板&#xff0c;后端提供了很多模板参数&#xff0c;然后要求将后端返回的特殊字符转成按钮&#xff0c;编辑完成后在相应的位置拼接成字符串。 2.效果&#xff1a…

C++ 类模板

目录 前言 类模板语法 类模板和函数模板的区别 类模板没有自动类型推导的使用方式 类模板在模板参数列表中可以有默认参数 类模板中成员函数创建时机 类模板对象做函数参数 指定传入的类型 参数模板化 整个类模板化 类模板与继承 类模板成员函数类外实现 类模板分…

在Spring Cloud中使用OpenFeign完成从一个微服务上传到另一个微服务中

跨服务上传文件&#xff0c;嘿嘿&#xff0c;来一篇实用性高的&#xff0c;本篇将主要完成在Feign中上传文件到另一个微服务中。步骤如下&#xff1a; 我们需要在服务提供者和服务消费者的项目中添加相应的依赖&#xff1a; 对于服务提供者的项目&#xff0c;你需要添加Sprin…

Redis设计与实现之集合及有序集

目录 一、集合 1、编码的选择 2、编码的切换 3、 字典编码的集合 4、集合命令的实现 5、 求交集算法 6、求并集算法 7、 求差集算法 二、有序集 1、编码的选择 2、编码的转换 3、ZIPLIST 编码的有序集 4、SKIPLIST 编码的有序集 三、如何添加元素到集合或有序集中…

Next.js 学习笔记(二)——项目结构

Next.js 项目结构 此页面提供了 Next.js 项目的文件和文件夹结构的概述。它涵盖了 app 和 pages 目录中的顶级文件和文件夹、配置文件以及路由约定。 顶级文件夹 文件夹名描述appApp RouterpagesPages Routerpublic待服务的静态资源src可选的应用程序源文件夹 顶级文件 文…

万兆网络之屏蔽线序接法(中)

在介绍优质网线选购之前&#xff0c;先简单介绍一下水晶头 1毛钱一颗跟1元一颗的水晶头&#xff0c;往往是金手指厚度差别&#xff0c;你可以想象压制的时候可能会有什么情况 另外&#xff0c;一些3元一颗的镀金水晶头会有15U、30U之类的是电镀厚度单位&#xff0c;数值越大镀…