OpenCV应用实例 —— 二维码识别与定位

这篇具有很好参考价值的文章主要介绍了OpenCV应用实例 —— 二维码识别与定位。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

定位二维码不仅仅是为了识别二维码;还可以通过二维码对图像进行水平纠正以及相邻区域定位。定位二维码,不仅需要图像处理相关知识,还需要分析二维码的特性,本文先从二维码的特性讲起。

二维码特性

二维码在设计之初就考虑到了识别问题,所以二维码有一些特征是非常明显的。

二维码有三个"回"字形图案,这一点非常明显。中间的一个点位于图案的左上角,如果图像偏转,也可以根据二维码来纠正。

opencv识别二维码位置,图像处理,opencv,人工智能,计算机视觉,二维码,C/C++

为什么是三个点,而不是一个、两个或四个点呢?

一个点:特征不明显,不易定位。不易定位二维码倾斜角度。

两个点:两个点的次序无法确认,很难确定二维码是否放正了。

四个点:无法确定4个点的次序,从而无法确定二维码是否放正了。

识别二维码,就是识别二维码的三个点,逐步分析一下这三个点的特性

 1、每个点有两个轮廓。就是两个口,大“口”内部有一个小“口”,所以是两个轮廓。

 2 、如果把这个“回”放到一个白色的背景下,从左到右,或从上到下画一条线。这条线经过的图案黑白比例大约为:黑白比例为1:1:3:1:1。

 3 、如何找到左上角的顶点?这个顶点与其他两个顶点的夹角为90度。

通过上面几个步骤,就能识别出二维码的三个顶点,并且识别出左上角的顶点。

使用opencv识别二维码

 查找轮廓,筛选出三个二维码顶点

opencv一个非常重要的函数就是查找轮廓,就是可以找到一个图中的缩所有的轮廓,“回”字形图案是一个非常的明显的轮廓,很容易找到。

int QrParse::FindQrPoint(Mat& srcImg, vector<vector<Point>>& qrPoint)
{
     //彩色图转灰度图
     Mat src_gray;
     cvtColor(srcImg, src_gray, CV_BGR2GRAY);
     namedWindow("src_gray");
     imshow("src_gray", src_gray);
 
     //二值化
     Mat threshold_output;
     threshold(src_gray, threshold_output, 0, 255, THRESH_BINARY | THRESH_OTSU);
     Mat threshold_output_copy = threshold_output.clone();
     namedWindow("Threshold_output");
     imshow("Threshold_output", threshold_output);
 
     //调用查找轮廓函数
     vector<vector<Point> > contours;
     vector<Vec4i> hierarchy;
     findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CHAIN_APPROX_NONE, Point(0, 0));
 
     //通过黑色定位角作为父轮廓,有两个子轮廓的特点,筛选出三个定位角
     int parentIdx = -1;
     int ic = 0;
 
     for (int i = 0; i < contours.size(); i++)
     {
         if (hierarchy[i][2] != -1 && ic == 0)
         {
             parentIdx = i;
             ic++;
         }
         else if (hierarchy[i][2] != -1)
         {
             ic++;
         }
         else if (hierarchy[i][2] == -1)
         {
             ic = 0;
             parentIdx = -1;
         }
 
        
              
         //保存找到的三个黑色定位角
         if (isQr)
             qrPoint.push_back(contours[parentIdx]);
 
             ic = 0;
             parentIdx = -1;
         }
     }
 
     return 0;
}

 找到了两个轮廓的图元,需要进一步分析是不是二维码顶点,用到如下函数:

bool QrParse::IsQrPoint(vector<Point>& contour, Mat& img)
{
    //最小大小限定
    RotatedRect rotatedRect = minAreaRect(contour);
    if (rotatedRect.size.height < 10 || rotatedRect.size.width < 10)
        return false;

    //将二维码从整个图上抠出来
    cv::Mat cropImg = CropImage(img, rotatedRect);
    int flag = i++;

    //横向黑白比例1:1:3:1:1
    bool result = IsQrColorRate(cropImg, flag);
    return result;
}

 黑白比例判断函数:

  //横向和纵向黑白比例判断
  bool QrParse::IsQrColorRate(cv::Mat& image, int flag)
  {
       bool x = IsQrColorRateX(image, flag);
       if (!x)
           return false;
       bool y = IsQrColorRateY(image, flag);
       return y;
  }

  //横向黑白比例判断
  bool QrParse::IsQrColorRateX(cv::Mat& image, int flag)
  {
      int nr = image.rows / 2;
      int nc = image.cols * image.channels();
  
      vector<int> vValueCount;
      vector<uchar> vColor;
      int count = 0;
      uchar lastColor = 0;
  
      uchar* data = image.ptr<uchar>(nr);
      for (int i = 0; i < nc; i++)
      {
          vColor.push_back(data[i]);
          uchar color = data[i]; 28 
          if (i == 0)
          {
              lastColor = color;
              count++;
          }
          else
          {
              if (lastColor != color)
              {
                  vValueCount.push_back(count);
                  count = 0;
              }
              count++;
              lastColor = color;
          }
      }
  
      if (count != 0)
          vValueCount.push_back(count);
  
      if (vValueCount.size() < 5)
          return false;
  
      //横向黑白比例1:1:3:1:1
      int index = -1;
      int maxCount = -1;
      for (int i = 0; i < vValueCount.size(); i++)
      {
          if (i == 0)
          {
              index = i;
              maxCount = vValueCount[i];
          }
          else
          {
              if (vValueCount[i] > maxCount)
              {
                  index = i;
                  maxCount = vValueCount[i];
              }
          }
      }
  
      //黑白比例1:1:3:1:1
      float rate = ((float)maxCount) / 3.00;
  
      cout << "flag:" << flag << " ";
  
      float rate2 = vValueCount[index - 2] / rate;
      cout << rate2 << " ";
      if (!IsQrRate(rate2))
          return false;
  
      rate2 = vValueCount[index - 1] / rate;
      cout << rate2 << " ";
      if (!IsQrRate(rate2))
          return false;
  
      rate2 = vValueCount[index + 1] / rate;
      cout << rate2 << " ";
      if (!IsQrRate(rate2))
          return false;
  
      rate2 = vValueCount[index + 2] / rate;
      cout << rate2 << " ";
      if (!IsQrRate(rate2))
         return false;
 
      return true;
 }
//纵向黑白比例判断 省略
bool QrParse::IsQrColorRateY(cv::Mat& image, int flag)
bool QrParse::IsQrRate(float rate)
{
     //大概比例 不能太严格
    return rate > 0.6 && rate < 1.9;
}

确定三个二维码顶点的次序

 通过如下原则确定左上角顶点:二维码左上角的顶点与其他两个顶点的夹角为90度。

 // pointDest存放调整后的三个点,三个点的顺序如下
 // pt0----pt1
 // 
 // pt2
 bool QrParse::AdjustQrPoint(Point* pointSrc, Point* pointDest)
 {
     bool clockwise;
     int index1[3] = { 2,1,0 };
     int index2[3] = { 0,2,1 };
     int index3[3] = { 0,1,2 };
 
     for (int i = 0; i < 3; i++)
     {
         int *n = index1;
         if(i==0)
             n = index1;
         else if (i == 1)
             n = index2;
         else 
             n = index3;
 
         if (angle > 80 && angle < 99)
         {
             pointDest[0] = pointSrc[n[2]];
             if (clockwise)
             {
                 pointDest[1] = pointSrc[n[0]];
                 pointDest[2] = pointSrc[n[1]];
             }
             else
             {
                 pointDest[1] = pointSrc[n[1]];
                 pointDest[2] = pointSrc[n[0]];
             }
             return true;
         }
     }
     return true;
 }

 

通过二维码对图片矫正

图片有可能是倾斜的,倾斜夹角可以通过pt0与pt1连线与水平线之间的夹角确定。二维码的倾斜角度就是整个图片的倾斜角度,从而可以对整个图片进行水平矫正。

//二维码倾斜角度
Point hor(pointAdjust[0].x+300,pointAdjust[0].y); //水平线
double qrAngle = QrParse::Angle(pointAdjust[1], hor, pointAdjust[0], clockwise);

//以二维码左上角点为中心 旋转
Mat drawingRotation = Mat::zeros(Size(src.cols,src.rows), CV_8UC3);
double rotationAngle = clockwise? -qrAngle:qrAngle;
Mat affine_matrix = getRotationMatrix2D(pointAdjust[0], rotationAngle, 1.0);//求得旋转矩阵
warpAffine(src, drawingRotation, affine_matrix, drawingRotation.size());

二维码相邻区域定位

一般情况下,二维码在整个图中的位置是确定的。识别出二维码后,根据二维码与其他图的位置关系,可以很容易的定位别的图元。

opencv识别二维码位置,图像处理,opencv,人工智能,计算机视觉,二维码,C/C++

 

总结

通过查找大量资料,仔细研究了二维码的特征,从而找到了识别二维码的方法。网上也有许多识别二维码的方法,但是不够严谨。本文是将二维码的多个特征相结合来识别,这样更准确。这种识别方法已应用在公司的产品中,识别效果还是非常好的。文章来源地址https://www.toymoban.com/news/detail-519632.html

到了这里,关于OpenCV应用实例 —— 二维码识别与定位的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 计算机竞赛 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

    🔥 优质竞赛项目系列,今天要分享的是 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 物体检测就是对数字图像中一类特定的物体的

    2024年02月11日
    浏览(64)
  • 计算机毕设 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

    今天学长向大家介绍一个机器视觉的毕设项目,二维码 / 条形码检测与识别 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 物体检测就是对数字图像中一类特定的物体的位置进行自动检测。基本的检测框架有两种: 一种是以滑动窗口为单位对图像进行扫描

    2024年02月10日
    浏览(52)
  • 互联网加竞赛 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

    🔥 优质竞赛项目系列,今天要分享的是 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 物体检测就是对数字图像中一类特定的物体的

    2024年01月18日
    浏览(73)
  • OpenCv案例(十): 基于OpenCvSharp识别二维码

    1:二维码在工业和工作生活中应用广泛,下面基于OpenCvSharp识别图像中二维码; 2:函数:OpenCvSharp中, QRCodeDetector  有两个相关API分别实现二维码检测与二维码解析。           public string DetectAndDecode(InputArray img, out Point2f[] points, OutputArray straightQrcode = null); 其中:      

    2024年02月11日
    浏览(40)
  • opencv实战--角度测量和二维码条形码识别

    首先导入一个带有角度的照片 然后下面的代码注册了一个鼠标按下的回调函数, 还有一个点的数列,鼠标事件为按下的时候就记录点,并画出点,由于点是画在图像上面的,那么就要求了img是需要刷新的所以将他们放在while True里面 当有按键按下的的时候就把图片归为原来的

    2024年02月16日
    浏览(61)
  • Python Opencv实践 - 二维码和条形码识别

            使用pyzbar模块来识别二维码和条形码。ZBar是一个开源软件,用来从图像中读取条形码,支持多种编码,比如EAN-13/UPC-A、UPC-E、EAN-8、代码128、代码39、交错2/5以及二维码。         pyzbar是python封装ZBar的模块,我们用它来做条形码和二维码的识别。         安装方法:

    2024年02月04日
    浏览(46)
  • Python - Opencv + pyzbar实时摄像头识别二维码

    直接上代码: 简单使用的记录

    2024年02月15日
    浏览(46)
  • 计算机竞赛 python+opencv+深度学习实现二维码识别

    🔥 优质竞赛项目系列,今天要分享的是 🚩 python+opencv+深度学习实现二维码识别 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:3分 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/danch

    2024年02月12日
    浏览(61)
  • Python - OpenCV识别条形码、二维码(已封装,拿来即用)

    此代码可识别条形码和二维码,已封装好,拿来即用: 结果:

    2024年02月12日
    浏览(46)
  • OpenCV中QR二维码的生成与识别(CIS摄像头解析)

    QR(Quick Response) 属于二维条码的一种,意思是快速响应的意思。QR码不仅信息容量大、可靠性高、成本低,还可表示汉字及图像等多种文字信息、其保密防伪性强而且使用非常方便。更重要的是QR码这项技术是 开源的 ,在移动支付、电影票、电子会员卡等场景以及很多的产品上

    2024年02月11日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包