2024 Update
I recently purchased a Raspberry Pi 5 (4GB) and a replacement Pi 4 for my light-gun project. These notes were originally posted back in 2022 for a 1GB Raspberry Pi 4. I’ve updated the notes for the latest (as of 07/2024) and OpenCV 4.10.0. I’ve also added some notes for the ArduCam B0164 (OV9281) camera.
Preparing the Raspberry Pi
System Updates
The first thing to do is install Raspbian on your Raspberry Pi. I used the Raspberry Pi Imager to install the 64-bit version of the OS.
On first boot, upgrade the packages and reboot.
sudo apt update
sudo apt upgrade
sudo reboot
If necessary, update the EPROM.
sudo rpi-eeprom-update -a
$ *** PREPARING EEPROM UPDATES ***
BOOTLOADER: update available
CURRENT: Wed 11 Jan 17:40:52 UTC 2023 (1673458852)
LATEST: Mon 15 Apr 13:12:14 UTC 2024 (1713186734)
RELEASE: default (/lib/firmware/raspberrypi/bootloader-2711/default)
Use raspi-config to change the release.
VL805_FW: Using bootloader EEPROM
VL805: up to date
CURRENT: 000138c0
LATEST: 000138c0
CURRENT: Wed 11 Jan 17:40:52 UTC 2023 (1673458852)
UPDATE: Mon 15 Apr 13:12:14 UTC 2024 (1713186734)
BOOTFS: /boot/firmware
'/tmp/tmp.Gd5PwuY6WI' -> '/boot/firmware/pieeprom.upd'
Copying recovery.bin to /boot/firmware for EEPROM update
EEPROM updates pending. Please reboot to apply the update.
To cancel a pending update run "sudo rpi-eeprom-update -r".
and reboot again.
sudo reboot
Configure Swap Space (Optional)
Compiling OpenCV can use a lot of memory. This has caused problems for me in the past on lower memory systems. If your Raspbery Pi is a 1GB system, you may want to increase the swap size to help with compiling
- TUrn off the swap
sudo dphys-swapfile swapoff $
- Set the swap size in
/etc/dphys-swapfile
.
CONF_MAXSWAP=2048
- Apply the changes
sudo dphys-swapfile setup $
- Turn swap back on
sudo dphys-swapfile swapon $
YOu can check the amount of swap with `free -m
free -m
$ total used free shared buff/cache available
Mem: 1846 396 828 37 728 1450
Swap: 2047 0 2047
Configuring the ArduCam B0165
For my projects I’m now using an ArduCam B0165. It’s a NoIR, Global SHutter camera that works iwht the Raspberry Pi 4 and 5. They have a quickstart guide. It has some good diagrams for connecting their cameras to different Raspberry Pi models.
The first time I tried it, my Pi wasn’t able to find the B0165.
ggallard@raspberrypi:~ $ libcamera-hello --list
No cameras available!
The docs indicate the B0165 is an OV9281. I had to add
dtoverlay=ov9281
to /boot/firemware/config.txt
and reboot.
This lets libcamera-hello
see the ov9281
ggallard@raspberrypi:~ $ libcamera-hello --list
Available cameras
-----------------
0 : ov9281 [1280x800 10-bit MONO] (/base/soc/i2c0mux/i2c@1/ov9281@60)
Modes: 'R8' : 640x400 [309.79 fps - (0, 0)/1280x800 crop]
1280x720 [171.79 fps - (0, 0)/1280x720 crop]
1280x800 [143.66 fps - (0, 0)/1280x800 crop]
'R10_CSI2P' : 640x400 [247.83 fps - (0, 0)/1280x800 crop]
1280x720 [137.42 fps - (0, 0)/1280x720 crop]
1280x800 [114.93 fps - (0, 0)/1280x800 crop]
Since I’ll be using OpenCV with gstreamer, I installed gstreamer tools to test the camera.
sudo apt install gstreamer1.0-tools
The following pipeline was able to conenct to the camera and display video
gst-launch-1.0 libcamerasrc ! video/x-raw, format=YuY2, width=640, height=480, framerate=30/1 ! videoconvert ! videoscale ! autovideosink
Build and Install OpenCV
- Install Build Tools and Dependencies
sudo apt install cmake
sudo apt install libjpeg-dev libpng-dev libtiff-dev libgif-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-gl libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libgtk-3-dev libopenblas-dev libatlas-base-dev gfortran libblas-dev liblapack-dev
- Download Sources Download the OpenCV source code from GitHub and unpack it
curl -LJO https://github.com/opencv/opencv/archive/refs/tags/4.10.0.tar.gz
tar -xvf opencv-4.10.0.tar.gz
I want some of the modules from contrib, so download OpenCV-Contrib source code from GitHub and unpack it
curl -LJO https://github.com/opencv/opencv_contrib/archive/refs/tags/4.10.0.tar.gz
tar -xvf opencv_contrib-4.10.0.tar.gz
- Configure OpenCV with CMake Change directories into opencv-4.10.0 and create a build directory
cd opencv-4.10.0
mkdir build
cd build
Then run cmake with the following options
cmake -D CMAKE_INSTALL_PREFIX=/usr/local -D ENABLE_NEON=ON -D WITH_OPENMP=ON -D BUILD_TIFF=ON -D WITH_GSTREAMER=ON -D WITH_V4L=ON -D WITH_LIBV4L=ON -D WITH_VTK=OFF -D OPENCV_ENABLE_NONFREE=ON -D INSTALL_C_EXAMPLES=OFF -D BUILD_opencv_python3=OFF -D BUILD_opencv_python2=OFF -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.10.0/modules -D CMAKE_BUILD_TYPE=release ..
More info about the flags are at opencv
- Compile and Install Compile opencv
make -j4
If everything went well, you can install it with
sudo make install
sudo ldconfig
Camera Test
I’m primarily interested in grabbing frames from a camera for image processing. I use the following code to test OpenCV with my camera.
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{// assuming camera 0
//cv::VideoCapture cap(0); // no longer works. Use libcamerasrc
"libcamerasrc ! video/x-raw, width=(int)640, height=(int)480, framerate=(fraction)60/1, format=YUY2 ! videoconvert ! videoscale ! appsink", cv::CAP_GSTREAMER);
cv::VideoCapture cap(
if(!cap.isOpened())
{std::cout << "Error opening cv::VideoCapture" << std::endl;
return -1;
}
// set the frame size to 640x480 for speed
std::cout << "width: " << cap.get( cv::CAP_PROP_FRAME_WIDTH) << "\n";
std::cout << "height: " << cap.get( cv::CAP_PROP_FRAME_HEIGHT) << "\n";
// loop forever
std::cout << "Press 'Q' to quit." << "\n";
while(1)
{
cv::Mat frame;
cap >> frame;if (frame.empty()) {
break;
}"cam", frame );
cv::imshow(auto key = cv::waitKey(1);
// q for quit
if(key == 'q') {
break;
else if ( key == 'w' ) {
} "out.png", frame);
cv::imwrite(
}
}
// cleanup
cap.release(); }
Use CMake to handle the build flags.
cmake_minimum_required(VERSION 3.10)
# set the project name
project(TestOpenCV)
# setup opencv
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIR} )
# add the executable
add_executable( testocv test.cpp)
target_link_libraries( testocv ${OpenCV_LIBS} )
And it works!