Introduction

備忘録。

Windows だと何も考えずにカメラを使えるが、Linux ではそうもいかない。
例えば、下記のようなコードも

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>

int32_t main(int32_t argc, const char** argv)
{
cv::VideoCapture cap(0, cv::CAP_V4L2);
if(!cap.isOpened())
return -1;

std::cout << "BackendName: " << cap.getBackendName() << std::endl;

cv::Mat frame;
while(cap.read(frame))
std::cout << "w: " << frame.cols << ", h: " << frame.rows << std::endl;

return 0;
}

実行すれば

1
2
[ WARN:0] global ../modules/videoio/src/cap_v4l.cpp (887) open VIDEOIO(V4L2:/dev/video1): can't open camera by index
~/Work/test

こんな感じでエラー。

Why?

単純に権限がない。
Linux の場合、カメラデバイスはデバイスファイルとして /dev/video0/dev/video1 として認識される。
これらの権限が

1
2
3
$ ls -la /dev/video*
crw-rw----+ 1 root video 81, 0 2月 3 23:35 /dev/video0
crw-rw----+ 1 root video 81, 1 2月 3 23:35 /dev/video1

のようになっており、オープンするには

  • root ユーザ
  • video グループに所属

である必要がある。

How to resolve?

今回は video グループに追加する。

1
$ sudo usermod -aG video $USER

ちなみにグループに追加後は再度ログインしなおす必要があるので、リモートならつなぎなおす等する。
だが、Visual Studio Code のリモート接続を使用している場合、つなぎなおしても、セッションが維持されているのか反映されない。

video グループに追加後

1
2
3
4
5
6
7
8
9
$ ./camera 
BackendName: V4L2
w: 640, h: 480
w: 640, h: 480
w: 640, h: 480
w: 640, h: 480
w: 640, h: 480
w: 640, h: 480
w: 640, h: 480

Not friendly!

そもそも、エラーの内容が不親切。
デバイスファイルを開けないので、can't open camera by index というのはわかるが、これではまるで指定したデバイス ID が間違っているかのような印象を受ける。

ちなみにバックエンドに Gstreamer を指定した場合も似たような感じ。

1
2
3
[ WARN:0] global ../modules/videoio/src/cap_gstreamer.cpp (1758) handleMessage OpenCV | GStreamer warning: Embedded video playback halted; module v4l2src0 reported: Could not open device '/dev/video0' for reading and writing.
[ WARN:0] global ../modules/videoio/src/cap_gstreamer.cpp (888) open OpenCV | GStreamer warning: unable to start pipeline
[ WARN:0] global ../modules/videoio/src/cap_gstreamer.cpp (480) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created

せめて、デバイスファイルは存在しているから権限がないよ、くらいは教えて欲しい。

ただ、v4l2-ctl でデバイスの確認をするとき、video グループに所属していなかったりすると

1
2
$ v4l2-ctl --list-devices
Failed to open /dev/video0: Permission denied

ちゃんと権限がないことを教えてくれる。