最近有个项目需要实现二维码的识别和摄像头的数据采集。在开始正式项目之前,我决定用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)