标准二维码的识别
libdmtx 配置
Libdmtx 是一个专门用于识别 datamatrix 二维码的库。搭配Opencv 可以较为准确识别工业二维码 ECC200(关于二维码的编码种类以及 ECC200,自行 google/百度)。接下来是 libdmtx 在VS2013 中的配置,以及简单的测试用例。
1. 下载libdmtx
进入网站https://sourceforge.net/p/libdmtx/libdmtx/ci/master/tree/ 在左侧标 签区域选择版本,下载最新版v0.7.4。
2. 编译代码生成 libdmtx.lib 和libdmtx.dll 文件
在编译时发现v0.7.4版本缺少工程目录。解决办法:下载v0.7.2版本解压,将project和wrapper文件夹拷到0.7.4的源码包里。用VS2013打开project工程目录下的libdmtx.sln。将工程libdmtx设置为当前启动项,编译,在Debug目录下生成libmtx.lib和libmtx.dll文件。
3. Libdmtx+Opencv测试
VS下新建空项目工程libdmtxTest。将生成的libmtx.lib libmtx.dll文件以及dmtx.h文件拷贝到工程目录下,将dmtx.h添加添加至头文件。在工程属性页->链接器->输入->附加依赖中加入libdmtx.lib
然后添加libdmtxTest.cpp文件,输入以下代码:
#include <iostream>
#include "dmtx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace std;
using namespace cv;
int main()
{
DmtxMessage *msg;
DmtxRegion *reg;
Mat src = imread("data_matrix_encode.jpg");
if (!src.data){
cout << "Load image failed!" << endl;
return 0;
}
DmtxImage *img;
img = dmtxImageCreate(src.data, src.cols, src.rows, DmtxPack24bppRGB);
DmtxDecode *dec = dmtxDecodeCreate(img, 1);
reg = dmtxRegionFindNext(dec, NULL);
if (reg != NULL) {
msg = dmtxDecodeMatrixRegion(dec, reg, DmtxUndefined);
if (msg != NULL) {
cout << msg->output << endl;
dmtxMessageDestroy(&msg);
}
dmtxRegionDestroy(®);
}
dmtxDecodeDestroy(&dec);
dmtxImageDestroy(&img);
return 0;
}
运行结果如下:
注意:data_matrix_encode.jpg是位于工程目录下的ECC200二维码图片。
非标准二维码识别
以上二维码的识别要求二维码图像清晰且角度标准,若图像发生一定角度的旋转该如何识别?
基本思路:
-将图像二值化
-对图像进行膨胀操作
-寻找二维码四条边界轮廓线
-利用角点检测算法得出四条直线相交的四个点的坐标
-利用得到的四个点坐标将图像进行仿射变换得到校正的二维码图片
-对校正后的图片进行识别
为节约篇幅,只贴出校正函数代码:
void ImgCorrection(Mat imageSource)
{
Mat image;
imageSource.copyTo(image);
GaussianBlur(image, image, Size(3, 3), 0); //滤波
threshold(image, image, 100, 255, CV_THRESH_BINARY); //二值化
imshow("二值化", image);
Mat element = getStructuringElement(2, Size(7, 7)); //膨胀腐蚀核
dilate(image, image, element);
imshow("膨胀", image);
Mat image1;
Laplacian(image, image1, image.depth(), 1);//拉普拉斯变换寻找边界
imshow("边界", image1);
//寻找直线
vector<Vec2f>lines;
HoughLines(image1, lines, 1, CV_PI / 150, 60, 0, 0);
Mat DrawLine = Mat::zeros(image1.size(), CV_8UC1);
for (int i = 0; i<lines.size(); i++)
{
float rho = lines[i][0];
float theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * a);
pt2.x = cvRound(x0 - 1000 * (-b));
pt2.y = cvRound(y0 - 1000 * a);
line(DrawLine, pt1, pt2, Scalar(255), 1, CV_AA);
}
imshow("直线", DrawLine);
Point2f P1[4];
Point2f P2[4];
vector<Point2f>corners;
goodFeaturesToTrack(DrawLine, corners, 4, 0.1, 10, Mat()); //角点检测
cout << "角点坐标:" << endl;
for (int i = 0; i<corners.size(); i++)//四个角点的坐标
{
circle(DrawLine, corners[i], 3, Scalar(255), 3);
P1[i] = corners[i];
cout << corners[i].x << " " << corners[i].y << endl;
}
imshow("交点", DrawLine);
P2[0] = Point2f(0, 0);
P2[1] = Point2f(0, imageSource.rows);
P2[2] = Point2f(imageSource.cols, imageSource.rows);
P2[3] = Point2f(imageSource.cols, 0);
Mat elementTransf;
elementTransf = getAffineTransform(P1, P2);
warpAffine(imageSource, imageSource, elementTransf, imageSource.size(), 1, 0, Scalar(255));
imwrite("corrImge.jpg", imageSource);//校正后的图片保存
}
运行结果如下:
校正后的图:
识别结果: