OpenCV二维码检测与定位

在如今流行扫描的年代,应用程序实现二维码扫描检测与识别已经是应用程序的标配、特别是在移动端、如果你的应用程序不能自动发现检测二维码,自动定位二维码你都不好意思跟别人打招呼,二维码识别与解析基于ZXing包即可。难点就在于如何从画面中快速而准确的找到二维码区域,寻找到二维码三个匹配模式点。

一:二维码的结构与基本原理

标准的二维码结构如下:

特别要关注的是图中三个黑色正方形区域,它们就是用来定位一个二维码的最重要的三个区域,我们二维码扫描与检测首先要做的就是要发现这三个区域,如果找到这个三个区域,我们就成功的发现一个二维码了,就可以对它定位与识别了。二维码其它各个部分的说明如下:

三个角上的正方形区域从左到右,从上到下黑白比例为1:1:3:1:1。

不管角度如何变化,这个是最显著的特征,通过这个特征我们就可以实现二维码扫描检测与定位。

二:算法各部与输出

1. 首先把输入图像转换为灰度图像(cvtColor)

2. 通过OTSU转换为二值图像(threshold)

3. 对二值图像使用轮廓发现得到轮廓(findContours)

4. 根据二维码三个区域的特征,对轮廓进行面积与比例过滤得到最终结果显示如下:

三:程序运行结果演示

上述程序运行的最终结果,左侧为原图,右侧为检测结果

四:各个步骤代码实现

#include <opencv2/opencv.hpp>
#include <math.h>
#include <iostream>

using namespace cv;
using namespace std;

bool isCorner(Mat &image);
Mat transformCorner(Mat &image, RotatedRect &rect);
int main(int argc, char** argv) {
    Mat src = imread("D:/gloomyfish/qrcode_05.jpg");
    if (src.empty()) {
        printf("could not load image...\n");
        return -1;
    }
    namedWindow("input image", CV_WINDOW_AUTOSIZE);
    imshow("input image", src);

    Mat gray, binary;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    imwrite("D:/gloomyfish/outimage/qrcode_gray.jpg", gray);

    threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
    imwrite("D:/gloomyfish/outimage/qrcode_binary.jpg", binary);

    // detect rectangle now
    vector<vector<Point>> contours;
    vector<Vec4i> hireachy;
    Moments monents;
    findContours(binary.clone(), contours, hireachy, RETR_LIST, CHAIN_APPROX_SIMPLE, Point());
    Mat result = Mat::zeros(src.size(), CV_8UC3);
    for (size_t t = 0; t < contours.size(); t++) {
        double area = contourArea(contours[t]);

        if (area < 100) continue;
        RotatedRect rect = minAreaRect(contours[t]);
        // 根据矩形特征进行几何分析
        float w = rect.size.width;
        float h = rect.size.height;
        float rate = min(w, h) / max(w, h);
        if (rate > 0.85 && w < src.cols/4 && h<src.rows/4) {
            printf("angle : %.2f\n", rect.angle);
            Mat qr_roi = transformCorner(src, rect);
            if (isCorner(qr_roi)) {
                drawContours(src, contours, static_cast<int>(t), Scalar(255, 0, 0), 2, 8);
                imwrite(format("D:/gloomyfish/outimage/contour_%d.jpg", static_cast<int>(t)), qr_roi);
                drawContours(result, contours, static_cast<int>(t), Scalar(255, 0, 0), 2, 8);
            }
        }
    }
    imshow("result", src);
    imwrite("D:/gloomyfish/outimage/qrcode_patters.jpg", result);
    waitKey(0);
    return 0;
}

原文发布于微信公众号 - OpenCV学堂(CVSCHOOL)

原文发表时间:2017-08-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏量子位

神经网络造“汉字”新技能全开,biangbiang面自愧不如

9310
来自专栏一心无二用,本人只专注于基础图像算法的实现与优化。

对皮肤美白算法的一些研究。

 皮肤美白是现在任何一款流行的美颜软件必备的功能之一,不过你如果在互联网上搜索关于美白算法,能直接拿到并使用的可能不多。一直觉得这个算法其实很简单的,并且实现...

352100
来自专栏AI研习社

25 行 Python 代码就能实现人脸识别?这篇文章告诉你详情

首先,在阅读本文之前,需要注意以下几点: 建议先读一遍本文再跑代码——你需要理解这些代码是干什么的。成功跑一遍不是目的,能够举一反三、在新任务上找出 bug 才...

42670
来自专栏机器学习人工学weekly

机器学习人工学weekly-2018/4/15

注意下面很多链接需要科学上网,无奈国情如此 1. DeepMind的新工作,不用地图在城市里导航 Learning to navigate in cities ...

36580
来自专栏Python专栏

Python | 论做游戏外挂,Python输过谁?

来源:http://blog.csdn.net/qq_37267015/article/details/71330600

1.2K20
来自专栏数据处理

碰运气的约会-几何概率

25450
来自专栏人工智能头条

如何用OpenCV、Python和深度学习实现面部识别?

这篇文章首先将简单介绍下基于深度学习的面部识别的工作原理,以及“深度度量学习”(deep metric learning)的概念。接下来我会帮你安装好面部识别需...

33880
来自专栏量子位

众筹项目能否成功?用机器学习预测可以早知道

安妮 编译自 Shrikar Archak 量子位出品 | 公众号 QbitAI Kickstarter是一家美国的众筹平台。自2009年成立至今,已经有36万...

38450
来自专栏小詹同学

Python系列之三——人脸检测、人脸识别

这是关于人脸的又一篇原创! 之前有利用C++和OpenCv写过人脸识别的系列文章,对于人脸识别的基本理解和步骤流程等基本知识不做反复叙述。比詹小白还要白的童鞋可...

87280
来自专栏机器之心

教程 | 摄影爱好者玩编程:利用Python和OpenCV打造专业级长时曝光摄影图

选自pyimagesearch 机器之心编译 参与:乾树、蒋思源 在本文中,我们将学习如何使用 OpenCV 和图像处理技术来模拟长时曝光图像。为了模拟长时曝...

466140

扫码关注云+社区

领取腾讯云代金券