基於Opencv識別,矯正二維碼(C++)


參考鏈接
[ 基於opencv 識別、定位二維碼 (c++版)
](https://www.cnblogs.com/yuanchenhui/p/opencv_qr.html)
OpenCV4.0.0二維碼識別代碼簡析

1.使用Qrdetector實現二維碼檢測

opencv中的QRCodeDetector類可以實現二維碼的定位,識別功能,由於本項目使用的是自己設計的二維碼,因此暫時只使用到QRCodeDetector的檢測功能
函數接口
bool detect (InputArray img, OutputArray points) const

使用示例

	QRCodeDetector dec;
	vector<Point2f> list;
	dec.detect(src, list);

原圖
image.png

將list畫出后,得到
image.png

優缺點

優點: 檢測快速方便,速度較快,代碼量少
缺點:准確率不高,有的時候標准的二維碼也會檢測失效
錯誤示例 image.png

2.使用輪廓檢測算法實現二維碼檢測

思路
1.將彩圖轉換為灰度圖

cvtColor(image, dstGray, COLOR_BGR2GRAY);
  1. 將灰度圖使用二值化方法,轉換為黑白
    也可以直接使用Canny算法進行邊緣提取
    OTSU算法更適合色偏較大的二維碼,能夠實現准確的二值化
threshold(dstGray, dstGray, 100, 255, THRESH_BINARY);
或 threshold(srcGray, srcGray, 188, 255, THRESH_BINARY|THRESH_OTUS );
  1. 輪廓查找

進行輪廓層級查找,並進行層級判斷,當嵌套層級大於2時,有可能為定位點
關於輪廓查找的參考文檔
輪廓層級>2的條件不夠強,如果環境光較為自然的話,可以把條件改成>5。某處光源過強,會照成提取出來的輪廓撕裂,這時要額外增加判斷條件。具體做法參考開頭的文檔一

    contours, hierarchy = cv2.findContours(srcGray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    hierarchy = hierarchy[0]
    found = []
    for i in range(len(contours)):
        k = i
        c = 0
        while hierarchy[k][2] != -1:
            k = hierarchy[k][2]
            c = c + 1
        if c >= 2:
            found.append(i)
    foundContours = [contours[i] for i in found]

效果
image.png
增強判斷條件后,只會檢測到周圍三個定位點

3.使用透視變換矯正二維碼

1. 使用QRdetector得到的Point進行透視變換

透視變換參考
假設正常二維碼的大小為(ROW,COL)

vector<Point2f> dstTri;
dstTri.push_back(Point2f( 0,0 ));
dstTri.push_back(Point2f( 0,COL-1 ));
dstTri.push_back(Point2f( ROW-1,COL-1));
dstTri.push_back(Point2f( ROW-1,0 ));//創建目的點
Mat warp_mat = getPerspectiveTransform(list, dstTri);//得到旋轉矩陣
warpPerspective(src, output, warp_mat, srcImg.size());//對src進行透視變幻

經過透視變換結果
image.png

2. 通過二維碼定位點的中點進行透視變換

由於qrcodetect類經常出錯,為了解決此問題,只能使用輪廓查找定位二維碼,但因為輪廓查找只找出三個定位點,無法透視變換,因此項目中二維碼需要額外增加一個定位點(標准的二維碼也不只3個定位點

  1. 通過minAreaRect方法生成輪廓的最小外接矩形
  2. 計算四個矩形中點,與對應的原圖四個定位點中點進行透視變換

代碼如下

RotatedRect rect = minAreaRect((contour2[i]));//生成某一定位點輪廓的最小外接矩形

M = cv2.moments(cnt) # 計算第一條輪廓的各階矩,字典形式
center_x = int(M["m10"] / M["m00"])
center_y = int(M["m01"] / M["m00"])
center_point.append((center_x,center_y))
# 使用矩方法來計算中點

對四個中點按指定順序進行排序,並做透視變換
效果與使用Qrdetector的point進行透視變換類似

	warpPerspective(srcGray, output, warp_mat, srcGray.size()); 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM