Raspberry Pi 在Jupyterlab中显示摄像头画面

实现在Jupyter NoteBook上实时显示当前摄像头的图像

使用v4l2-ctl查看摄像头信息

!v4l2-ctl -d 0 -l

v4l2-ctl是一个命令行工具,它用于与Linux中的Video4Linux2系统进行交互。Video4Linux2简称V4L2,是Linux操作系统中处理视频设备的内核驱动。

v4l2-ctl帮助您执行各种操作,例如列出可用的视频设备,查询或更改视频设备的设置等。例如,您可以使用它来更改摄像头的分辨率,设置视频输入等。

具体地说,一些常见的使用v4l2-ctl的命令包括:

  • v4l2-ctl --list-devices 用于列出系统中所有可用的视频设备。
  • v4l2-ctl --set-fmt-video=width=640,height=480,pixelformat=1用于设置视频设备的分辨率和像素格式等属性。
  • v4l2-ctl --all用于显示所有关于设备的信息,包括驱动,功能,视频和音频标准等。

简单来说,v4l2-ctl是Linux中一个非常有用的工具,对于需要管理和配置视频设备的用户们来说。它提供了直观且易于使用的命令行界面,使得视频设备的管理和配置变得更容易。

遇到错误提示:v4l2-ctl: command not found 解决办法

这是个错误,是因为没有安装v4l2-ctl所导致的,在对应的操作系统中输入命令,安装即可:

Debian OS

apt-get install v4l-utils

Ubuntu OS

apt-get install v4l-utils

Alpine OS

apk add v4l-utils

Arch Linux

pacman -S v4l-utils

Kali Linux

apt-get install v4l-utils

CentOS

yum install v4l-utils

Fedora

dnf install v4l-utils

Windows (WSL2)

sudo apt-get update sudo apt-get install v4l-utils

Raspbian

apt-get install v4l-utils

安装后再次尝试该命令,则会返回当前摄像头的所有信息。

实时显示摄像头NoteBook 代码

这段代码是一个Python程序,用于创建并控制一个Camera的类对象,获取来自一个视频设备(例如网络摄像头)的画面。

import traitlets
from traitlets.config.configurable import SingletonConfigurable
import numpy as np
import enum
import cv2
import ipywidgets.widgets as widgets
from IPython.display import display
import atexit
import threading

import matplotlib.pyplot as plt

# 将图像从BGR格式转为JPEG格式的函数
def bgr8_to_jpeg(value, quality=10):
        return bytes(cv2.imencode('.jpg', value)[1])

# 这是定义了一个名为Camera的类,
# 它继承自SingletonConfigurable类。
# SingletonConfigurable 类是 traitlets 模块提供的一个基类,用来产生单例类。
# 同一时间只会存在一个这个类的实例。
class Camera(SingletonConfigurable):
    value = traitlets.Any()

    def __init__(self):
        try:
            # 创建一个 cv2.VideoCapture 的实例,
            # 用于从摄像头捕获视频。
            # 其中的数字 0 具体代表系统的哪个摄像头可能会依据实际环境有差异,通常0代表默认的摄像头。
            self.cap = cv2.VideoCapture(0)

            # 通过调用 VideoCapture 实例的 read() 方法,来获取摄像头的一帧图像。
            re, image = self.cap.read()

            if not re:
                raise RuntimeError('Could not read image from camera.')

            # 设置Camera类的value属性,将其值设置为获取到的一帧图像。
            self.value = image
            self.start()
        except:
            self.stop()
            raise RuntimeError(
                'Could not initialize camera.  Please see error trace.')

        atexit.register(self.stop)

    # 这部分是一个定义在Camera类内部的方法,
    # 用于在独立的线程中,持续地从摄像头获取画面。    
    def _capture_frames(self):
        while True:
            re, image = self.cap.read()
            if re:
                self.value = image
            else:
                break    

    def start(self):
#         if not self.cap.isOpened():
#             self.cap.open(self._gst_str(), cv2.CAP_GSTREAMER)
        if not hasattr(self, 'thread') or not self.thread.isAlive():
                    # 启动一个新的线程,用于连续获取摄像头的画面。
            self.thread = threading.Thread(target=self._capture_frames)
            self.thread.start()

    def stop(self):
        if hasattr(self, 'cap'):
            self.cap.release()
        if hasattr(self, 'thread'):
            self.thread.join()

# 创建一个 Image组件,用于在Jupyter Notebook中显示摄像头的画面。
# 这里的宽度和高度不一定要与摄像机匹配,代表着在浏览器中显示的宽度和高度
image = widgets.Image(format='jpeg', width=500, height=500)  

camera = Camera()

# 使用traitlets库的dlink函数,
# 实现camera的value属性和image的value属性之间的双向绑定,
# 当camera.value发生改变时,image.value也会自动更新。
# 其中 bgr8_to_jpeg 是一个将图像从BGR格式转为JPEG格式的函数。
traitlets.dlink((camera, 'value'), (image, 'value'), transform=bgr8_to_jpeg)

display(image)

camera.stop()

总的来说,这段代码创建了一个Camera类,用于控制并获取摄像头的画面,并在Jupyter Notebook上实时显示出来。其中使用到了 OpenCV(用于图片获取和处理), traitlets(用于创建类和属性绑定), ipywidgets(用于创建图片组件), threading(用于创建新的线程)。

把代码复制到Jupyte Notebook上就可以实现查看摄像头了。