Im stuck with implementing a Qr-Code Scanner I found here:
I already managed to set up the Raspberry Pi camera in the Browser, like it was explained at this tutorial: https://blog.miguelgrinberg.com/post/video-streaming-with-flask
I'd like to read the Qr Code from the camera which is displayed in the Browser window, but unfortunately the Camera Window from the Qr-Code scanner script always pops up when I enter the route where the camera is supposed to appear. I haven't got much experience with threading and OpenCv etc. and tried various combinations with the camera.py script and scanner.py script. At this point I'm only importing scanner.py, which obviously can't work.
Does somebody know how to implement the scanner into the camera in my program? And what is the element from which to read / scan the Qr Code in the camera.py script?
from flask import Flask from flask import render_template, Response from camera import Camera app = Flask(__name__) @app.route("/scanner/") def scanner(): return render_template("scanner.html") def gen(camera): """Video streaming generator function.""" while True: frame = camera.get_frame() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') @app.route('/video_feed') def video_feed(): """Video streaming route. Put this in the src attribute of an img tag.""" return Response(gen(Camera()), mimetype='multipart/x-mixed-replace; boundary=frame') if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", threaded=True)
import time import io import threading import picamera import cv2 import cv2.cv as cv import numpy import zbar #import stackscanner class Camera(object): thread = None # background thread that reads frames from camera frame = None # current frame is stored here by background thread last_access = 0 # time of last client access to the camera def initialize(self): if Camera.thread is None: # start background frame thread Camera.thread = threading.Thread(target=self._thread) Camera.thread.start() import stackscanner # wait until frames start to be available while self.frame is None: time.sleep(0) def get_frame(self): Camera.last_access = time.time() self.initialize() return self.frame @classmethod def _thread(cls): with picamera.PiCamera() as camera: # camera setup camera.resolution = (320, 320) camera.hflip = True camera.vflip = False # let camera warm up #~ camera.start_preview() #~ time.sleep(2) stream = io.BytesIO() for foo in camera.capture_continuous(stream, 'jpeg', use_video_port=True): # store frame stream.seek(0) cls.frame = stream.read() # reset stream for next frame stream.seek(0) stream.truncate() # if there hasn't been any clients asking for frames in # the last 10 seconds stop the thread #camera.close() if time.time() - cls.last_access > 10: break cls.thread = None
import cv2 import cv2.cv as cv import numpy import zbar import time import threading 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) cv2.imshow(self.WINDOW_NAME, img) cv.WaitKey(1) #print 'Sleep', time.time() time.sleep(self.LOOP_INTERVAL_TIME) cam.release() scanner = BarCodeScanner() scanner.start()
I appreciate any help from you!