VS2013 + Opencv + libdmtx 識別 datamatrx ECC200 二維碼 [入門]

標準二維碼的識別

libdmtx 配置

Libdmtx 是一個專門用於識別 datamatrix 二維碼的庫。搭配Opencv 可以較爲準確識別工業二維碼 ECC200(關於二維碼的編碼種類以及 ECC200,自行 google/百度)。接下來是 libdmtx 在VS2013 中的配置,以及簡單的測試用例。

1. 下載libdmtx

進入網站https://sourceforge.net/p/libdmtx/libdmtx/ci/master/tree/ 在左側標 籤區域選擇版本,下載最新版v0.7.4。
圖1-1

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(&reg);
    }
    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);//校正後的圖片保存

}

運行結果如下:
這裏寫圖片描述

校正後的圖:
這裏寫圖片描述

識別結果:
這裏寫圖片描述

代碼下載地址:http://download.csdn.net/download/u010354182/9960809

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章