Python+OpenCV實現定位二維碼
相較于BarCode,QRCode有明顯的特征區(qū)域,也就是左上角、右上角、左下角三個”回“字區(qū)域,得益于hierarchy中,父子關系的輪廓是連續(xù)的(下標),所以這個時候我們就可以通過cv2.findContours()返回的hierarchy來進行定位。
我們直接上代碼
import cv2 import numpy def qrcode(image): # 有些二維碼和邊緣緊貼,無法識別出整個矩形,所以我們先對圖片大小進行擴展 expand_length = 10 edge = expand_length // 2 h, w = image.shape[:2] image_extend = numpy.zeros((image.shape[0] + expand_length, image.shape[1] + expand_length, 3), numpy.uint8) image_extend[:] = 255 image_extend[edge:edge + h, edge:edge + w] = image # 轉灰度、二值化、找輪廓 gray = cv2.cvtColor(image_extend, cv2.COLOR_BGR2GRAY) # blur = cv2.GaussianBlur(gray, (5, 5), 0) _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) contours, hir = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) ''' 2.4282182798755647 2.3203121154092337 2.3487607213520345 2.318010267306266 ''' # 三個“回”字特征輪廓存儲 parent_hierarchy_list = [] parent_contours_list = [] # 通過層級信息去查找三個“回”字特征區(qū)域 for index, item in enumerate(hir[0][:-2]): # 查找最外層(A)輪廓 if item[2] != -1: parent_index = item[2] - 1 if hir[0][index+1][3] == parent_index: # 查找次一層(B)輪廓 child_first = hir[0][index+1][2] - 1 if hir[0][index+2][3] == child_first: # 查找最里層(C)輪廓 # 計算A輪廓的周長和C輪廓周長的比值 error = cv2.arcLength(contours[parent_index], True) / cv2.arcLength(contours[parent_index + 2], True) if 2 < error < 3: parent_hierarchy_list.append(item) parent_contours_list.append(contours[index]) # 繪制出三個“回”字特征區(qū)域的最外層輪廓 cv2.drawContours(image_extend, contours, index, (0, 255, 0), 3) # 將整個二維碼區(qū)域繪制出來 points_list = [] for index, box in enumerate(parent_contours_list): x, y, w, h = cv2.boundingRect(box) if index == 0: points_list.append((x, y+h)) if index == 1: points_list.append((x+w, y)) if index == 2: points_list.append((x, y)) points_list = numpy.array(points_list) rect = cv2.minAreaRect(points_list) box = cv2.boxPoints(rect) box = numpy.int0(box) cv2.drawContours(image_extend, [box], 0, (255, 0, 0), 2) cv2.imshow('', image_extend) if __name__ == '__main__': img = cv2.imread('../images/QRCode_3.png') qrcode(img) cv2.waitKey() cv2.destroyAllWindows()
通常我們所見的二維碼都是有留白邊緣區(qū)域的,但是在隨便找一些二維碼圖的過程中,有一些是沒有留白邊緣區(qū)域的:
上圖是在IDE中打開的,原圖是沒有灰色邊緣的,這個時候我們如果直接讀取這張圖片,得到的輪廓信息并不是我們期待的三個連續(xù)的父子關系的hierarchy,為了避免這種情況,這里就手動向外擴展十個像素,人為制造一個間隔。
通常來說,我們通過三層for循環(huán)來定位特征區(qū)域已經是足夠的,但是如果二維碼的其他區(qū)域也出現了三層輪廓,那么我們就需要進行篩選,所以代碼通過計算最外層輪廓的長度和最內存輪廓長度的比值來進行篩選,每一個“回”的黑白框框的比例大概為1:1:3:1:1,也就是說他們的邊長比為7:3,而這個比值在標準二維碼中,只有三個特征區(qū)域才符合。
代碼的21到24行中的數值,便是嘗試過了四個不同的二維碼得出的比值,都接近7:3。
最后我們繪制出四個邊框,完成二維碼的定位:
到此這篇關于Python+OpenCV實現定位二維碼的文章就介紹到這了,更多相關Python OpenCV定位二維碼內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決Tkinter中button按鈕未按卻主動執(zhí)行command函數的問題
這篇文章主要介紹了解決Tkinter中button按鈕未按卻主動執(zhí)行command函數的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-05-05Python collections.deque雙邊隊列原理詳解
這篇文章主要介紹了Python collections.deque雙邊隊列原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10