JeVois  1.20
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
jevois-camtest.C
Go to the documentation of this file.
1 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4 // California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5 //
6 // This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7 // redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8 // Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10 // License for more details. You should have received a copy of the GNU General Public License along with this program;
11 // if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12 //
13 // Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14 // Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 /*! \file */
17 
18 #include <jevois/Core/Camera.H>
19 #include <jevois/Debug/Log.H>
20 #include <string.h>
21 #include <linux/videodev2.h>
22 #include <opencv2/core/core.hpp>
23 #include <opencv2/imgproc/imgproc.hpp>
24 
25 #ifdef JEVOIS_PLATFORM
26 #include <opencv2/imgcodecs.hpp>
27 #else
28 // On older opencv, imwrite is in highgui:
29 #include <opencv2/highgui/highgui.hpp>
30 #endif
31 
32 // Comment this out to use the jevois::Camera driver instead of low-level V4L2 code:
33 #define USE_RAW_CAMERA
34 
35 #ifdef USE_RAW_CAMERA
36 #define NB_BUFFER 4
37 #include <jevois/Util/Utils.H>
38 #include <sys/mman.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #endif
43 
44 //! Grabs video frames from the camera, and write them to disk as PNG files
45 int main(int argc, char const* argv[])
46 {
47  jevois::logLevel = LOG_DEBUG;
48 
49  if (argc != 5) LFATAL("USAGE: jevois_camtest <YUYV|BAYER|RGB565> <width> <height> <fps>");
50 
51  jevois::VideoMapping m;
52  if (strcmp(argv[1], "BAYER") == 0) m.cfmt = V4L2_PIX_FMT_SRGGB8;
53  else if (strcmp(argv[1], "YUYV") == 0) m.cfmt = V4L2_PIX_FMT_YUYV;
54  else if (strcmp(argv[1], "RGB565") == 0) m.cfmt = V4L2_PIX_FMT_RGB565;
55  else LFATAL("Invalid format, should be BAYER, YUYV or RGB565");
56 
57  m.cw = std::atoi(argv[2]);
58  m.ch = std::atoi(argv[3]);
59  m.cfps = std::atof(argv[4]);
60 
61 #ifdef USE_RAW_CAMERA
62  // Simplest V4L2 capture code, taken from http://staticwave.ca/source/uvccapture/
63  int fd; if ((fd = open ("/dev/video0", O_RDWR)) == -1) LFATAL("ERROR opening V4L interface");
64 
65  // See what kinds of inputs we have and select the first one that is a camera:
66  int camidx = -1; struct v4l2_input inp = { };
67  while (true)
68  {
69  try { XIOCTL(fd, VIDIOC_ENUMINPUT, &inp); } catch (...) { break; }
70  if (inp.type == V4L2_INPUT_TYPE_CAMERA)
71  {
72  if (camidx == -1) camidx = inp.index;
73  LINFO("Input " << inp.index << " [" << inp.name << "] is a camera sensor");
74  } else LINFO("Input " << inp.index << " [" << inp.name << "] is a NOT camera sensor");
75  ++inp.index;
76  }
77  if (camidx == -1) LFATAL("No valid camera input found");
78 
79  // Select the camera input, this seems to be required by VFE for the camera to power on:
80  XIOCTL(fd, VIDIOC_S_INPUT, &camidx);
81 
82  // Check capabilities:
83  struct v4l2_capability cap = { };
84  XIOCTL(fd, VIDIOC_QUERYCAP, &cap);
85  if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) LFATAL("Video capture not supported");
86  if (!(cap.capabilities & V4L2_CAP_STREAMING)) LFATAL("Cameradoes not support streaming i/o");
87 
88  /* set format in */
89  struct v4l2_format fmt = { };
90  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
91  fmt.fmt.pix.width = m.cw;
92  fmt.fmt.pix.height = m.ch;
93  fmt.fmt.pix.pixelformat = m.cfmt;
94  fmt.fmt.pix.field = V4L2_FIELD_ANY;
95  XIOCTL(fd, VIDIOC_S_FMT, &fmt);
96 
97  if ((fmt.fmt.pix.width != m.cw) || (fmt.fmt.pix.height != m.ch)) LFATAL("Format asked unavailable");
98 
99  /* request buffers */
100  struct v4l2_requestbuffers rb = { };
101  rb.count = NB_BUFFER;
102  rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
103  rb.memory = V4L2_MEMORY_MMAP;
104  XIOCTL(fd, VIDIOC_REQBUFS, &rb);
105 
106  /* map the buffers */
107  void * mem[NB_BUFFER];
108  for (int i = 0; i < NB_BUFFER; i++) {
109  struct v4l2_buffer buf = { };
110  buf.index = i;
111  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
112  buf.memory = V4L2_MEMORY_MMAP;
113  XIOCTL(fd, VIDIOC_QUERYBUF, &buf);
114 
115  mem[i] = mmap(0 /* start anywhere */, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
116  if (mem[i] == MAP_FAILED) LFATAL("Unable to map buffer");
117  }
118 
119  /* Queue the buffers. */
120  for (int i = 0; i < NB_BUFFER; ++i) {
121  struct v4l2_buffer buf = { };
122  buf.index = i;
123  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
124  buf.memory = V4L2_MEMORY_MMAP;
125  XIOCTL(fd, VIDIOC_QBUF, &buf);
126  }
127 
128  // start streaming
129  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
130  XIOCTL(fd, VIDIOC_STREAMON, &type);
131  LINFO("Grab start...");
132  for (int i = 0; i < 100; ++i)
133  {
134  struct v4l2_buffer buf = { };
135  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
136  buf.memory = V4L2_MEMORY_MMAP;
137  XIOCTL(fd, VIDIOC_DQBUF, &buf);
138 
139  if (i >= 30)
140  {
141  // FIXME we only support YUYV here for now
142  cv::Mat imgbgr;
143  cv::Mat imgcv(m.ch, m.cw, CV_8UC2, mem[buf.index]);
144  cv::cvtColor(imgcv, imgbgr, cv::COLOR_YUV2BGR_YUYV);
145  cv::imwrite(std::string("camtest") + std::to_string(i-30) + ".png", imgbgr);
146  }
147 
148  XIOCTL(fd, VIDIOC_QBUF, &buf);
149  }
150  LINFO("All done!");
151 
152  // should cleanup, unmap, close, etc
153 
154 #else // USE_RAW_CAMERA
155  std::shared_ptr<jevois::Camera> cam(new jevois::Camera("/dev/video0"));
156  cam->setFormat(m);
157  LINFO("Stream On");
158  cam->streamOn();
159 
160  // First grab a few trash frames to let the auto exposure, gain, white balance, etc stabilize:
161  LINFO("Trashing a few frames...");
162  jevois::RawImage img;
163  for (int i = 0; i < 30; ++i) { cam->get(img); cam->done(img); }
164 
165  // Now grab a few that we convert and save to disk:
166  LINFO("Grab start...");
167  for (int i = 0; i < 10; ++i)
168  {
169  cam->get(img);
170 
171  cv::Mat imgbgr;
172  switch (m.cfmt)
173  {
174  case V4L2_PIX_FMT_SRGGB8:
175  {
176  cv::Mat imgcv(img.height, img.width, CV_8UC1, img.buf->data());
177  cv::cvtColor(imgcv, imgbgr, cv::COLOR_BayerBG2BGR);
178  }
179  break;
180 
181  case V4L2_PIX_FMT_YUYV:
182  {
183  cv::Mat imgcv(img.height, img.width, CV_8UC2, img.buf->data());
184  cv::cvtColor(imgcv, imgbgr, cv::COLOR_YUV2BGR_YUYV);
185  }
186  break;
187 
188  case V4L2_PIX_FMT_RGB565:
189  {
190  cv::Mat imgcv(img.height, img.width, CV_8UC2, img.buf->data());
191  cv::cvtColor(imgcv, imgbgr, cv::COLOR_BGR5652BGR);
192  }
193  break;
194  }
195 
196  cam->done(img);
197  cv::imwrite(std::string("camtest") + std::to_string(i) + ".png", imgbgr);
198  }
199 
200  LINFO("All done!");
201  cam->streamOff();
202  cam.reset();
203 
204 #endif // USE_RAW_CAMERA
205 
206  // Terminate logger:
207  jevois::logEnd();
208 
209  return 0;
210 }
jevois::Camera::done
void done(RawImage &img) override
Indicate that user processing is done with an image previously obtained via get()
Definition: Camera.C:215
NB_BUFFER
#define NB_BUFFER
Definition: jevois-camtest.C:36
jevois::RawImage
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition: RawImage.H:110
jevois::RawImage::width
unsigned int width
Image width in pixels.
Definition: RawImage.H:145
Log.H
main
int main(int argc, char const *argv[])
Grabs video frames from the camera, and write them to disk as PNG files.
Definition: jevois-camtest.C:45
jevois::Camera::get
void get(RawImage &img) override
Get the next captured buffer.
Definition: Camera.C:190
LFATAL
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
jevois::Camera::streamOn
void streamOn() override
Start streaming.
Definition: Camera.C:163
Camera.H
jevois::RawImage::height
unsigned int height
Image height in pixels.
Definition: RawImage.H:146
jevois::to_string
std::string to_string(T const &val)
Convert from type to string.
jevois::Camera::setFormat
void setFormat(VideoMapping const &m) override
Set the video format and frame rate.
Definition: Camera.C:49
jevois::logLevel
int logLevel
Current log level.
Definition: Log.C:29
jevois::Camera::streamOff
void streamOff() override
Stop streaming.
Definition: Camera.C:181
Utils.H
jevois::RawImage::buf
std::shared_ptr< VideoBuf > buf
The pixel data buffer.
Definition: RawImage.H:149
jevois::logEnd
void logEnd()
Terminate log service.
Definition: Log.C:125
jevois::Camera
JeVois camera driver class - grabs frames from a Video4Linux camera sensor.
Definition: Camera.H:62
LINFO
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition: Log.H:194