Search code examples
pythonopencvyolo

use the result of YOLOv8 for pyzbar


I want to pass the result from the YOLOv8 to the decode function so that the barcodes are read from it.

My program code is:

model = YOLO("yolov8n.pt")

cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    results = model.predict(source=frame, show=True, conf=0.70, stream=True, device=0)
    decode(results.numpy())
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

When I do this, I get the following error message:

AttributeError: 'generator' object has no attribute 'numpy'

Additionally I want to preprocess the frame with kraken.binarization.nlbin() is this possible, if so how?


Solution

  • If you read the documentation for Ultralytics' predict you will see that return does not contain any image.

    You have to customize your predictor to return the original image so that you can use the bboxes present in results in order to crop the image. Then you can pass the crops to decode:

    import cv2
    from ultralytics.yolo.engine.model import YOLO
    from pyzbar.pyzbar import decode
    
        
    def on_predict_batch_end(predictor):
        # results -> List[batch_size]
        path, im, im0s, vid_cap, s = predictor.batch
        predictor.results = zip(predictor.results, im0s)
             
    
    model = YOLO("yolov8n.pt")
    model.add_callback("on_predict_batch_end", on_predict_batch_end)
    results = model.predict(source="0", show=True, stream=True)
    for i, (result, im0) in enumerate(results):
        boxes = result.boxes
        for box in boxes:
            xyxy = box.xyxy[0]  # get box coordinates in (top, left, bottom, right) format
            t = int(xyxy[0].item())
            l = int(xyxy[1].item())
            b = int(xyxy[2].item())
            r = int(xyxy[3].item())
            crop_img = im0[l:r, t:b]
            d = decode(crop_img)
            print(d)
            cv2.imshow('YOLO V8 crop', crop_img)  
                
    

    This gives me the following output (I had a QR code on my phone screen) which I anonymized for obvious reasons:

    0: 480x640 2 persons, 1 cell phone, 9.7ms
    [Decoded(data=b'https://wa.me/qr/XXXXXXXXXXXXXX', type='QRCODE', rect=Rect(left=105, top=248, width=90, height=95), polygon=[Point(x=105, y=343), Point(x=193, y=341), Point(x=195, y=251), Point(x=111, y=248)], quality=1, orientation=None)]