Raspberry Pi

Is pypng 16-bit PNG encoding faster using pypy on the Raspberry Pi?

In our previous post How to save Raspberry Pi raw 10-bit image as 16-bit PNG using pypng we investigated how to use the pypng library to save 10-bit raw Raspberry Pi Camera images to 16-bit PNG files.

However, saving a single image took ~26 seconds using CPython 3.7.3. Since pypy can provide speedups to many Python workloads, we tried using pypy3 7.0.0 (see How to install pypy3 on the Raspberry Pi) to speed up the PNG encoding.

Results

pypng PNG export seems to be one of the workloads that are much slower using pypy3.

  • CPython 3.7.3: Encoding took 24.22 seconds
  • pypy3 7.0.0: Encoding took 266.60 seconds

Encoding is more that 10x slower when using pypy3!

Hence I don’t recommend using pypy3 to speed up pypng encoding workloads, at least not on the Raspberry Pi!

Full example

This example is derived from our full example previously posted on How to save Raspberry Pi raw 10-bit image as 16-bit PNG using pypng:

#!/usr/bin/env python3
import time
import picamera
import picamera.array
import numpy as np
import png

# Capture image
print("Capturing image...")
with picamera.PiCamera() as camera:
    with picamera.array.PiBayerArray(camera) as stream:
        camera.capture(stream, 'jpeg', bayer=True)
        # Demosaic data and write to rawimg
        # (stream.array contains the non-demosaiced data)
        rawimg = stream.demosaic()

# Write to PNG
print("Writing 16-bit PNG...")
t0 = time.time()
with open('16bit.png', 'wb') as outfile:
    writer = png.Writer(width=rawimg.shape[1], height=rawimg.shape[0], bitdepth=16, greyscale=False)
    # rawimg is a (w, h, 3) RGB uint16 array
    # but PyPNG needs a (w, h*3) array
    png_data = np.reshape(rawimg, (-1, rawimg.shape[1]*3))
    # Scale 10 bit data to 16 bit values (else it will appear black)
    # NOTE: Depending on your photo and the settings,
    #  it might still appear quite dark!
    png_data *= int(2**6)
    writer.write(outfile, png_data)
t1 = time.time()

print(f"Encoding took {(t1 - t0):.2f} seconds")

 

Posted by Uli Köhler in Python, Raspberry Pi

How to install pypy3 on the Raspberry Pi

This post shows you an easy way of getting pypy3 running on the Raspberry Pi. I used Raspbian Buster on a Raspberry Pi 3 for this example. On Raspbian buster this will install pypy3 7.x!

First install pypy3 and virtualenv:

sudo apt update && sudo apt -y install pypy3 pypy3-dev virtualenv

Now we can create a virtualenv to install pypy packages into:

virtualenv -p /usr/bin/pypy3 ~/pypy3-virtualenv

Now we can activate the virtualenv. You need to do this every time you want to use pypy, for each shell / SSH connection separately:

source ~/pypy3-virtualenv/bin/activate

If your shell prompt is now prefixed by (pypy3-virtualenv) you have successfully activated the virtualenv:

(pypy3-virtualenv) uli@raspberrypi:~ $

Now python points to pypy3 and pip will install packages locally to ~/pypy3-virtualenv.

Now you can use e.g.

python3 myscript.py

to run your script (both python and python3 will point to pypy3 if you activated the virtual environment!).

Note: Installing pypy3-dev is not strictly neccessary to get pypy3 running, but you need it in order to compile native librarie like numpy.

Posted by Uli Köhler in Python, Raspberry Pi

How to save Raspberry Pi raw 10-bit image as 16-bit PNG using pypng

In our previous post How to capture RaspberryPi camera 10-bit raw image in Python we showed how you can use the picamera Python library to capture raw 10-bit image data.

The PNG image format supports storing 16-bit image data. This post shows you how to do that using the NumPy arrays we generated in our previous post. We are using the pypng library.

with open('16bit.png', 'wb') as outfile:
    writer = png.Writer(width=rawimg.shape[1], height=rawimg.shape[0], bitdepth=16, greyscale=False)
    # rawimg is a (w, h, 3) RGB uint16 array
    # but PyPNG needs a (w, h*3) array
    png_data = np.reshape(rawimg, (-1, rawimg.shape[1]*3))
    # Scale 10 bit data to 16 bit values (else it will appear black)
    # NOTE: Depending on your photo and the settings,
    #  it might still appear quite dark!
    png_data *= int(2**6)
    writer.write(outfile, png_data)

Note that the resulting PNGs are ~9.9 Megabytes in size and saving them using pypng takes about 27 seconds to save the image on my Raspberry Pi 3!

For comparison, the raw NumPy data is ~29 Megabytes whereas the compressed NumPy data is 9.3 Megabytes,

  • Raw NumPy data (np.save): 29 Megabytes, takes 0.11 seconds to save.
  • Compressed NumPy data (np.savez_compressed): 9.3 Megabytes, take 12 seconds to save.

So if your motivation for using PNG is to save space, you might be better off using NumPy compressed data, especially if you need to save many camera frames in quick succession and hence are limited.

In case you need to use PNGs, you might want to check Pypy since pypng is a pure Python library and hence might benefit from Pypy’s increased execution speed. However, in practice, pypy3 is more than 10x slower. Please read our detailed analysis at Is pypng 16-bit PNG encoding faster using pypy on the Raspberry Pi?

Full example:

#!/usr/bin/env python3
import picamera
import picamera.array
import numpy as np
import png

# Capture image
print("Capturing image...")
with picamera.PiCamera() as camera:
    with picamera.array.PiBayerArray(camera) as stream:
        camera.capture(stream, 'jpeg', bayer=True)
        # Demosaic data and write to rawimg
        # (stream.array contains the non-demosaiced data)
        rawimg = stream.demosaic()

# Write to PNG
print("Writing 16-bit PNG...")
with open('16bit.png', 'wb') as outfile:
    writer = png.Writer(width=rawimg.shape[1], height=rawimg.shape[0], bitdepth=16, greyscale=False)
    # rawimg is a (w, h, 3) RGB uint16 array
    # but PyPNG needs a (w, h*3) array
    png_data = np.reshape(rawimg, (-1, rawimg.shape[1]*3))
    # Scale 10 bit data to 16 bit values (else it will appear black)
    # NOTE: Depending on your photo and the settings,
    #  it might still appear quite dark!
    png_data *= int(2**6)
    writer.write(outfile, png_data)

 

Posted by Uli Köhler in Raspberry Pi

How to capture RaspberryPi camera 10-bit raw image in Python

You can use the picamera Python library to capture a raw sensor image of a camera attached to the Raspberry Pi via CSI:

#!/usr/bin/env python3
import picamera
import picamera.array
import numpy as np

# Capture image
print("Capturing image...")
with picamera.PiCamera() as camera:
    with picamera.array.PiBayerArray(camera) as stream:
        camera.capture(stream, 'jpeg', bayer=True)
        # Demosaic data and write to rawimg
        # (stream.array contains the non-demosaiced data)
        rawimg = stream.demosaic()

rawimg is a numpy uint16 array of dimensions (w, h, 3), e.g. (1944, 2592, 3) and contains integer values from 0 to 1023.

You can, for example, save it in a NumPy file using

np.save("rawimg.npy", rawimg) # Reload with np.load("rawimg.npy")

or save it in a compressed format using

np.savez_compressed("rawimg.npz", rawimg) # Reload with np.load("rawimg.npz")
Posted by Uli Köhler in Python, Raspberry Pi

How to fix ModuleNotFoundError: No module named ‘picamera’

Problem:

You want to run a Python script using the Raspberry Pi camera but you see an error message like

Traceback (most recent call last):
  File "mycamera.py", line 2, in <module>
    import picamera
ModuleNotFoundError: No module named 'picamera'

Solution:

You need to install the picamera Python module using pip:

sudo pip3 install picamera

or, if you are still using Python 2.x:

sudo pip install picamera

In case you see

sudo: pip3: command not found

install pip3 using

sudo apt install -y python3-pip

 

Posted by Uli Köhler in Python, Raspberry Pi

How to install picamraw using pip

First try installing it normally:

sudo pip3 install picamraw

In case that fails with this error message (like for me):

Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting picamraw
Could not install packages due to an EnvironmentError: 404 Client Error: Not Found for url: https://www.piwheels.org/simple/picamraw/

download it and install it manually: Copy the link of the most recent .whl file from https://pypi.org/project/picamraw/#files, download it using wget and install it using pip3, e.g.:

wget https://files.pythonhosted.org/packages/1e/47/4efb0d0ab5d40142424e7f3db545e276733a45bd7f7f9095919ef30c96b3/picamraw-1.2.64-py3-none-any.whl
sudo pip3 install picamraw-1.2.64-py3-none-any.whl

 

Posted by Uli Köhler in Python, Raspberry Pi

How to capture Raspi Camera image using OpenCV & Python

First, install OpenCV for Python 3:

sudo apt install python3-opencv

Here’s the code to acquire the image and store it in image.png:

#!/usr/bin/env python3
import cv2
video_capture = cv2.VideoCapture(0)
# Check success
if not video_capture.isOpened():
    raise Exception("Could not open video device")
# Read picture. ret === True on success
ret, frame = video_capture.read()

cv2.imwrite('image.png', frame)
# Close device
video_capture.release()

Run it using

python3 cv-raspicapture.py

 

Posted by Uli Köhler in OpenCV, Python, Raspberry Pi

How to fix Raspi camera ‘mmal_vc_component_create: failed to create component ‘vc.ril.camera’ (1:ENOMEM)’

Problem:

You are trying to acess the Raspberry Pi camera using raspistill or raspivid, but you see an error message like this:

mmal: Cannot read camera info, keeping the defaults for OV5647
mmal: mmal_vc_component_create: failed to create component 'vc.ril.camera' (1:ENOMEM)
mmal: mmal_component_create_core: could not create component 'vc.ril.camera' (1)
mmal: Failed to create camera component
mmal: main: Failed to create camera component
mmal: Camera is not enabled in this build. Try running "sudo raspi-config" and ensure that "camera" has been enabled

Solution:

The most common issue here is that you don’t have the camera interface enabled. Read How to enable Raspberry Pi camera using raspi-config for instructions on how to do that.

If the camera interface has already been enabled (remember that you need to reboot for the changes to take effect), the most likely reason for error messages like this is that the camera is not connected correctly to the Raspberry Pi:

  • Is the CSI cable inserted the right way? The silvery contacts need to face away from the Ethernet connector!
  • Is the CSI cable fully seated?
  • Did you insert the CSI cable into the Display connector? It needs to be inserted into the CSI connector, which is the one closer to the Ethernet connector.
  • Is the other end of the CSI cable correctly attached to the camera board?
Posted by Uli Köhler in Embedded, Raspberry Pi

How to enable Raspberry Pi camera using raspi-config

You can enable the camera interface by running

sudo raspi-config

Select 5 Interfacing Options and press Return.

Now select P1 Camera and press Return.

Select Yes and press Return.

Now that the camera interface has been enabled, press Return.

Press Tab twice to select Finish and press Return. You are now asked if you want to reboot:

Select Yes and wait for your Raspberry Pi to reboot. Your camera interface will be enabled after the reboot.

In case you are not asked to reboot, your camera interface was already enabled. In this case, select Finish on the main raspi-config screen by pressing Tab twice and pressing Return:

After pressing Return, check your shell again. Reboot (sudo reboot) so that any previous settings will take effect and then try

sudo raspistill -o myimg.jpg

in order to test your camera.

Posted by Uli Köhler in Embedded, Raspberry Pi

How to fix Raspi camera ‘failed to open vchiq instance’

Problem:

You are trying to access the Raspberry Pi camera using raspistill or raspivid. Although you already enabled the camera interface using raspi-config, you see this error message:

* failed to open vchiq instance

Solution:

Your user does not have the permissions to access the camera interface. As a quick fix, you can run raspistill or raspivid as root using sudo, or add your user to the video group to acquire the required permissions:

sudo usermod -a -G video $USER

After doing this, log out and log back in again for the changes to take effect – or close your SSH session and connect again. If in doubt, try to reboot.

Posted by Uli Köhler in Embedded, Raspberry Pi