How to Scan Barcodes in Jupyter Notebook Using Python and OpenCV

Jupyter Notebook is a web-based interactive computing environment that lets you combine live code, equations, visualizations, and narrative text in a single document. If you have Anaconda installed, Jupyter Notebook is included by default. This tutorial walks you through building a Python barcode scanner inside a Jupyter Notebook — upload an image, decode every barcode in it, and display the annotated results inline.

What you’ll build: An interactive Jupyter Notebook that accepts image uploads via a widget button, scans all barcodes and QR codes using Dynamsoft Barcode Reader and OpenCV, and renders annotated results side-by-side with Matplotlib.

Key Takeaways

  • Dynamsoft Barcode Reader’s Python SDK can decode 1D/2D barcodes from image files inside a Jupyter Notebook in a single API call via CaptureVisionRouter.
  • The ipywidgets.FileUpload widget provides a zero-JavaScript way to accept image uploads directly in a notebook cell.
  • OpenCV handles image decoding and barcode-location overlay drawing, while Matplotlib renders the before/after comparison inline.
  • This approach works in both classic Jupyter Notebook and JupyterLab with no extra frontend extensions required.

Common Developer Questions

How do I scan barcodes from an uploaded image in Jupyter Notebook using Python?

Use an ipywidgets.FileUpload control to accept the image, decode the uploaded bytes with OpenCV, and then send the image into CaptureVisionRouter for barcode recognition. The notebook flow in this article keeps everything inline, so upload, decode, and result display all happen inside notebook cells.

What Python library can decode QR codes and 1D barcodes inside a Jupyter Notebook cell?

Dynamsoft Barcode Reader’s Python SDK is the library used here for both QR codes and 1D barcodes. It runs inside a notebook cell through CaptureVisionRouter, so you can decode uploaded images without building a separate desktop or web app first.

How do I display barcode detection results with bounding boxes in Jupyter Notebook?

Draw the barcode quadrilateral points onto a copy of the image with OpenCV, then render the original and annotated versions side-by-side with Matplotlib. That gives you an inline before-and-after view directly in Jupyter Notebook or JupyterLab.

Prerequisites

Build a Barcode Scanner in Jupyter Notebook

  1. Run Jupyter notebook:

    Jupyter notebook

  2. Open http://localhost:8888/ in your browser to create a barcode_scanning.ipynb file.

    new Jupyter notebook

  3. Insert a new cell to install Dynamsoft Barcode Reader, OpenCV, and Matplotlib:

     %pip install dynamsoft-barcode-reader-bundle opencv-python matplotlib
    
  4. Initialize the license of barcode SDK and barcode reader object:

     from dynamsoft_capture_vision_bundle import *
     license_key = "LICENSE-KEY"
     error_code, error_message = LicenseManager.init_license(license_key)
     cvr_instance = CaptureVisionRouter()
    
  5. Create an image upload button in Jupyter notebook:

     from ipywidgets import FileUpload
     def on_upload_change(change):
         if change.name != "value":
             return
         if not change.new:
             return
        
         up = change.owner
         files_obj = change.new
        
         records = list(_flatten_records(files_obj))
        
         for rec in records:
             try:
                 content = _get_bytes(rec)  
             except Exception as e:
                 print("Skip unsupported record:", e)
                 continue
        
             buf = np.frombuffer(content, dtype=np.uint8)
             img = cv.imdecode(buf, cv.IMREAD_COLOR)
             if img is None:
                 print("Failed to decode image.")
                 continue
        
             new_img = img.copy()
             try:
                 decode(new_img)
             except Exception as e:
                 print("Decode error:", e)
        
             img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)
             new_rgb = cv.cvtColor(new_img, cv.COLOR_BGR2RGB)
             show_image(img_rgb, new_rgb)
        
         try:
             up.unobserve(on_upload_change, names="value")
         except Exception:
             pass
        
         reset_done = False
         for val in ((), [], None):
             try:
                 up.value = val
                 reset_done = True
                 break
             except Exception:
                 continue
         if not reset_done:
             try:
                 up.value.clear()
                 reset_done = True
             except Exception:
                 pass
        
         try:
             up.observe(on_upload_change, names="value")
         except Exception:
             pass
        
     uploader = FileUpload(accept='image/*', multiple=True) 
     uploader.observe(on_upload_change, names="value")
     uploader
    
  6. Convert the image data to numpy array and then decode the image with OpenCV API:

     import cv2 as cv
     import numpy as np
    
     for rec in records:
         try:
             content = _get_bytes(rec)  
         except Exception as e:
             print("Skip unsupported record:", e)
             continue
    
         buf = np.frombuffer(content, dtype=np.uint8)
         img = cv.imdecode(buf, cv.IMREAD_COLOR)
    
  7. Scan barcodes with Dynamsoft Barcode Reader API:

     def decode(frame):
         before = time.time()
         result = cvr_instance.capture(frame, EnumPresetTemplate.PT_READ_BARCODES.value)
         after = time.time()
        
         COLOR_RED = (0, 0, 255)
         thickness = 2
         text_x, text_y = 10, 20
        
         if result.get_error_code() != EnumErrorCode.EC_OK:
             print("Error:", result.get_error_code(), result.get_error_string())
             cv.putText(frame, f'{after - before:.2f} s, barcode found: 0', (text_x, text_y),
                        cv.FONT_HERSHEY_SIMPLEX, 0.5, COLOR_RED)
             return
        
         items = result.get_items()
         found = len(items)
         for item in items:
             format_type = item.get_format()
             text = item.get_text()
             print(f'Format: {format_type}, Text: {text}')
             loc = item.get_location()
             pts = np.array([[p.x, p.y] for p in loc.points], dtype=np.int32)
             cv.drawContours(image=frame, contours=[pts], contourIdx=-1,
                             color=COLOR_RED, thickness=thickness, lineType=cv.LINE_AA)
             cv.putText(frame, f'{format_type}', (pts[0][0], pts[0][1] - 10),
                        cv.FONT_HERSHEY_SIMPLEX, 0.5, COLOR_RED)
             cv.putText(frame, f'{text}', (pts[0][0], pts[0][1] - 30),
                        cv.FONT_HERSHEY_SIMPLEX, 0.5, COLOR_RED)
         cv.putText(frame, f'{after - before:.2f} s, barcode found: {found}', (text_x, text_y),
                    cv.FONT_HERSHEY_SIMPLEX, 0.5, COLOR_RED)
            
     new_img = img.copy()
     decode(new_img)
    
  8. Display the barcode recognition results with Matplotlib:

     import matplotlib.pyplot as plt
    
     def show_image(img1, img2):
         fig = plt.figure(figsize=(18, 8))
         ax1 = fig.add_subplot(1, 2, 1)
         ax1.set_title('Input image', fontsize=14)
         ax1.axis('off')
         ax2 = fig.add_subplot(1, 2, 2)
         ax2.set_title('Barcode Recognition', fontsize=14)
         ax2.axis('off')
         ax1.imshow(img1)
         ax2.imshow(img2)
         plt.show()
    

    Scan barcodes in Jupyter Notebook

Common Issues and Edge Cases

  • “License has expired” or “License invalid” error: Ensure you have replaced "LICENSE-KEY" with a valid trial or purchased license key. Trial keys expire after 30 days — request a new one from the Dynamsoft License Portal.
  • FileUpload widget does not appear: The ipywidgets package must be installed and the Jupyter Notebook extension enabled. Run %pip install ipywidgets and restart the kernel. In JupyterLab, you may also need jupyter labextension install @jupyter-widgets/jupyterlab-manager.
  • cv.imdecode returns None: This typically means the uploaded file is not a valid image or is corrupted. Verify the file format (JPEG, PNG, BMP are supported) and ensure the file is not zero-length.

Source Code

Get the complete sample project source code on GitHub