Quantcast
Viewing all articles
Browse latest Browse all 4834

Advanced users • Capture live frames from camera, convert to raw RGB565 and process further, in Python

I have a project where I'm trying to project a live video feed to a large RGB LED matrix (currently 256x256).

There are several PicoW involved that receive the image data over WiFi. That part's been solved.

Now I need to implement the rest on a Pi 5, by using the directly connected camera, from which I extract frames at 20 fps, reduce the image size to 256x256, then convert that into RGB565 format (i.e. a raw pixel buffer with 16 bit per pixel) so that I can send it to the Picos.

How do I do this in Python?

I've skimmed over the Picamera2 docs, which seems to offer only direct output to various streams and files. I am unsure how I'd get at the frames so that I can resize them and then get the raw pixels.

I gave ChatGPT a try and it came up with a seemingly nice and complete solution on my first try:

Code:

import cv2import numpy as npdef rgb888_to_rgb565(rgb888_frame):    # Extract the R, G, B components from the 8-bit image    r = rgb888_frame[:, :, 0] >> 3    g = rgb888_frame[:, :, 1] >> 2    b = rgb888_frame[:, :, 2] >> 3        # Combine the components into a 16-bit RGB565 format    rgb565_frame = (r << 11) | (g << 5) | b    return rgb565_framedef save_rgb565(filename, rgb565_frame):    with open(filename, "wb") as f:        # Convert the numpy array to bytes and write to file        rgb565_frame.tofile(f)# Open a connection to the cameracap = cv2.VideoCapture(0)  # You might need to change the device index if you have multiple camerasif not cap.isOpened():    print("Error: Could not open camera.")    exit()while True:    # Capture a frame from the camera    ret, frame = cap.read()        if not ret:        print("Error: Could not read frame.")        break    # Resize the frame to 256x256    resized_frame = cv2.resize(frame, (256, 256))        # Convert the frame from BGR (OpenCV default) to RGB    rgb_frame = cv2.cvtColor(resized_frame, cv2.COLOR_BGR2RGB)        # Convert the RGB frame to RGB565 format    rgb565_frame = rgb888_to_rgb565(rgb_frame)        # Save the RGB565 frame to a file    save_rgb565("frame.rgb565", rgb565_frame)    # Display the frame (optional)    cv2.imshow('Frame', resized_frame)        # Break the loop if 'q' is pressed    if cv2.waitKey(1) & 0xFF == ord('q'):        break# Release the camera and close any OpenCV windowscap.release()cv2.destroyAllWindows()
Problem is: It always reports "Error: Could not read frame.".

The same camera works with the rpicam-... commands just fine.

So I asked GPT to rewrite the program by using Picamera2 instead. It made this:

Code:

from picamera2 import Picamera2import numpy as npfrom PIL import Imagedef rgb888_to_rgb565(rgb888_frame):    # Extract the R, G, B components from the 8-bit image    r = (rgb888_frame[:, :, 0] >> 3).astype(np.uint16)    g = (rgb888_frame[:, :, 1] >> 2).astype(np.uint16)    b = (rgb888_frame[:, :, 2] >> 3).astype(np.uint16)        # Combine the components into a 16-bit RGB565 format    rgb565_frame = (r << 11) | (g << 5) | b    return rgb565_framedef save_rgb565(filename, rgb565_frame):    with open(filename, "wb") as f:        # Convert the numpy array to bytes and write to file        rgb565_frame.tofile(f)# Initialize the camerapicam2 = Picamera2()# Configure the cameraconfig = picam2.create_preview_configuration(main={"size": (640, 480)})picam2.configure(config)# Start the camerapicam2.start()try:    while True:        # Capture a frame from the camera        frame = picam2.capture_array()                # Convert the frame to a PIL image for resizing        image = Image.fromarray(frame)                # Resize the frame to 256x256        resized_image = image.resize((256, 256))                # Convert the resized image back to a numpy array        rgb_frame = np.array(resized_image)                # Convert the RGB frame to RGB565 format        rgb565_frame = rgb888_to_rgb565(rgb_frame)                # Save the RGB565 frame to a file        save_rgb565("frame.rgb565", rgb565_frame)        # Optionally display the frame (requires additional libraries like matplotlib)        # plt.imshow(resized_image)        # plt.show()        # Break the loop if a specific condition is met, e.g., capturing a fixed number of frames        # For an interactive approach, implement a key listener or other stopping condition        except KeyboardInterrupt:    # Handle the keyboard interrupt to exit gracefully    print("Capture stopped by user")# Stop the camerapicam2.stop()
And that worked!

Wow.

Statistics: Posted by tem_pi — Thu Aug 01, 2024 3:17 pm



Viewing all articles
Browse latest Browse all 4834

Trending Articles