If you want to use Raspberry Pi as an economical way of detecting barcodes, you can take account for Dynamsoft Barcode Reader SDK. As a business software, Dynamsoft Barcode Reader SDK is designed for overcoming a variety of complicated scenarios with sophisticated algorithms and heavy computations. Although the SDK is flexible for customizing algorithm parameters, subject to the low-frequency CPU of Raspberry Pi, the tradeoff between recognition accuracy and detection speed is still a big challenge. In this article, I will use Socket client-server model as a substitute solution. Thanks to Sabjorn’s NumpySocket module.
System Requirements
- Python 2.7
- Dynamsoft Barcode Reader
Python Barcode Reader Module
Install Dynamsoft Barcode Reader and follow the GitHub repository to build and install the Python barcode module.
Why do We Need the Socket Client-Server Model for Raspberry Pi
I am using the Raspberry Pi 3 Model B+:
- Broadcom BCM2837B0, Cortex-A53 (ARMv8) 64-bit SoC @ 1.4GHz
- 1GB LPDDR2 SDRAM
Here is the time cost of calling the barcode decoding method on Raspberry Pi. Let’s see the resolution of 640×480 first.
The average elapsed time is more than 400ms. What about the resolution of 320×240?
It seems a little bit better but not stable. The CPU utilization may reach 100% which will freeze the process. That is why we need the Socket client-server model by which we can continuously send video frames from Raspberry Pi to a remote server and execute barcode detection tasks on the server.
How to Implement the C/S Model for Barcode Detection
Install OpenCV, scipy, and pillow on Raspberry Pi:
$ sudo apt-get install libopencv-dev python-opencv python-scipy $ python -m pip install pillow
Download NumpySocket. The Python module has already implemented the function of transferring the NumPy array. I only added two methods for sending and receiving barcode results in JSON formats:
import json def sendJSON(self, data): out = json.dumps(data) try: self.connection.sendall(out) except Exception: exit() def receiveJSON(self): try: chunk = self.socket.recv(1024) except Exception: exit() return json.loads(chunk)
Create a pc.py file:
from numpysocket import NumpySocket import cv2 import time import json import dbr # Get the license of Dynamsoft Barcode Reader from https://www.dynamsoft.com/CustomerPortal/Portal/Triallicense.aspx dbr.initLicense('LICENSE KEY') npSocket = NumpySocket() npSocket.startServer(9999) # Receive frames for barcode detection while(True): try: frame = npSocket.recieveNumpy() # cv2.imshow('PC Reader', frame) results = dbr.decodeBuffer(frame, 0x3FF | 0x2000000 | 0x4000000 | 0x8000000 | 0x10000000) out = {} out['results'] = results # Send barcode results to Raspberry Pi npSocket.sendJSON({'results': results}) except: break # Press ESC to exit key = cv2.waitKey(20) if key == 27 or key == ord('q'): break npSocket.endServer() print('Closed')
In the infinite loop, receive the video frames from Raspberry Pi and then call barcode decoding function to get the results.
Create a rpi.py file. In this file, create a queue for storing and sharing video frames between threads:
def read_barcode(): vc = cv2.VideoCapture(0) vc.set(3, 640) #set width vc.set(4, 480) #set height if not vc.isOpened(): print('Camera is not ready.') return host_ip = '192.168.8.84' npSocket = NumpySocket() npSocket.startClient(host_ip, 9999) socket_thread = SocketThread('SocketThread', npSocket) socket_thread.start() while vc.isOpened(): ret, f = vc.read() cv2.imshow("RPi Reader", f) frame = imresize(f, .5) key = cv2.waitKey(20) if key == 27 or key == ord('q'): socket_thread.isRunning = False socket_thread.join() break if not socket_thread.is_alive(): break try: frame_queue.put_nowait(frame) except: # Clear unused frames try: while True: frame_queue.get_nowait() except: pass frame_queue.close() frame_queue.join_thread() vc.release()
Create a worker thread for Socket connection:
class SocketThread (threading.Thread): def __init__(self, name, npSocket): threading.Thread.__init__(self) self.name = name self.npSocket = npSocket self.isRunning = True def run(self): while self.isRunning: frame = frame_queue.get(timeout=100) try: start_time = time.time() self.npSocket.sendNumpy(frame) obj = self.npSocket.receiveJSON() print("--- %.2f ms seconds ---" % ((time.time() - start_time) * 1000)) data = obj['results'] if (len(data) > 0): for result in data: print("Type: " + result[0]) print("Value: " + result[1] + "\n") else: print('No barcode detected.') except: break self.npSocket.endClient()
Run pc.py in Windows and run rpi.py on Raspberry Pi. I used the resolution of 640×480 for preview and resized the frame size for TCP/IP transfer.
The barcode detection works stalely, and the average elapsed time is less than 150ms.
Reference
Source Code
https://github.com/yushulx/python-socket-rpi-barcode
The post Moving Heavy Computation from Raspberry Pi to Windows PC appeared first on Code Pool.