如图所示,二维码由不规则的圆点阵列而成,用手机扫描也很难识别。
先进行图像预处理,再识别出斑点:
根据斑点的相对位置生成方阵:
最后填充边界并放大后保存图像,给zxing模块(python调用java)识别。
识别结果如下:
附上源代码:
代码语言:javascript复制import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
import zxing # 导入解析包
class BlobDetector(object):
def __init__(self,thresholdStep = 100,minArea = 200,maxArea= 1000):
self.params = cv2.SimpleBlobDetector_Params()
self.params.thresholdStep = thresholdStep #亮度阈值的步长控制,越小检测出来的斑点越多
self.params.filterByArea = True #像素面积大小控制
self.params.minArea = minArea
self.params.maxArea= maxArea
self.detector = cv2.SimpleBlobDetector_create(self.params)#创建斑点检测器
def detect(self,img):
keypoints = self.detector.detect(img) #在哪个图上检测斑点
print("共检测出%d个斑点" %len(keypoints))
im_with_keypoints=cv2.drawKeypoints(thresh, keypoints, np.array([]), (0, 0, 255),cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
blobs = []
for (x,y) in keypoints[0].convert(keypoints):
blobs.append((x,y))
plt.subplot(1,1,1)
plt.imshow(cv2.cvtColor(im_with_keypoints, cv2.COLOR_BGR2RGB))
plt.title("OpenCV 斑点检测",fontSize =16, color="b")
plt.show()
return blobs
def ocr_qrcode_zxing(filename):
zx = zxing.BarCodeReader() # 调用zxing二维码读取包
zxdata = zx.decode(filename) # 图片解码
return zxdata.parsed # 返回记录的内容
#图像预处理
threshold = 128
img0 = cv2.imread("2.jpg")
gray =cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)
gauss = cv2.GaussianBlur(gray, (13,13), 0) #高斯模糊,X,Y 方向的Ksiez分别
ret, thresh = cv2.threshold( gauss, threshold, 255,cv2.THRESH_BINARY) #转二值图
#斑点识别
blobDetector = BlobDetector()
blobs = blobDetector.detect(thresh)
#根据各斑点之间的相对位置,将斑点阵列 转换为 值为 0(0代表斑点)和 1 的矩阵
blobs.sort(key = lambda L: L[1])#按行sort
blob_X = [x for (x,y) in blobs]
blob_Y = [y for (x,y) in blobs]
# 18行* 18列 的二维码
index_ychange = []
last_y =blob_Y[0]
for i,y in enumerate(blob_Y):
#print(y, y-last_y)
if y - last_y > 20:#pix
index_ychange.append(i)
last_y = y
index_xchange = []
blob_X.sort()
last_x =blob_X[0]
for i,x in enumerate(blob_X):
if x - last_x > 20:#pix
index_xchange.append(i)
last_x = x
A = np.ones((18,18),dtype = np.uint8)
j = 0
start = 0
index_ychange.append(len(blobs))
index_xchange.append(len(blobs))
for _ in index_ychange:
for k in range(start,_):
x = blobs[k][0] # pix
x_index = blob_X.index(x)
for i,m in enumerate(index_xchange):
#print(i,m)
if x_index < m:
break
#print("x_index,i:",x_index,i)
A[j, i] = 0 # has dot. 零代表斑点
start = _
j = 1
#print("j:",j)
for row in A:
print(row)
A *= 255 # 变成黑白图像数组
#周围填充白色方便识别
N = 20
B = np.ones((N,N),dtype = np.uint8)
B *= 255
B[ (N-18)//2:N-(N-18)//2 , (N-18)//2:N-(N-18)//2] =A
plt.subplot(1,1,1)
plt.imshow(B,cmap ="gray")
plt.title("OpenCV 斑点检测",fontSize =16, color="b")
plt.show()
# 放大图像,提高识别率
rows,cols = B.shape
k =2
C = np.zeros((rows*k,cols*k))
for i in range(rows):
for j in range(cols):
C[k*i:k*(i 1),k*j:k*(j 1)] = B[i,j]
cv2.imwrite('test.bmp',C)
result = ocr_qrcode_zxing("test.bmp")
print(result)
程序还需改进以提高健壮性。