We use some essential cookies to make our website work.

We use optional cookies, as detailed in our cookie policy, to remember your settings and understand how you use our website.

Raspberry Pi Camera Module: Still image capture

This #MagPiMonday we bring you this in-depth guide to the Raspberry Pi Camera Module’s still image capture modes and settings.

The High Quality Camera Module is focused manually; the new Camera Module 3 has autofocus that can be controlled in software
The High Quality Camera Module is focused manually; the new Camera Module 3 has autofocus that can be controlled in software

In The MagPi #129 we introduced libcamera-still which allows us to capture still images. But it also has many more options controlling how it captures images, and the file formats and available image encoders. We’ll discover some of those in this tutorial. For now, we shall continue to assume that you have your keyboard and a monitor plugged directly into your Raspberry Pi.

Capturing images at different resolutions

By default, libcamera-still will capture images at the maximum available resolution supported by the camera. For the HQ Camera, for example, this means images that are 4056×3040 pixels in size. But it’s easy to change this with the --width and --height parameters. For example, if you want to capture an image that is 1536×1024 pixels instead, you should use:

libcamera-still --width 1536 --height 1024 -o smaller.jpg

Autofocus is available on Raspberry Pi Camera Module 3, enabling you to focus in on specific parts of an image
Autofocus is available on Raspberry Pi Camera Module 3, enabling you to focus in on specific parts of an image

Image encoders and file formats

Images are normally encoded in some way (often they are compressed so that they aren’t so large) and then saved to a standard file format on the disk.

JPEG files

The default file format used by libcamera-still is JPEG because of the very wide support that it has, combined with a useful level of compression. Usually, JPEG files are given the extension .jpg, or sometimes .jpeg, as we have already seen.

JPEG is a lossy compression format, meaning that the result of loading your JPEG file is no longer identical to the image that you started from, though the differences are arranged to be ones that you will least notice. In return, you get to specify a quality factor indicating how much compression you want. At very low values your image will indeed deteriorate, but at very high values the JPEG process will be visually lossless; that is, it really will look as good as the original camera image.

The quality factor ranges from 1 to 99, and if you don’t give one it will choose the value 93, which equates informally to ‘quite high quality’. To save a JPEG at a different quality level, use the -q (or equivalently --quality) parameter like this:

libcamera-still -q 80 -o test.jpg

Experiment with quality values like 10 and 50 to see what you get!

PNG files

PNG (or ‘Portable Network Graphic’) is another file and compression format which enjoys wide support. PNG is a lossless compression format, meaning that you are guaranteed to be able to recover exactly the same image that you started from (unlike JPEG). On the downside, PNG files are normally larger than JPEG files, and they are harder work to create, which takes longer.

To save a PNG file, you’ll need to tell libcamera-still that you want to use a different encoder using the -e or --encoder parameter, like this:

libcamera-still -e png -o test.png

Note that it’s necessary to specify the -e option to get a PNG file – changing the file name on its own is not enough. PNG does not support a quality parameter.

DNG files

DNG, or ‘Digital NeGative’, files are quite different from PNG files. As the full name suggests, they’re somewhat analogous to the ‘negatives’ we had from film cameras before developing them into photos. In our case, the DNG file stores the raw numbers received from the image sensor before the hardware on Raspberry Pi ‘develops’ it into a viewable (JPEG or PNG) image. DNG files are saved alongside the ‘developed’ JPEG or PNG version of the same image. To save a DNG file, use the -r (or --raw) parameter:

libcamera-still -r test.jpg

libcamera-still will automatically replace .jpg by .dng in the DNG file name, giving both test.dng and test.jpg in this case.

Many third-party software programs exist to ‘develop’ these DNG files interactively – a rather complex procedure beyond the scope of this guide.

Time-lapse captures

A time-lapse capture is where we capture an image at regular intervals, perhaps every minute, hour or day, and then reassemble them into a video where we play them back at a much faster rate. libcamera-still is all set up to capture the images we need out of the box.

Raspberry Pi Camera Modules are capable of capturing images in a variety of different formats including JPEG, PNG, and DNG
Raspberry Pi Camera Modules are capable of capturing images in a variety of different formats including JPEG, PNG, and DNG

We need to introduce the --timelapse option and we’ll review a couple that we’ve seen before.

-t or –timeout. The length of time in milliseconds for which to perform a capture. In the case of timelapse, libcamera-still will run capturing images in total for this duration. You can pass the value 0 which means ‘run indefinitely’ (you will have to stop libcamera-still manually, for example by pressing CTRL+C on the keyboard).

–timelapse. The length of time, again in milliseconds, between each of the time-lapse captures.

-o or –output. The name of the output file or files. For time-lapse captures, we can’t give all the images the same name so we use a special syntax that includes an image counter. For example, -o capture_%04d.jpg means that all the files are named ‘capture_’, followed by a counter, and then .jpg. %04d specifies how the counter is formatted, in this case the 0 means to add leading zeroes to the number and the 4 means ‘so that every number has at least 4 digits’. This is useful so that listing your image files will return them to you in chronological order.

Let’s try an example.

libcamera-still -o capture_%04d.jpg
--timelapse 5000 -t 30000 --width 1024
--height 768

This will run for 30 seconds, capturing an image every 5 seconds, and they’ll be called capture_0000.jpg through to capture_0004.jpg.
Note how we’ve reduced the resolution of the images to something that is more appropriate to the final video that we want to create.

Assembling your Images into a Video

There’s a handy tool called FFmpeg which is capable of turning your sequence of still images into a video. We can use it like this:

ffmpeg -r 2 -i capture_%04d.jpg video.mp4

Note how we format the name of the input files with the special % syntax in the same way as we did for libcamera-still. The -r parameter gives the frame rate of the output video, 2 frames per second in this case. We’ve chosen the output file to have the MP4 format and called it video.mp4.

FFmpeg is a highly versatile tool that we recommend learning about.

Capturing when a key is pressed

Rather than doing regular captures, we can also do them in response to an event, or a key press. There are a couple of new option parameters to learn.

–datetime. Use this instead of -o to name the output file after the current date and time. The format will be MMDDhhmmss.jpg, where MM and DD are the month and date number, and hh, mm and ss are hours, minutes and seconds.

-k or –keypress. Capture an image when ENTER is pressed on the keyboard. Type X and press ENTER to quit.

So the command to use is this:

libcamera-still -t 0 --keypress --datetime

Here we’re running the capture indefinitely, so we’ll have to type X followed by ENTER to quit (or press CTRL+C). Files would have names like 0405102742.jpg, meaning ‘10:27am, and 42 seconds, on 5 April’.

Capturing in response to a signal

For those familiar with Linux signals, an alternative to pressing a key is to send a signal instead. To do this, simply use -s or --signal instead of -k (or --keypress).

To send a capture signal to libcamera-still, first start it and then type the following into another terminal window:

kill -SIGUSR1 `pidof libcamera-still`

And you can force libcamera-still to quit with:

kill -SIGUSR2 `pidof libcamera-still`

HDR (high dynamic range) can be activated on Camera Module 3 to enable higher levels of contrast in your captured images
HDR (high dynamic range) can be activated on Camera Module 3 to enable higher levels of contrast in your captured images

Autofocus and High Dynamic Range

Autofocus and High Dynamic Range imaging are supported at the time of writing only on Raspberry Pi Camera Module 3.

Autofocus

When using the Camera Module 3, autofocus is enabled automatically in continuous mode. This means that the camera lens will move whenever necessary to maintain optimal focus on the centre part of the image, and this is probably what most users will want most of the time.

It’s also possible to turn off autofocus and set the focus position of the lens manually. To do this, use the --lens-position parameter, and pass it a value measured in dioptres, meaning the reciprocal of the focus distance. Thus, to focus at a very close distance of about 0.1 m, pass in the value 10 (which is 1 / 0.1). To focus at infinity, pass in 0 (informally, the value of 1 / infinity). You can pass in non-integer values too. For example:

libcamera-still --lens-position 0 -o infinity.jpg

…will set the focus position to infinity and not move the lens again.

High Dynamic Range imaging

The Camera Module 3 supports High Dynamic Range (HDR) imaging. To use it, specify the --hdr option on the command line, for example:

libcamera-still --hdr -o hdr.jpg

Note that non-HDR captures can be performed at a maximum resolution of 4608×2592 pixels, but HDR captures, because of the special nature of the sensor required to support HDR, are limited to 2304×1296 pixels (exactly half the width and height of the non-HDR mode).

The MagPi #130 out NOW!

You can grab the brand-new issue right now from Tesco, Sainsbury’s, Asda, WHSmith, and other newsagents, including the Raspberry Pi Store in Cambridge. It’s also available at our online store which ships around the world. You can also get it via our app on Android or iOS.

magpi 130

You can also subscribe to the print version of The MagPi. Not only do we deliver it globally, but people who sign up to the six- or twelve-month print subscription get a FREE Raspberry Pi Pico W!

2 comments

Joce Boissin avatar

Are there plans for you to expand to a standard video format with this – e.g. 24 frames per second? Is that achievable?

S O avatar

A jpg image is 8bit per channel (24bit RGB) and definitionally *not* “HDR”, the extra data captured is thrown out in to process of approximating whatever canned contrast profile is being used. Ideally you would use the DNG format to actually capture this data, or alternatively 16-32 bit per channel integer or floating point PNG (does libcamera even support this?).

Comments are closed