通过zbar和Raspicam modu扫描二维码

2024-04-28 17:35:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我想用我的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以检查图片中是否包含二维码。 我无法运行此代码,此错误是由于:

Segmentation fault

------------------ (program exited with code: 139) Press return to continue

我找不到任何解决方案如何修复这个错误,知道吗?

亲切的问候


Tags: 代码ioimageimportstreampiltimemy
3条回答

排队

scanner.scan(图像)

您使用的变量以前从未出现在代码中。因为zbar是用C编写的,所以它不会捕捉到变量是未定义的,并且库尝试读取垃圾数据,就像它是一个图像一样。因此,segfault。我猜你是指我的流而不是图像。

我的项目是在覆盆子上使用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"

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

如果你想解码不同大小的图像。

所有其他答案的不足之处在于它们有很大的延迟——例如,它们扫描并显示在屏幕上的内容实际上是几秒钟前拍摄的帧,等等。

这是因为树莓Pi的CPU速度慢。所以frame-rate比我们的软件读取和扫描的速率要大得多。

经过大量的努力,我终于编写了这段代码,它的延迟很小。所以当你给它一个QRCode/条形码,它会在不到一秒钟的时间内给你一个结果。

代码中解释了我使用的技巧。

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()

相关问题 更多 >