Opencvsharp4之健康码的颜色识别

配置环境: vs2019 , .Net Framework 4.8 , opencvsharp4

给大家介绍一下实现的主要思路吧。

    使用的主要方法 Cv2.InRange() ,该方法的作用就是得到输入图像在指定颜色范围内的部分。通过该函数的输出图像就能判断输入的健康码是什么颜色了。

首先,我们需要判断一张图像内是否有二维码。

直接采用 opencvsharp 里面的QRCodeDetector ,可以根据该方法的返回值来判断是否含有二维码,true的话表示有二维码,同时输出的 points 为二维码四个顶点的坐标,false表示没有,输出的坐标都为0.

        public static bool DetectQRCode(Mat src, out OpenCvSharp.Point2f[] points)
        {
            QRCodeDetector qrCode = new QRCodeDetector();
            return qrCode.Detect(src, out points);
        }

对于大部分的健康码而言,并不是仅仅只有一个二维码,周围还有很多的干扰项,我们在操作时只需要二维码部分。这是就需要用到掩码了。

首先定义一个输入图像大小相同的单通道图像,再根据提取到的二维码的顶点坐标,填充其坐标内部。

          Mat mask = new Mat(src.Size(), MatType.CV_8UC1);

            List<List<OpenCvSharp.Point>> pps = new List<List<OpenCvSharp.Point>>()
                                              { new List<OpenCvSharp.Point>() { points[0], points[1], points[2], points[3] } };
            // 建立一个空的图像 只填充二维码部分 其余部分都为0
            Cv2.FillPoly(mask, pps, new Scalar(255, 255, 255));

     掩码定义好后就可以从原图中提取出二维码了;最好将原图转到HSV空间,这样效果比较好

  图像自身与自身做与运算得到的还是本身,加上掩码之后就能拿到任意ROI了。

            // 转成HSV空间
            Mat hsvImg = new Mat();
            Cv2.CvtColor(src, hsvImg, ColorConversionCodes.BGR2HSV);
            // 提取ROI
            Cv2.BitwiseAnd(hsvImg, hsvImg, hsvImg, mask);

得到HSV空间的图像后就能使用 Cv2.InRange() 得到你想要的颜色部分了。

颜色范围可以根据网上的HSV表设置

我根据这个设置,发现跟我的效果差的比较远,所以我就自己设置了几个颜色。
但也有一个问题就是当输入图像是黄色时,用绿色也能捕捉到。其余没什么问题

            Scalar greenScMin = new Scalar(25, 52, 72);   //绿
            Scalar greenScMax = new Scalar(102, 255, 255);
            Scalar yellowScMin = new Scalar(11, 43, 46); // 黄
            Scalar yellowScMax = new Scalar(34, 255, 255);
            Scalar redScMin = new Scalar(0, 43, 46);   //红
            Scalar redScMax = new Scalar(10, 255, 255);
            Scalar blackScMin = new Scalar(0, 0, 0);  // 黑
            Scalar blavkScMax = new Scalar(180, 255, 46);

下面是  Cv2.InRange()  后几组不同的结果,健康码或者二维码都是网上找的照片或者自己生成的二维码。

当输入为红码时, 想要的颜色范围为红色。输出就红色的部分为白色255,其余都是黑色0.

当输入为红码时,想要的颜色范围为绿色时,输出如下,发现没有白色部分,都是0

黄码 黄色

绿码 绿色

绿码 黄色

 发现效果都还可以。我这样设置颜色的话,经过我多次实验,发现,绿色只能用绿色捕捉到,而黄色能用绿色和黄色捕捉到。我们只需要在绿色捕捉到的情况下,判断黄色有没有捕捉到就行了,不影响我们的最终结果。

      一般而言,我们可以根据最后的输出图像以及输入的颜色范围,判断有没有白色部分输出即255的部分就能判断是什么颜色了。但是大部分的健康码中心都会有一个logo,这个logo的颜色可能会导致输出图像有些问题。logo只是占小部分,所以我们就计数,用不同的颜色得到不同的输出图像,分别计算每张图像像素在二维码范围内像素值等于255的点的数量,最多的就认为是整个二维码的颜色。

        int ScalarCode(Mat mm, Scalar min, Scalar max, Mat maskMat)
            {
                Rect rect = Cv2.BoundingRect(pts);
                int k = 0;
                Mat dst = new Mat();
                Cv2.InRange(mm, min, max, dst);
                for (int i = 0; i < mm.Rows; i++)
                {
                    for (int j = 0; j < mm.Cols; j++)
                    {
                        // maskMat填充的部分就是二维码的部分 其他位置就不需要考虑了
                        if (maskMat.At<byte>(i, j) != 255) continue;
                        if (dst.At<byte>(i, j) == (byte)255)
                        {
                            k++;
                        }
                    }
                }
                return k;
            }

 

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值