1

My code is crashing with the following error:

TypeError: the JSON object must be str, not 'tuple'

I have printed the communicate from ALPR and I receive the following:

(b'plate0: 10 results\n - SBG984\t confidence: 85.7017\n - SBG98\t confidence: 83.3453\n - S8G984\t confidence: 78.3329\n - 5BG984\t confidence: 76.6761\n - S8G98\t confidence: 75.9766\n - SDG984\t confidence: 75.5532\n - 5BG98\t confidence: 74.3198\n - SG984\t confidence: 73.3743\n - SDG98\t confidence: 73.1969\n - BG984\t confidence: 71.7671\n', None)

I wonder how I make the code read this and break it down? I have taken the following code from another example I found online and it works for them so I am not sure what I am doing wrong. I have attached my code below.

# Setting up Pyrebase config below
config = {

}

camera = PiCamera()
global alpr_command_args

def Take_an_Image():
    global alpr_command_args
    camera.start_preview()
    sleep(5)
    camera.capture('picture.jpg')
    camera.stop_preview()

    #alpr subprocess args
    alpr_command = "alpr -c gb pictureold.jpg"
    alpr_command_args = shlex.split(alpr_command)
    read_plate()

def alpr_subprocess():
    global alpr_command_args
    return subprocess.Popen(alpr_command_args, stdout=subprocess.PIPE)

def alpr_json_results():
    alpr_out, alpr_error = alpr_subprocess().communicate()

    if not alpr_error is None:
        return None, alpr_error
    elif b"No license plates found." in alpr_out:
        return None, None

    try:
        return json.loads(alpr_out), None
    except (ValueError) as e:
        return None, e


def read_plate():
    alpr_json, alpr_error = alpr_json_results()
    if not alpr_error is None:
        print (alpr_error)
        return
    if alpr_json is None:
        print ("No results!")
        return
    results = alpr_json["results"]
    print(results)
    ordinal = 0
    for result in results:
        candidates = result["candidates"]
        for candidate in candidates:
            if candidate["matches_template"] == 1:
                ordinal += 1
                print ("PLATE " + candidate["plate"] + candidate["confidence"])


firebase = pyrebase.initialize_app(config)
db = firebase.database()

# Setting initial values to Firebase Database on startup
data = {
    "CAMERA": "OFF",
}

# Setting default values on Pi

results = db.update(data)

# This is the handler when Firebase database changes
def stream_handler(message):
    path = str(message["path"]) # This is what sensor changes, e.g path returns /LED
    status = str(message["data"]) # This is what the sensor says, e.g /LED says "ON"
    # Getting global values
    if path =="/CAMERA":
        if status == "ON":
            print("**TAKE PIC**")
            data = {
                "CAMERA": "OFF",
            }
            results = db.update(data)
            Take_an_Image();

# Starting stream for Firebase
my_stream = db.stream(stream_handler)

UPDATE:

With trying Denis' method I receive the following error:

Exception in thread Thread-1: Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner self.run() File "/usr/lib/python3.5/threading.py", line 862, in run self._target(*self._args, **self._kwargs) File "/home/pi/.local/lib/python3.5/site-packages/pyrebase/pyrebase.py", line 563, in start_stream self.stream_handler(msg_data) File "camera.py", line 96, in stream_handler Take_an_Image(); File "camera.py", line 29, in Take_an_Image read_plate() File "camera.py", line 50, in read_plate alpr_json, alpr_error = alpr_json_results() File "camera.py", line 36, in alpr_json_results elif "No plates found." in alpr_out: TypeError: a bytes-like object is required, not 'str'

UPDATE:

After fixing the byte issue by adding a b before "No license plates found." I am now getting the following error:

Exception in thread Thread-1: Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner self.run() File "/usr/lib/python3.5/threading.py", line 862, in run self._target(*self._args, **self._kwargs) File "/home/pi/.local/lib/python3.5/site-packages/pyrebase/pyrebase.py", line 563, in start_stream self.stream_handler(msg_data) File "camera.py", line 96, in stream_handler Take_an_Image(); File "camera.py", line 29, in Take_an_Image read_plate() File "camera.py", line 52, in read_plate alpr_json, alpr_error = alpr_json_results() File "camera.py", line 46, in alpr_json_results return json.loads(alpr_out), None File "/usr/lib/python3.5/json/init.py", line 312, in loads s.class.name)) TypeError: the JSON object must be str, not 'bytes'

Curtis Boylan
  • 827
  • 1
  • 7
  • 23
  • Why you declare `global alpr_command_args` in so many places? – denis_lor Mar 21 '19 at 10:34
  • @denis_lor I don't think that is what my error is being caused by – Curtis Boylan Mar 21 '19 at 10:35
  • For sure no. Just curious why you set alpr_command_args global multiple times. Since you are just setting its value in __init__, before doing `alpr_command_args = shlex.split(alpr_command)` just write there a line before `global alpr_command_args` and you can remove all the other that are not needed. Just do it once. – denis_lor Mar 21 '19 at 10:39
  • Can you update the code you are using also in the question? You posted about an exception for `a bites-like object is required, not str` but doesn't seem that error to come from the code that is right now in the question. – denis_lor Mar 21 '19 at 10:40
  • @denis_lor Fixed the byte issue by adding a b before the check if the license plate is not found. I am still getting an error though, just updated my question with the new error and the code. – Curtis Boylan Mar 21 '19 at 11:00
  • I guess you are using python3 right? – denis_lor Mar 21 '19 at 11:09

1 Answers1

0

I couldn't reproduce the data you got, but for as much as I tried with the output you gave I could come to this conclusion to get the plates and confidences from the object you are analyzing:

import json

alpr_example = b'plate0: 10 results\n - SBG984\t confidence: 85.7017\n - SBG98\t confidence: 83.3453\n - S8G984\t confidence: 78.3329\n - 5BG984\t confidence: 76.6761\n - S8G98\t confidence: 75.9766\n - SDG984\t confidence: 75.5532\n - 5BG98\t confidence: 74.3198\n - SG984\t confidence: 73.3743\n - SDG98\t confidence: 73.1969\n - BG984\t confidence: 71.7671\n', None

def alpr_json_results():
    alpr_out, alpr_error = alpr_example

    if not alpr_error is None:
        return None, alpr_error
    elif b"No license plates found." in alpr_out:
        return None, None

    try:
        decoded = alpr_out.decode('utf-8')
        decoded = decoded.replace('-', 'plate:')
        decoded = decoded[19:]
        decoded = decoded.replace('plate:', ',plate:')
        decoded = decoded.replace('confidence:', ',confidence:')
        decoded = decoded.split(',')
        decoded.pop(0)
        plateList=[]
        confidenceList=[]
        for i, item in enumerate(decoded):
            if (i%2 == 0):
                print(item.replace('plate: ',''))
            else:
                print(item.replace('confidence: ',''))

        return plateList, confidenceList
    except (ValueError) as e:
        return None, e

alpr_json_results()

#SBG984  
#85.7017
# 
#SBG98   
#83.3453
# 
#S8G984  
#78.3329
# 
#5BG984  
#76.6761
# 
#S8G98   
#75.9766
# 
#SDG984  
#75.5532
# 
#5BG98   
#74.3198
# 
#SG984   
#73.3743
# 
#SDG98   
#73.1969
# 
#BG984   
#71.7671
denis_lor
  • 6,212
  • 4
  • 31
  • 55
  • I have already gotten that code as it is from the sample I used but when I use it it returns an error and I have updated my answer with the error as well, could you have a look? – Curtis Boylan Mar 21 '19 at 09:54
  • Can you update also your code? You are receiving error now with this `elif "No plates found." in alpr_out:` but your code doesn't seem to have those lines – denis_lor Mar 21 '19 at 10:25
  • I tried that and I then get "Expecting value: line 1 column 1 (char 0)" – Curtis Boylan Mar 21 '19 at 11:27