I have a lot of video devices in my /dev
folder (e.g. video1
, video2
, ..., video9
) and one /dev/video
which
The best thing is to parse the ID of the device.
#include <regex>
#include <boost/filesystem.hpp>
...
boost::filesystem::path path( "/dev/video3" );
auto target = boost::filesystem::canonical(path).string();
std::regex exp( ".*video(\\d+)" );
std::smatch match;
std::regex_search( target, match, exp );
auto id = strtod( match[1] );
auto cap = cv::VideoCapture( id );
Note the use of canonical()
to make the path absolute and resolve any symbolic links. This way it works even if you give it v4l device paths from /dev/v4l/by-id
or /dev/v4l/by-path
like for example:
"/dev/v4l/by-id/usb-046d_0990_1188AD49-video-index0"
"/dev/v4l/by-path/pci-0000:00:13.2-usb-0:4.4.4:1.0-video-index0"
with current OpenCV 3.2.0 you can create a new capture like this:
cv::VideoCapture cap("/dev/video20", cv::CAP_V4L);
its one of the additional constructors:
VideoCapture (const String &filename, int apiPreference)
Open video file or a capturing device or a IP video stream for video capturing with API Preference.
this is also possible with the open function:
cap.open("/dev/video20", cv::CAP_V4L);
i have tested this successfully under Kubuntu 16.10 with self compiled openCV from current git master.
By looking at the source code of OpenCV 2.4.11 (cap.cpp) you can see that the overload using const string& filename is calling 'cvCreateFileCapture' which uses other plugins as FFMPEG or GStreamer to load files so the answer is no.
bool VideoCapture::open(const string& filename)
{
if (isOpened()) release();
cap = cvCreateFileCapture(filename.c_str());
return isOpened();
}