专栏首页深度学习和计算机视觉【从零学习OpenCV 4】分割图像——分水岭法

【从零学习OpenCV 4】分割图像——分水岭法

经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

二维码被广泛的应用在我们日常生活中,比如微信和支付宝支付、火车票、商品标识等。二维码的出现极大的方便了我们日常的生活,同时也能将信息较为隐蔽的传输。二维码种类多种多样,有QR Code、Data Matrix、Code One等,日常生活中常用的二维码是QR二维码,该二维码样式以及每部分的作用在图7-30给出。二维码定点方向有三个较大的“回”字形区域用于对二维码进行定位,该区域最大的特别之处在于任何一条经过中心的直线其在黑色和白色区域的长度比值都为1:1:3:1:1。二维码中间具有多个较小的“回”字形区域用于二维码的对齐,根据二维码版本和尺寸的不同,对齐区域的数目也不尽相同。

图7-29 QR二维码各部分的作用

QR二维码的识别过程大致分成两个过程,首先搜索二维码的位置探测图形,即QR二维码中三个顶点处的“回”字区域,QR二维码位置以四个顶点的坐标形式给出。之后对二维码进行解码,提取其中的信息。QR二维码识别是OpenCV 4新增加的功能,OpenCV 4提供了相关函数直接解码QR二维码读取其中的信息,但是在OpenCV 4之前的版本中对QR二维码的识别需要借助第三方工具,常用的是zbar解码库。

针对QR二维码识别的两个过程,OpenCV 4提供了多个函数用于实现每个过程,这些函数分别是定位QR二维码的detect()函数、根据定位结果解码二维码的decode()函数以及同时定位和解码的detectAndDecode()函数,接下来将详细介绍这三个函数的函数原型和使用方法。

定位QR二维码的位置不仅可以用于解码QR二维码,也可以用于视觉定位。在利用QR二维码定位的任务中有时不需要对QR二维码进行解码,而是直接使用四个顶点的坐标,因此只定位不解码QR二维码可以加快系统的运行速度。定位QR二维码函数detect()的函数原型在代码清单7-37中给出。

代码清单7-37 detect()函数原型
bool cv::QRCodeDetector::detect(InputArray  img,
                                OutputArray  points 
                                )
  • img:待检测是否含有QR二维码的灰度图像或者彩色图像。
  • points:包含QR二维码的最小区域四边形的四个顶点坐标,即二维码的四个顶点坐标。

该函数能够识别图像中是否含有QR二维码,以bool类型的返回值表示是否含有二维码的结果。如果图像中含有二维码,返回值为true,否则返回值为false。函数第一个参数是待检测是否含有QR二维码的图像,图像可以是灰度图像或者彩色图像,图像的尺寸任意。函数第二个参数是包含QR二维码的最小区域四边形的四个顶点坐标,数据类型为vector。

decode()函数能够利用图像中二维码的定位结果对QR二维码进行解码,该函数的函数原型在代码清单7-38中给出。

代码清单7-38 decode()函数原型
std::string cv::QRCodeDetector::decode(InputArray  img,
                                       InputArray  points,
                                       OutputArray  straight_qrcode = noArray() 
                                       )
  • img:含有QR二维码的图像。
  • points:包含QR二维码的最小区域四边形的四个顶点坐标。
  • straight_qrcode:经过校正和二值化的QR二维码。

该函数能够根据二维码定位的结果信息对二维码进行解码,以string类型的返回值输出解码结果。该函数前两个参数与detect()函数的两个参数含义相同,不过该函数的第二个参数是输入值,数据量不能为空。函数第三个参数是经过校正和二值化的QR二维码,变量类型为Mat,在校正的二维码中每一个有效数据点都以单个像素出现,例如在经过校正和二值化的QR二维码中“回”字形区域中心的黑色区域尺寸为3×3,黑色区域边缘的白色轮廓宽度为1。

有时我们需要识别二维码中的信息,detectAndDecode()函数可以直接一步完成二维码的定位和解码过程,该函数的函数原型在代码清单7-39中给出。

代码清单7-39 detectAndDecode()函数原型
std::string cv::QRCodeDetector::detectAndDecode(InputArray  img,
                                                OutputArray  points = noArray(),
                                                OutputArray  straight_qrcode = noArray() 
                                                )
  • img:含有QR二维码的图像。
  • points:包含QR二维码的最小区域四边形的四个顶点坐标。
  • straight_qrcode:经过校正和二值化的QR二维码。

该函数能够直接完成对QR二维码四个顶点的定位和识别图像中QR二维码的信息,并以vector类型返回四个顶点的坐标,以string类型的返回值输出QR二维码识别的结果。函数第一个参数是含有QR二维码的灰度图像或者彩色图像。第二个参数是包含QR二维码的最小区域四边形的四个顶点坐标,在此函数中该参数是输出值,如果不需要QR二维码顶点坐标可以在调用函数时缺省该参数或者使用默认参数noArray()表示不输出坐标。函数第三个参数是经过校正和二值化的QR二维码,变量类型为Mat,如果不需要输出该结果可以在调用函数时缺省该参数或者使用默认参数noArray()表示不输出图像。

为了了解QR二维码定位和解码相关函数的使用方法,在代码清单7-40中给出了利用上述三个函数识别QR二维码的示例程序。程序中将定位和解码分步识别结果和直接识别结果显示在含有QR二维码的图像中,并输出校正和二值化的QR二维码。程序输出结果在图7-30给出,为了能够直观的了解校正和二值化的QR二维码,图7-30中使用的是Image Watch中查看到的校正和二值化的QR二维码图像。

代码清单7-40 mydetectQRcode.cpp二维码识别
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("qrcode2.png");
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}
	Mat gray, qrcode_bin;
	cvtColor(img, gray, COLOR_BGR2GRAY);
	QRCodeDetector qrcodedetector;
	vector<Point> points;
	string information;
	bool isQRcode;
	isQRcode = qrcodedetector.detect(gray, points);  //识别二维码
	if (isQRcode)
	{
		//解码二维码
		information = qrcodedetector.decode(gray, points, qrcode_bin);
		cout << points << endl;  //输出二维码四个顶点的坐标
	}
	else
	{
		cout << "无法识别二维码,请确认图像时候含有二维码" << endl;
		return -1;
	}
	//绘制二维码的边框
	for (int i = 0; i < points.size(); i++)
	{
		if (i == points.size() - 1)
		{
			line(img, points[i], points[0], Scalar(0, 0, 255), 2, 8);
			break;
		}
		line(img, points[i], points[i + 1], Scalar(0, 0, 255), 2, 8);
	}
	//将解码内容输出到图片上
	putText(img, information.c_str(), Point(20, 30), 0, 1.0, Scalar(0, 0, 255), 2, 8);

	//利用函数直接定位二维码并解码
	string information2;
	vector<Point> points2;
	information2 = qrcodedetector.detectAndDecode(gray, points2);
	cout << points2 << endl;
	putText(img, information2.c_str(), Point(20, 55), 0, 1.0, Scalar(0, 0, 0), 2, 8);

	//输出结果
	imshow("result", img);
	namedWindow("qrcode_bin", WINDOW_NORMAL);
	imshow("qrcode_bin", qrcode_bin);
	waitKey(0);
	return 0;
}

图7-30 mydetectQRcode.cpp程序中二维码识别结果

本文分享自微信公众号 - 小白学视觉(NoobCV),作者:小白

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-02-24

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【从零学习OpenCV 4】QR二维码检测

    二维码被广泛的应用在我们日常生活中,比如微信和支付宝支付、火车票、商品标识等。二维码的出现极大的方便了我们日常的生活,同时也能将信息较为隐蔽的传输。二维码种类多...

    小白学视觉
  • 图像传感器的这9个知识点,你都懂吗?

    典型图像传感器的核心是CCD单元(charge-coupled device,电荷耦合器件)或标准CMOS单元(complementary meta-oxide...

    小白学视觉
  • 【从零学习OpenCV 4】边缘检测原理

    图像的边缘指的是图像中像素灰度值突然发生变化的区域,如果将图像的每一行像素和每一列像素都描述成一个关于灰度值的函数,那么图像的边缘对应在灰度值函数中是函数值突然...

    小白学视觉
  • 【从零学习OpenCV 4】QR二维码检测

    二维码被广泛的应用在我们日常生活中,比如微信和支付宝支付、火车票、商品标识等。二维码的出现极大的方便了我们日常的生活,同时也能将信息较为隐蔽的传输。二维码种类多...

    小白学视觉
  • Excel也能制作二维码

    现在二维码广泛流行,各种各样的地方都需要扫码。二维码不光能使用代码来实现,也可以通过Excel来制作二维码。

    一觉睡到小时候
  • 标签打印软件如何生成DataMatrix码

    随着二维码应用的普及,二维码类型也随着时代的发展越来越多了起来,其中DataMatrix码也逐渐被大家接收并投入使用,下面我们来详细了解一下其制...

    用户5759861
  • 二维码会使用完么?

    现在生活中总是会使用到二维码,在支付中、博客的推广图片上、各种各样的商品推广,都有着二维码的身影,二维码已经是我们的日常生活中有着不可替代的便捷信息载体,近几日...

    Debug客栈
  • 一行python代码生成酷炫/恶搞/表白二维码(内附源码)

    很多人都扫过二维码,大部分人的印象都是黑白相间的小方块,实际上二维码是运用了计算机图像处理技术,组合编码原理的一种编码,其用黑白像素点的图像来代表二进制中的“1...

    行哥玩Python
  • 还可以这样玩!一键生成「专属二维码」,就靠这 4 款小程序

    今天,知晓程序(微信号 zxcx0101)给你推荐 4 款二维码生成器小程序,让你轻松玩转二维码。

    知晓君
  • 走近科学:二维码真的安全吗

    二维码自普及以来,无论是从它的便捷性,还是其安全问题,一直都是公众关注的焦点问题。“码”时代来势迅猛,不可阻挡,似乎一夜之间,二维码即遍布各电商平台、商场、网站...

    FB客服

扫码关注云+社区

领取腾讯云代金券