К содержимому
  1. Главная
  2. Документация
  3. USB-камеры UVC
  4. Доступ к камерам UVC через OpenCV, Python и GStreamer в Linux

Доступ к камерам UVC через OpenCV, Python и GStreamer в Linux

Документация Arducam · перевод arducam-russia.ru

Общие сведения

Камеры Arducam UVC работают по стандарту UVC, поэтому драйверы не нужны и камеры сразу работают с приложениями для веб-камер. Но опытным пользователям для задач машинного зрения и ИИ может понадобиться собственный код на Python и OpenCV с расширенным управлением камерой. Ниже подробно описано, как открыть камеру Arducam UVC и управлять ею.

Работа в Linux

1. Видеоузел, поддерживаемые разрешения и частота кадров

Перед тем как открыть камеру UVC, определите нужный видеоузел.

ls /dev/video*
Список видеоузлов /dev/video*

Обычно у камер с кодированием H.264 два или четыре видеоузла:

  • если узлов два, video0 выдаёт YUV, MJPEG и т. д., а video1 — H.264;
  • если узлов четыре, video0 выдаёт YUV, MJPEG и т. д., а video2 — H.264.

Посмотреть поддерживаемые форматы можно командой:

v4l2-ctl --list-formats -d 0 # 0 is video0

Ниже — пример для камеры UVC с четырьмя видеоузлами.

Форматы видеоузла камеры UVC (1)
Форматы видеоузла камеры UVC (2)

При необходимости проверьте разрешения и частоту кадров для каждого формата командой:

v4l2-ctl --list-formats-ext -d 0 # 0 is video0
Разрешения и частота кадров форматов камеры (1)
Разрешения и частота кадров форматов камеры (2)

2. Доступ к камере и управление через OpenCV

Откройте камеру через OpenCV на Python (OpenCV устанавливается через pip: pip install OpenCV-python).

import cv2

# open video0
cap = cv2.VideoCapture(0)

# The control range can be viewed through v4l2-ctl -L
cap.set(cv2.CAP_PROP_BRIGHTNESS, 64)
cap.set(cv2.CAP_PROP_CONTRAST, 0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # Display the resulting frame
    cv2.imshow('frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

Пример вывода v4l2-ctl -L.

Вывод команды v4l2-ctl -L с параметрами камеры

Ручная фокусировка камеры с автофокусом через OpenCV

Включить ручную фокусировку на камере с автофокусом можно двумя способами:

1. Значения задаются в коде

import cv2
import time
# open video0
cap = cv2.VideoCapture(0)
cap.grab()

cap.set(cv2.CAP_PROP_AUTOFOCUS, 1)
time.sleep(2)
cap.set(cv2.CAP_PROP_AUTOFOCUS, 0)
time.sleep(2)
cap.set(cv2.CAP_PROP_FOCUS, 123)


cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # Display the resulting frame
    cv2.imshow('frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

2. Значения задаются через графический интерфейс

import cv2
import argparse
import configparser
from pathlib import Path
import time


parser = argparse.ArgumentParser()
parser.add_argument("-v", "--vid", default="0", help="Video sourse, default 0")
parser.add_argument(
    "-f", "--auto_focus", action="store_true", default=False, help="Turn on auto focus"
)
parser.add_argument(
    "-c",
    "--config",
    default="focus.ini",
    help="Focus config file, default focus.ini",
)
args = parser.parse_args()

try:
    vid = int(args.vid)
except ValueError:
    vid = args.vid

config_path = (Path(__file__).parent / Path(args.config)).resolve().absolute()
print("config file :", config_path)

config = configparser.ConfigParser()

config.read(config_path, encoding="utf-8")

cap = cv2.VideoCapture(vid)
cap.grab()
cap.set(cv2.CAP_PROP_AUTOFOCUS, 1)

if not args.auto_focus and config.has_section("Focus"):
    auto_focus = (
        config.getint("Focus", "auto_focus")
        if config.has_option("Focus", "auto_focus")
        else 1
    )
    focus = (
        config.getint("Focus", "focus")
        if config.has_option("Focus", "focus")
        else int(cap.get(cv2.CAP_PROP_FOCUS))
    )
else:
    auto_focus = 1
    focus = None
print("config auto_focus = %s" % auto_focus)
print("config focus = %s" % focus)
print("*" * 10)


if not auto_focus:
    cap.set(cv2.CAP_PROP_AUTOFOCUS, 0)

time.sleep(2)
if focus:
    cap.set(cv2.CAP_PROP_FOCUS, focus)

cv2.namedWindow("frame")


def set_auto_focus(x):
    cap.set(cv2.CAP_PROP_AUTOFOCUS, x)


cv2.createTrackbar(
    "0: OFF\r\n 1: ON\r\nauto_focus",
    "frame",
    int(cap.get(cv2.CAP_PROP_AUTOFOCUS)),
    1,
    set_auto_focus,
)


def set_focus(x):
    cap.set(cv2.CAP_PROP_FOCUS, x)


cv2.createTrackbar("focus", "frame", int(cap.get(cv2.CAP_PROP_FOCUS)), 1023, set_focus)

while cap.isOpened():
    # cap frame-by-frame
    ret, frame = cap.read()
    if not ret:
        break
    focus = int(cap.get(cv2.CAP_PROP_FOCUS))
    cv2.setTrackbarPos("focus", "frame", focus)

    af = int(cap.get(cv2.CAP_PROP_AUTOFOCUS))
    cv2.setTrackbarPos("0: OFF\r\n 1: ON\r\nauto_focus", "frame", af)

    cv2.imshow("frame", frame)

    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

# When everything done, release the cap
cap.release()
cv2.destroyAllWindows()

if not config.has_section("Focus"):
    config.add_section("Focus")

print("set auto_focus = 0")
config.set("Focus", "auto_focus", "0")

print("set focus = %s" % focus)
config.set("Focus", "focus", str(focus))

config.write(open(config_path, "w"))

3. Доступ к нескольким камерам UVC

Иногда нужно подключить несколько камер UVC одновременно, но их трудно различить. У каждой камеры Arducam UVC есть собственный серийный номер, не повторяющийся у других камер; по нему её можно распознать и управлять ею отдельно. Ниже — два способа узнать серийный номер.

Через видеоузел

sudo udevadm info --query=all /dev/video0 | grep 'VENDOR_ID\|MODEL_ID\|SERIAL_SHORT'
Серийный номер камеры в выводе udevadm

Через Python

Установите зависимости:

sudo pip3 install pyudev

Код:

import pyudev
def getSerialNumber(device = 0):
    context = pyudev.Context()
    device_file = "/dev/video{}".format(device)
    device = pyudev.Devices.from_device_file(context, device_file)
    info = { item[0] : item[1] for item in device.items()}
    return info["ID_SERIAL_SHORT"]
Серийный номер камеры, полученный через pyudev
ПримечаниеЕсли нужен другой серийный номер, напишите нам на quote@arducam-russia.ru.

4. Трансляция видео через GStreamer

GStreamer — популярный открытый мультимедийный фреймворк. Его высокоуровневые API позволяют строить собственные приложения для трансляции, воспроизведения и монтажа видео с разными кодеками и функциями.

ПримечаниеПодробнее о форматах видеоузлов — в разделе «Видеоузел, поддерживаемые разрешения и частота кадров».

Формат видео

Камера выдаёт видео в трёх форматах.

MJPEG (формат вывода video0):

gst-launch-1.0 v4l2src device=/dev/video0 ! \
    image/jpeg,width=1280,height=720,framerate=30/1 ! \
    decodebin ! autovideosink

YUV (формат вывода video0):

gst-launch-1.0 -vv v4l2src device=/dev/video0 ! \
    video/x-raw,format=YUY2,width=1280,height=720,framerate=10/1 ! \
    videoconvert ! autovideosink

H.264 (формат вывода video2):

gst-launch-1.0 v4l2src device=/dev/video2 ! queue ! \<br>video/x-h264,width=1280,height=720,framerate=30/1 ! \<br>avdec_h264 ! autovideosink

Трансляция

В отличие от сжатых форматов MJPEG и H.264, YUV даёт большой объём данных и для трансляции не подходит.

MJPEG:

# server
gst-launch-1.0 v4l2src device=/dev/video0 ! \
    image/jpeg,width=1280,height=720,framerate=30/1 ! \
    tcpserversink host=0.0.0.0 port=5001

# client 
# change xxx.xxx.xxx.xxx to the actual ip address
gst-launch-1.0 -v tcpclientsrc host=xxx.xxx.xxx.xxx port=5001 ! \
    decodebin ! autovideosink

H.264:

# server
gst-launch-1.0 v4l2src device=/dev/video2 ! queue ! \
    video/x-h264,width=1280,height=720,framerate=30/1 ! \
    rtph264pay ! gdppay  ! tcpserversink host=0.0.0.0 port=5001

# client
# change xxx.xxx.xxx.xxx to the actual ip address
gst-launch-1.0 -v tcpclientsrc host=xxx.xxx.xxx.xxx port=5001 ! \
    gdpdepay ! rtph264depay ! avdec_h264 ! autovideosink

Работа с камерой

Запись видео:

gst-launch-1.0 v4l2src device=/dev/video0 ! image/jpeg,width=1280,height=720,framerate=30/1 ! jpegdec ! x264enc ! qtmux ! filesink location=test.mp4 -e

Сохранение снимка:

gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=1 ! jpegenc ! filesink sync=false location=file.jpg

Просмотр:

gst-launch-1.0 v4l2src device=/dev/video0 ! image/jpeg,width=1280,height=720,framerate=30/1 ! jpegdec ! autovideosink

Запросить цену

Укажите количество — пришлём коммерческое предложение.