通过zbar和Raspicam模块扫描QR码

问题描述 投票:4回答:7

我想使用我的raspi cam模块来扫描QR码。为了检测和解码二维码,我想使用zbar。我当前的代码:

import io
import time
import picamera
import zbar
import Image

if len(argv) < 2: exit(1)

# Create an in-memory stream
my_stream = io.BytesIO()
with picamera.PiCamera() as camera:
    camera.start_preview()
    # Camera warm-up time
    time.sleep(2)
    camera.capture(my_stream, 'jpeg')

scanner = zbar.ImageScanner()
scanner.parse_config('enable')   

pil = Image.open(argv[1]).convert('L')
width, height = pil.size
raw = pil.tostring()

my_stream = zbar.Image(width, height, 'Y800', raw) 

scanner.scan(image)

for symbol in image:
    print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data

您可能会看到,我想创建一个图片流,将该流发送到zbar,以检查图片中是否包含二维码。我无法运行此代码,导致此错误:

分段错误

----(程序退出,代码:139)按回车键继续

我没有找到解决此错误的解决方案,有什么主意吗?

亲切的问候;

python raspberry-pi qr-code zbar
7个回答
4
投票

所有其他答案的不足之处在于它们有大量的DELAY-例如,它们正在扫描并显示到屏幕上的实际上是几秒钟前拍摄的一帧,依此类推。

这是由于Raspberry Pi的CPU速度慢。因此,frame-rate比我们的软件可以读取和扫描的速率大得多。

[尽力而为,我终于完成了这段代码,其中<< LITTLE DELAY。因此,当您给它一个QRCode / BarCode时,它将在不到一秒钟的时间内为您提供结果。

代码中说明了我使用的技巧。

import cv2 import cv2.cv as cv import numpy import zbar import time import threading ''' LITTLE-DELAY BarCodeScanner Author: Chen Jingyi (From FZYZ Junior High School, China) PS. If your pi's V4L is not available, the cv-Window may have some error sometimes, but other parts of this code works fine. ''' class BarCodeScanner(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.WINDOW_NAME = 'Camera' self.CV_SYSTEM_CACHE_CNT = 5 # Cv has 5-frame cache self.LOOP_INTERVAL_TIME = 0.2 cv.NamedWindow(self.WINDOW_NAME, cv.CV_WINDOW_NORMAL) self.cam = cv2.VideoCapture(-1) def scan(self, aframe): imgray = cv2.cvtColor(aframe, cv2.COLOR_BGR2GRAY) raw = str(imgray.data) scanner = zbar.ImageScanner() scanner.parse_config('enable') #print 'ScanZbar', time.time() width = int(self.cam.get(cv.CV_CAP_PROP_FRAME_WIDTH)) height = int(self.cam.get(cv.CV_CAP_PROP_FRAME_HEIGHT)) imageZbar = zbar.Image(width, height,'Y800', raw) scanner.scan(imageZbar) #print 'ScanEnd', time.time() for symbol in imageZbar: print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data def run(self): #print 'BarCodeScanner run', time.time() while True: #print time.time() ''' Why reading several times and throw the data away: I guess OpenCV has a `cache-queue` whose length is 5. `read()` will *dequeue* a frame from it if it is not null, otherwise wait until have one. When the camera has a new frame, if the queue is not full, the frame will be *enqueue*, otherwise be thrown away. So in this case, the frame rate is far bigger than the times the while loop is executed. So when the code comes to here, the queue is full. Therefore, if we want the newest frame, we need to dequeue the 5 frames in the queue, which is useless because it is old. That's why. ''' for i in range(0,self.CV_SYSTEM_CACHE_CNT): #print 'Read2Throw', time.time() self.cam.read() #print 'Read2Use', time.time() img = self.cam.read() self.scan(img[1]) cv2.imshow(self.WINDOW_NAME, img[1]) cv.WaitKey(1) #print 'Sleep', time.time() time.sleep(self.LOOP_INTERVAL_TIME) cam.release() scanner = BarCodeScanner() scanner.start()


1
投票
在线

scanner.scan(图像)

您使用的变量以前没有出现在代码中。因为zbar是用C编写的,所以它无法捕获未定义的变量,并且库试图像读取图像一样读取垃圾数据。因此,段错误。我猜你是说my_stream而不是图像。


0
投票
我正在为我的项目在树莓上使用QR解码。我通过使用解决了子过程模块。这是我的QR解码功能:

import subprocess def detect(): """Detects qr code from camera and returns string that represents that code. return -- qr code from image as string """ subprocess.call(["raspistill -n -t 1 -w 120 -h 120 -o cam.png"],shell=True) process = subprocess.Popen(["zbarimg -D cam.png"], stdout=subprocess.PIPE, shell=True) (out, err) = process.communicate() qr_code = None # out looks like "QR-code: Xuz213asdY" so you need # to remove first 8 characters plus whitespaces if len(out) > 8: qr_code = out[8:].strip() return qr_code

您可以轻松地向img_widt和img_height之类的函数添加参数并更改这部分代码

"raspistill -n -t 1 -w 120 -h 120 -o cam.png"

to

"raspistill -n -t 1 -w %d -h %d -o cam.png" % (img_width, img_height)

如果您想要不同尺寸的图像进行解码。

0
投票
阅读this之后,我能够提出一个涉及OpenCV的pythonic解决方案。

首先,按照these instructions在Pi上构建OpenCV。这可能需要几个小时才能完成。

现在重启树莓派并使用以下脚本(假设您已安装python-zbar)来获取QR /条形码数据:

import cv2 import cv2.cv as cv import numpy import zbar class test(): def __init__(self): cv.NamedWindow("w1", cv.CV_WINDOW_NORMAL) # self.capture = cv.CaptureFromCAM(camera_index) #for some reason, this doesn't work self.capture = cv.CreateCameraCapture(-1) self.vid_contour_selection() def vid_contour_selection(self): while True: self.frame = cv.QueryFrame(self.capture) aframe = numpy.asarray(self.frame[:,:]) g = cv.fromarray(aframe) g = numpy.asarray(g) imgray = cv2.cvtColor(g,cv2.COLOR_BGR2GRAY) raw = str(imgray.data) scanner = zbar.ImageScanner() scanner.parse_config('enable') imageZbar = zbar.Image( self.frame.width, self.frame.height,'Y800', raw) scanner.scan(imageZbar) for symbol in imageZbar: print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data cv2.imshow("w1", aframe) c = cv.WaitKey(5) if c == 110: #pressing the 'n' key will cause the program to exit exit() # p = test()

注意:在zbar能够检测到QR /条形码之前,我必须逆时针旋转Raspi相机的镜头大约1/4-1/3。 

使用以上代码,每当zbar检测到QR /条形码时,解码的数据都会打印在控制台中。它连续运行,仅在按下n键时停止运行


0
投票
对于任何仍在寻找解决方案的人...这段代码很难看,但是可以在普通的网络摄像头上正常工作,还没有尝试过Pi摄像头。我是python的新手,所以这是我能在Python2和3中都能使用的最好的工具。

制作一个名为kill.sh的bash脚本,使其可执行...(chmod -x)

#kill all running zbar tasks ... call from python ps -face | grep zbar | awk '{print $2}' | xargs kill -s KILL

然后像这样从python进行系统调用...

import sys import os def start_cam(): while True: #Initializes an instance of Zbar to the commandline to detect barcode data-strings. p=os.popen('/usr/bin/zbarcam --prescale=300x200','r') #Barcode variable read by Python from the commandline. print("Please Scan a QRcode to begin...") barcode = p.readline() barcodedata = str(barcode)[8:] if barcodedata: print("{0}".format(barcodedata)) #Kills the webcam window by executing the bash file os.system("/home/pi/Desktop/kill.sh") start_cam()

希望这对以后有相同问题的人有所帮助!

0
投票
很晚才回答,但是在尝试使Zbar工作时,我遇到了许多问题。尽管我使用的是USB网络摄像头,但是在安装zbar之前,我必须安装多个库。我安装了fswebcam,python-zbar,libzbar-dev,最后运行setup.py。

更重要的是,sourceforge的zbar不适用于我,但是github的zbar具有Python包装器。

如果有帮助,我在http://techblog.saurabhkumar.com/2015/09/scanning-barcodes-using-raspberry-pi.html处逐步记录了我的步骤


0
投票
只是Dan2theR的一个小修改,因为我不想创建另一个shell文件。

import sys import os p = os.popen('/usr/bin/zbarcam --prescale=300x300 --Sdisable -Sqrcode.enable', 'r') def start_scan(): global p while True: print('Scanning') data = p.readline() qrcode = str(data)[8:] if(qrcode): print(qrcode) try: start_scan() except KeyboardInterrupt: print('Stop scanning') finally: p.close()

© www.soinside.com 2019 - 2024. All rights reserved.