最近有個項目需要實現二維碼的識別和攝像頭的數據採集。在開始正式項目之前,我決定用python寫幾行簡單的代碼來測試每個庫的識別效果。這次沒有連續測量,也沒有使用多線程識別。只是簡單的測試了每個二維碼的測試效果。這次測試的有opencv 4.2的QRCodeDetector庫,BoofCV的庫,Quirc,Zbar和ZXing。視頻的採集統一使用cv的VideoCapture,視頻的存儲統一使用cv的VideoWriter。我的硬件環境是orange pi 3 的2G內存版,系統是armbian的Debian GNU/Linux 10 (buster)。事先已經配置好了opencv、java和PyBoof等必備條件。
1、首先測試的是opencv
代碼如下(附件test_qr.py):
import numpy as np
import cv2
import os
import time
video_path = '~/Downloads/'
# VideoCapture
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
cap.set(3, 1280)
cap.set(4, 720)
cap.set(5, 30)
# VideoWriter
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
outVideo = cv2.VideoWriter()
outVideo.open('output.mp4',fourcc,30.0,(1280,720), True )
# QRCodeDetector
findQR = False
qrResult = ''
qrDetector = cv2.QRCodeDetector()
print('Demo will work')
cnt = 0
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
#frame = cv2.flip(frame,-1)
outVideo.write(frame)
# QR Code Detector
if not findQR :
frame_mono = cv2.cvtColor(np.uint8(frame), cv2.COLOR_BGR2GRAY)
start = time.time_ns()
qrDone, points = qrDetector.detect(frame_mono)
if qrDone:
#print("find QR Code. Frame counter is ", cnt )
qrString, straight = qrDetector.decode(frame_mono, points)
if len(qrString) >1:
end = time.time_ns()
print("Running time is ",str(end - start))
findQR = True
qrResult = qrString
print("find QR Code")
else:
print('fail to open camera')
break
cnt += 1
if cnt > 300 :
print('Have created output.avi')
break
if findQR:
print("QR Code is: {}".format(qrResult))
else:
print("Didn't find QR Code!")
cap.release()
outVideo.release()
cv2.destroyAllWindows()
評測結果是detect的效果很差,總有誤動作。需要對decode的結果判斷一下是否是空字符串。
用草料二維碼生成的文本或者網址都可以很好識別,但很難識別微信和支付寶的二維碼。可能需要提前對圖片做一定的旋轉和銳化處理。也可能與識別的光線有關係。
2、BoofCV(PyBoof)
這個庫在該網站的分析報告中評價最高,無論是識別效果還是識別速率。本身是java編寫的。但我們使用python版本的PyBoof。
代碼如下(附件中test_boof.py):
import numpy as np
import pyboof as pb
import cv2
import os
import time
video_path = '~/Downloads/'
# VideoCapture
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
cap.set(3, 1280)
cap.set(4, 720)
cap.set(5, 30)
# VideoWriter
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
outVideo = cv2.VideoWriter()
outVideo.open('output.mp4',fourcc,10.0,(1280,720), True )
# QRCodeDetector
findQR = False
qrResult = ''
pb.init_memmap()
detector = pb.FactoryFiducial(np.uint8).qrcode()
print('Demo will work')
cnt = 0
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
#frame = cv2.flip(frame,-1)
outVideo.write(frame)
# QR Code Detector
if not findQR :
frame_mono = cv2.cvtColor(np.uint8(frame), cv2.COLOR_BGR2GRAY)
boof_img = pb.ndarray_to_boof(frame_mono)
#boof_img = pb.load_single_band( 'path to image', np.uint8)
start = time.time_ns()
detector.detect(boof_img)
if len(detector.detections)>0:
end = time.time_ns()
print("running time is ", str(end - start))
print("find QR Code " )
findQR = True
qrResult = detector.detections[0].message
else:
print('fail to open camera')
break
cnt += 1
if cnt > 100 :
print('Have created output.mp4')
break
if findQR:
print("QR Code is: {}".format(qrResult))
else:
print("Didn't find QR Code!")
cap.release()
outVideo.release()
cv2.destroyAllWindows()
這個庫可以識別多個二維碼,總體來說識別準確率還是挺高的。但是昨晚測試時發現和opencv一樣很難識別手機展示的微信和支付寶二維碼。需要嘗試很多次。但今天白天的測試發現和opencv一樣都能正常測試。讓人疑惑。總體上識別需要花費的時間也比opencv短。
3、測試
第一項測試是微信二維碼截圖:
可以看出識別速率都不高,都需要幾百毫秒時間。可能與我使用的嵌入式板卡性能有關。後面將繼續測試zbar,zxing和quirc的效果。
第二項測試是使用草料二維碼生成的二維碼字符串
可以看出來兩者都很慢,需要600ms以上。可能與python有關係,因爲opencv的原生環境是c++而boofcv的是java。也可能與硬件本身的性能有關係。
(後面一篇將繼續測試另外幾個library)