健康码识别[QT+OpenCV]

news2024/9/23 17:20:10
  • 💂 个人主页:风间琉璃
  • 🤟 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主
  • 💬 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)订阅专栏

目录

一、识别原理

1.二维码定位

2.颜色识别

二、部分源码


一、识别原理

    二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的、黑白相间的、记录数据符号信息的图形;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理.

        它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。常见的二维码为QR CodeQR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。深色模块表示二进制"1",浅色模块表示二进制"0"

       健康码是申请人通过填报个人信息健康状况、旅游史、居住地、及是否接触过疑似或确诊肺炎病患等问题自动生成二维码,动态显示个人疫情风险等级。健康码又在二维码的基础上发展而来,健康码分红、黄、绿三种颜色,包含这三种颜色的色块表示二进制’’1”。

        健康码的识别一般分为两步健康码定位健康码颜色识别首先判断图片中是否含有二维码,若有则找到健康码的位置。然后将含有健康码的部分进行颜色识别,即可判断健康码是红码、黄码、绿码中的哪一种

1.二维码定位

        健康码码有三个形状相同的位置探测图形, 在没有旋转的情况下, 这三个位置探测图形分别位于健康码码符号的左上角、 右上角和左下角(如下图所示)。 三个位置探测图形共同组成图像图形。

         每个位置探测图形可以看作是由3个重叠的同心的正方形组成,它们分别为77个深色模块、55个浅模块和3*3个深色模块。位置探测图形的模块宽度比为1:1:3:1:1。这种1:1:3:1:1 的宽度比例特征在图像的其他位置出现的可能性很小,故可以将此作为位置探测图形的扫描特征。基于此特征,当一条直线上被黑白相间地截为1:1:3:1:1时,可以认为该直线穿过了位置探测图形。并且该扫描特征不受图像倾斜的影响。

        寻找健康码的三个角的定位角点,需要对图片进行平滑滤波,二值化,寻找轮廓,筛选轮廓中有两个子轮廓的特征,从筛选后的轮廓中找到面积最接近的3个即是二维码的定位角点。然后判断3个角点处于什么位置,主要用来对图片进行透视校正或者仿射校正。需要判断三个角点围成的三角形的最大的角就是二维码左上角的点。然后根据这个角的两个边的角度差确定另外两个角点的左下和右上位置。根据这些特征识别二维码的范围。

        二维码定位流程图如下图所示:

 

2.颜色识别

        找到健康码的位置后,裁剪该区域的图片,得到只含有健康码的图片进行颜色识别,可以避免因为图片中其他部分颜色从而导致识别结果错误。这里的颜色识别不是识别经过灰度化、二值化处理的图片,而是从健康码定位得到的四个顶点坐标,在原图进行裁剪得到的。由于裁剪后的健康码只有绿、黄、红、白色(衬底)这四种颜色。针对这种两者颜色组合而言,最简单粗暴的颜色识别是计算出健康码中三种颜色的像素个数,那个颜色像素点最多便是那种颜色的健康码(白色这里直接忽略不计)

         在OpenCV中图像颜色的处理一般不在RGB域,因为各个颜色连接程度比较大,不易区分。而图片处理一般采用HSV域,有利于图片分割。相对于RGB空间,HSV空间能够非常直观的表达色彩的明暗,色调,以及鲜艳程度,方便进行颜色之间的对比。所以在颜色检测时,选用HSV图像。HSV是相对RGB的另一种颜色表示方式,它相对RGB而言,是一种比较直观的颜色模型。其中颜色的参数分别是:色调(H),饱和度(S),明度(V)。一般对颜色空间的图像进行有效处理都是在HSV空间进行的,然后对于基本色中对应的HSV分量需要给定一个严格的范围,如下表所示。

绿

hmin

0

0

0

0

156

11

26

35

78

100

125

hamx

180

180

180

10

180

25

34

77

99

124

155

smin

0

0

0

43

43

43

43

43

43

43

smax

255

43

30

255

255

255

255

255

255

255

vmin

0

46

221

46

46

46

46

46

46

46

vmax

46

220

255

255

255

255

255

255

255

255

        确定了各个颜色在HSV中的范围后,只需要遍历健康码中每一个像素点,判断属于那个颜色范围即可。针对健康码这种双颜色的,红、黄、绿那个像素点的数量多,便基本可以确定健康码的颜色。

二、部分源码

二维码定位主要使用OpenCV在对象检测模块中QRCodeDetector有关API分别实现二维码检测。

定位结果的detect()函数

bool cv::QRCodeDetector::detect(InputArray img, OutputArray points)

img:待检测是否含有QR二维码的灰度图像或者彩色图像

points:包含QR二维码的最小区域四边形的4个顶点坐标,即二维码的4个顶点

定位结果解码的decode()函数

std::string cv::QRCodeDetector::decode(InputArray img, InputArray points, OutputArray straight_qrcode = noArray())

img:含有QR二维码的图像

points:包含QR二维码的最小区域的四边形的四个顶点

straight_qrcode:经过校正和二值化的QR二维码

识别并解码的detectAndDecode()函数

std::string cv::QRCodeDetector::decode(InputArray img, OutputArray points = noArray(), OutputArray straight_qrcode = noArray())

img:含有QR二维码的图像

points:包含QR二维码的最小区域的四边形的四个顶点

straight_qrcode:经过校正和二值化的QR二维码

以下是定位二维码,并且绘制二维码的边框,为后面图片裁剪作准备。


Qrcode::Qrcode(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::Qrcode)
{
    ui->setupUi(this);
    int red=0,green=0,yellow=0;

    Mat img = imread("/home/qt/qr/6.jpg");
    if (img.empty())
    {
        cout << "image error" << endl;
    }
    Mat gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);
    QRCodeDetector QRdetecter;
    vector<Point> points;
    bool isQRcode;
    string  color;
    Mat  roi;                                    //颜色识别区域
    isQRcode = QRdetecter.detect(gray, points);  //识别二维码
    if (isQRcode)
    {
        //绘制二维码的边框
        for (int i = 0; i < points.size(); i++)
        {
            if (i == points.size() - 1)
            {
                line(img, points[i], points[0], Scalar(0, 0, 0), 2, 8);
                break;
            }
            line(img, points[i], points[i + 1], Scalar(0, 0, 0), 2, 8);
        }
        
    }
    else
    {
        qDebug()<<"无法识别二维码,请确认图像时候含有二维码";
    }

}

以下是裁剪出二维码,然后进行颜色识别。

        //颜色识别
        Rect m_select = Rect(points[0].x,points[0].y,points[1].x-points[0].x,points[1].x-points[0].x); //提取二维码
        roi= img(m_select);
        Mat matHsv;
        cvtColor(roi, matHsv, COLOR_BGR2HSV);
        for (int i = 0; i < roi.rows; i++)
        {
            for (int j = 0; j < roi.cols; j++)
            {
                vector<int> colorVec;
                colorVec.push_back(matHsv.at<Vec3b>(i,j)[0]);
                colorVec.push_back(matHsv.at<Vec3b>(i,j)[1]);
                colorVec.push_back(matHsv.at<Vec3b>(i,j)[2]);

                if (((colorVec[0] >= 0 && colorVec[0] <= 10) || (colorVec[0] >= 156 && colorVec[0] <= 180)) && (colorVec[1] >= 43 && colorVec[1] <= 255) && (colorVec[2] >= 46 && colorVec[2] <= 255))
                {
                    red += 1;
                }
                else if ((colorVec[0] >= 26 && colorVec[0] <= 34) && (colorVec[1] >= 43 && colorVec[1] <= 255) && (colorVec[2] >= 46 && colorVec[2] <= 255))
                {
                    yellow += 1;
                }
                else if ((colorVec[0] >= 35 && colorVec[0] <= 77) && (colorVec[1] >= 43 && colorVec[1] <= 255) && (colorVec[2] >= 46 && colorVec[2] <= 255))
                {
                    green += 1;
                }

            }
        }

        int max = maxThree(red, yellow, green);
        if (yellow == max)
        {
            color = "yellow";
        }
        else if (green == max)
        {
            color = "green";
        }
        else if (red == max)
        {
            color = "red";
        }
        else
        {
            color = " ";
        }

实际上就是遍历健康码中每一个像素点并判断该颜色属于那个颜色范围,然后红、黄、绿那个像素点的数量多,便基本可以确定健康码的颜色。

结束语
感谢你观看我的文章呐~本次航班到这里就结束啦 🛬

希望本篇文章有对你带来帮助 🎉,有学习到一点知识~

躲起来的星星🍥也在努力发光,你也要努力加油(让我们一起努力叭)。

最后,博主要一下你们的三连呀(点赞、评论、收藏),不要钱的还是可以搞一搞的嘛~

不知道评论啥的,即使扣个666也是对博主的鼓舞吖 💞 感谢 💐

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

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

相关文章

matlab实现基本相位调制

相位调制&#xff08;PM&#xff09;是将信息编码为载波的瞬时相位变化的一种调制模式。 调相的基本表达式如下&#xff1b; 载波c(t)是一个标准正弦信号&#xff1b;m(t)是调制信号&#xff1b;调制以后是把m(t)的变化附加到了载波的相位变化上&#xff1b; 调相的基本示意如…

WPF中iconfont图标库的使用

总目录 文章目录总目录前言一、查找项目需要的图标二、图标的使用1.将下载的文件解压缩2.将ttf文件复制粘贴到自己的项目中3.使用总结前言 本文主要介绍在WPF中iconfont图标库的使用 一、查找项目需要的图标 首先进入阿里巴巴矢量图标库网站&#xff0c;登录自己的账号&#…

MySQL快速生成大量测试数据 (脚本一键生成分表数据)

生成128个分表的测试数据敲到手累&#xff1b; 生成的测试数据虽然有离散分布&#xff0c;但随着时间的增长数据量不增反降&#xff0c;不符合大多数线上业务的增长趋势&#xff1b; 生成的测试数据部分超过当前日期。 具体表现如下图所示&#xff1a; 我们直接看下脚本的用法…

月入8000+的steam/csgo搬砖项目(详细拆解)

大家好&#xff0c;我是阿阳 今天就给大家带来一个在steam游戏搬砖项目的拆解&#xff0c;目前这个项目我们团队也一直在带队实操&#xff0c;已经跑通了项目的整个流程&#xff0c;提炼出了完整的赚钱体系。 先给大家看看近期的收益情况&#xff1a; 近期的出售记录&#xf…

[ Azure - Database ] Azure Database for MySQL 配置Auditing并查看使用

传统MySQL的二进制日志binlog可以说是MySQL最重要的日志&#xff0c;它记录了所有的DDL和DML语句&#xff08;除了数据查询语句select&#xff09;&#xff0c;以事件形式记录&#xff0c;还包含语句所执行的消耗的时间。本文会讲解微软云Azure Database for MySQL的binlog相关…

i.MX8MP平台开发分享(IOMUX篇)- 硬件原理

专栏目录&#xff1a;专栏目录传送门 平台内核i.MX8MP5.15.71文章目录1.前言2.IOMUX原理3. 寄存器实例&#xff1a;UART1_RX3.1 PAD: UART1_RXD3.2 PAD: SD1_CMD3.3 PAD: SAI2_RXC3.4 Input select3.5 功能实现4.SION1.前言 我们都知道&#xff0c;芯片包含数量有限的引脚&am…

BeanFactory和Applicationcontext实现

1.容器接口 1.BeanFactory能做哪些事 1.什么是beanFactory 它是spring的核心容器 是ApplicationContext的父接口 ApplicationContext扩展实现都【组合了】beanFactory 2.BeanFactory的功能 明面上只有getBean()方法实际上控制反转、依赖注入、bean生命周期的各种功能都…

tslib-1.4在I.MX6ULL开发板上电容屏不能触摸问题

一、前言 在采用触摸屏的移动终端中&#xff0c;触摸屏性能的调试是个重要问题之一&#xff0c;因为电磁噪声的缘故&#xff0c;触摸屏容易存在点击不准确、有抖动等问题。Tslib是一个开源的程序&#xff0c;能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能&#x…

ESP32-S3 >>> MicroPython 编程初探

今天买了一个ESP32-S3&#xff0c;打算试试在这上面进行MicroPython的编程&#xff08;附资料网址&#xff09;。 首先为了在ESP32上进行mp的编程&#xff0c;需要对其重新烧录固件。这就需要我们电脑安装好CH343驱动&#xff0c;然后找到适用于ESP32-S3的固件&#xff0c;利用…

Diffusion详解及PyTorch代码

首先附上几个大佬的讲解 lilianweng-diffusion-models 这篇博客借鉴了上述博客和视频&#xff0c;同时加上个人的理解整合了一下&#xff0c;整个推导过程非常详细&#xff0c;希望能使每个人都看懂 结合之前讲过的VAE和GAN模型&#xff0c;Diffusion Model和他们的区别就是…

Apache Struts2远程代码执行漏洞(S2-015)复现及修复方案

Apache Struts2远程代码执行漏洞(S2-015)介绍 Apache Struts 2是用于开发JavaEE Web应用程序的开源Web应用框架。Apache Struts 2.0.0至2.3.14.2版本中存在远程命令执行漏洞。远程攻击者可借助带有‘${}’和‘%{}’序列值&#xff08;可导致判断OGNL代码两次&#xff09;的请求…

LabVIEW​​共享​变量生命周期

LabVIEW​​共享​变量生命周期 共享​变量​生命​周期 ​所有​共享​变量​都是​项目​库​的​一部分。​SVE​将会​注册​项目​库​和​库​中​包含​的​共享​变量​&#xff08;当​LabVIEW​需要​调​用​其中​某​个​变量​时&#xff09;​。​默认​情况​…

AlphaGo简易版MuGo源码解析

文章目录前言源码实现MuGo的输入数据模型的搭建模型的训练参考链接结语前言 自从AlphaGo横空出世&#xff0c;战胜李世石后&#xff0c;AI围棋如雨后春笋一般遍地开花。阅读DeepMind的论文有时还是隔靴搔痒&#xff0c;只有钻到代码里&#xff0c;才能一探究竟。于是&#xff…

Arthas诊断追踪性能案例

文章目录1、什么是Arthas2、安装启动3、追踪流程背景&#xff1a;本次案例使用Windows操作系统进行本地环境演示&#xff08;生产环境Linux同理&#xff09; 案例&#xff1a;查询接口性能特别慢&#xff0c;通过Arthas追踪诊断链路中哪个步骤导致性能如此之慢 注意&#xff1a…

code review的思考和实践

使用方式 1.看名称效果图&#xff0c;有没有和自己想要的效果类似的 2.有的话&#xff0c;复制粘贴代码使用 3.也可以自己修改一下 4.css效果并不是特别难&#xff0c;只是有时候我们可能想不到 5.笔者空闲时间&#xff0c;会继续更新的哦&#xff0c;点赞关注不迷路**^_^** …

EMNLP 22:SetGNER: General Named Entity Recognition as Entity Set Generation

SetGNER: General Named Entity Recognition as Entity Set Generation **任务形式&#xff1a;**识别flat、nest和不连续实体。 **任务建模方式&#xff1a;**采用基于pointer的方式实现任务建模&#xff0c;文本序列中的每个word可以用tag表示&#xff0c;具体为&#xff1…

Java算法_LeetCode122:买卖股票的最佳时机II

LeetCode122&#xff1a;买卖股票的最佳时机II 给你一个整数数组 prices &#xff0c;其中 prices[i] 表示某支股票第 i 天的价格。 在每一天&#xff0c;你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买&#xff0c;然后在 同一天 …

有关于huggingface evaluate的使用

老版本Transformer的from datasets import load_metric&#xff0c;在新版本中被替换成了evaluate。 这个包挺难用的&#xff0c;而且不同版本的接口都有点不太一样&#xff0c;本博客以transformers4.18.0, evaluate0.4.0为例&#xff0c;示范一下如何使用evaluate进行常见的…

【LDF】线性判别函数(一)

基于判别函数的判别准则 对于ccc类分类问题&#xff1a;设 gi(x),i1,2,…,cg_i(\mathbf{x}), i1,2, \ldots, cgi​(x),i1,2,…,c, 表示每个类别对应的判别函数&#xff0c;决策规则为&#xff1a;如果 gi(x)>gj(x),∀j≠ig_i(\mathbf{x})>g_j(\mathbf{x}), \forall j \n…

[机器学习-概念新] 什么是欧式距离、标准化欧式距离、马氏距离、余弦距离

1.欧式距离(Euclidean Distance) 欧式距离源自N维欧氏空间中两点间的距离公式&#xff1a; 代码实践 from scipy import spatial vec1 [1, 2, 3, 4] vec2 [5, 6, 7, 8] euclidean spatial.distance.euclidean(vec1, vec2) print(euclidean) 2.标准化欧式距离&#xff08;S…