JeVois  1.8
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Utils.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/Util/Utils.H>
19 #include <jevois/Debug/Log.H>
20 
21 #include <linux/videodev2.h>
22 #include <string>
23 #include <vector>
24 #include <regex>
25 
26 #include <string.h> // for strncmp
27 #include <fstream>
28 #include <cstdarg> // for va_start, etc
29 #include <cstdio>
30 #include <iostream>
31 #include <memory>
32 #include <stdexcept>
33 #include <array>
34 #include <cctype> // for std::isspace()
35 
36 #include <opencv2/core/hal/interface.h> // for CV_MAT_DEPTH_MASK
37 
38 // ####################################################################################################
39 std::string jevois::fccstr(unsigned int fcc)
40 {
41  if (fcc == 0) return "NONE"; // for no video over USB output
42 
43  std::string ret(" ");
44  ret[0] = static_cast<char>(fcc & 0xff);
45  ret[1] = static_cast<char>((fcc >> 8) & 0xff);
46  ret[2] = static_cast<char>((fcc >> 16) & 0xff);
47  ret[3] = static_cast<char>((fcc >> 24) & 0xff);
48  return ret;
49 }
50 
51 // ####################################################################################################
52 std::string jevois::cvtypestr(unsigned int cvtype)
53 {
54  // From: https://gist.github.com/rummanwaqar/cdaddd5a175f617c0b107d353fd33695
55  std::string r;
56 
57  uchar depth = cvtype & CV_MAT_DEPTH_MASK;
58  uchar chans = 1 + (cvtype >> CV_CN_SHIFT);
59 
60  switch (depth)
61  {
62  case CV_8U: r = "8U"; break;
63  case CV_8S: r = "8S"; break;
64  case CV_16U: r = "16U"; break;
65  case CV_16S: r = "16S"; break;
66  case CV_32S: r = "32S"; break;
67  case CV_32F: r = "32F"; break;
68  case CV_64F: r = "64F"; break;
69  default: r = "User"; break;
70  }
71 
72  r += 'C';
73  r += (chans + '0');
74 
75  return r;
76 }
77 
78 // ####################################################################################################
79 unsigned int jevois::strfcc(std::string const & str)
80 {
81  if (str == "BAYER") return V4L2_PIX_FMT_SRGGB8;
82  else if (str == "YUYV") return V4L2_PIX_FMT_YUYV;
83  else if (str == "GREY" || str == "GRAY") return V4L2_PIX_FMT_GREY;
84  else if (str == "MJPG") return V4L2_PIX_FMT_MJPEG;
85  else if (str == "RGB565") return V4L2_PIX_FMT_RGB565;
86  else if (str == "BGR24") return V4L2_PIX_FMT_BGR24;
87  else if (str == "NONE") return 0;
88  else throw std::runtime_error("Invalid pixel format " + str);
89 }
90 
91 // ####################################################################################################
92 unsigned int jevois::v4l2BytesPerPix(unsigned int fcc)
93 {
94  switch (fcc)
95  {
96  case V4L2_PIX_FMT_YUYV: return 2U;
97  case V4L2_PIX_FMT_GREY: return 1U;
98  case V4L2_PIX_FMT_SRGGB8: return 1U;
99  case V4L2_PIX_FMT_RGB565: return 2U;
100  case V4L2_PIX_FMT_MJPEG: return 2U; // at most??
101  case V4L2_PIX_FMT_BGR24: return 3U;
102  case 0: return 0U; // for NONE output to USB mode
103  default: LFATAL("Unsupported pixel format " << jevois::fccstr(fcc));
104  }
105 }
106 
107 // ####################################################################################################
108 unsigned int jevois::v4l2ImageSize(unsigned int fcc, unsigned int width, unsigned int height)
109 { return width * height * jevois::v4l2BytesPerPix(fcc); }
110 
111 // ####################################################################################################
112 unsigned int jevois::blackColor(unsigned int fcc)
113 {
114  switch (fcc)
115  {
116  case V4L2_PIX_FMT_YUYV: return 0x8000;
117  case V4L2_PIX_FMT_GREY: return 0;
118  case V4L2_PIX_FMT_SRGGB8: return 0;
119  case V4L2_PIX_FMT_RGB565: return 0;
120  case V4L2_PIX_FMT_MJPEG: return 0;
121  case V4L2_PIX_FMT_BGR24: return 0;
122  default: LFATAL("Unsupported pixel format " << jevois::fccstr(fcc));
123  }
124 }
125 
126 // ####################################################################################################
127 unsigned int jevois::whiteColor(unsigned int fcc)
128 {
129  switch (fcc)
130  {
131  case V4L2_PIX_FMT_YUYV: return 0x80ff;
132  case V4L2_PIX_FMT_GREY: return 0xff;
133  case V4L2_PIX_FMT_SRGGB8: return 0xff;
134  case V4L2_PIX_FMT_RGB565: return 0xffff;
135  case V4L2_PIX_FMT_MJPEG: return 0xff;
136  case V4L2_PIX_FMT_BGR24: return 0xffffff;
137  default: LFATAL("Unsupported pixel format " << jevois::fccstr(fcc));
138  }
139 }
140 
141 // ####################################################################################################
142 std::vector<std::string> jevois::split(std::string const & input, std::string const & regex)
143 {
144  // This code is from: http://stackoverflow.com/questions/9435385/split-a-string-using-c11
145  // passing -1 as the submatch index parameter performs splitting
146  std::regex re(regex);
147  std::sregex_token_iterator first{input.begin(), input.end(), re, -1}, last;
148  return { first, last };
149 }
150 
151 // ####################################################################################################
152 std::string jevois::join(std::vector<std::string> const & strings, std::string const & delimiter)
153 {
154  if (strings.empty()) return "";
155  if (strings.size() == 1) return strings[0];
156 
157  std::string ret; size_t const szm1 = strings.size() - 1;
158 
159  for (size_t i = 0; i < szm1; ++i) ret += strings[i] + delimiter;
160  ret += strings[szm1];
161 
162  return ret;
163 }
164 
165 // ####################################################################################################
166 bool jevois::stringStartsWith(std::string const & str, std::string const & prefix)
167 {
168  return (strncmp(str.c_str(), prefix.c_str(), prefix.length()) == 0);
169 }
170 
171 // ####################################################################################################
172 std::string jevois::replaceWhitespace(std::string const & str, char rep)
173 {
174  std::string ret = str;
175  for (char & c : ret) if (std::isspace(c)) c = rep;
176  return ret;
177 }
178 
179 // ####################################################################################################
180 std::string jevois::strip(std::string const & str)
181 {
182  int idx = str.length() - 1;
183  while (idx >= 0 && std::isspace(str[idx])) --idx;
184  return str.substr(0, idx + 1);
185 }
186 
187 // ####################################################################################################
188 namespace
189 {
190  // This code is from NRT, and before that from the iLab C++ neuromorphic vision toolkit
191  std::string vsformat(char const * fmt, va_list ap)
192  {
193  // if we have a null pointer or an empty string, then just return an empty std::string
194  if (fmt == nullptr || fmt[0] == '\0') return std::string();
195 
196  int bufsize = 1024;
197  while (true)
198  {
199  char buf[bufsize];
200 
201  int const nchars = vsnprintf(buf, bufsize, fmt, ap);
202 
203  if (nchars < 0)
204  {
205  // Better leave this as LFATAL() rather than LERROR(), otherwise we have to return a bogus std::string (e.g. an
206  // empty string, or "none", or...), which might be dangerous if it is later used as a filename, for example.
207  LFATAL("vsnprintf failed for format '" << fmt << "' with bufsize = " << bufsize);
208  }
209  else if (nchars >= bufsize)
210  {
211  // buffer was too small, so let's double the bufsize and try again:
212  bufsize *= 2;
213  continue;
214  }
215  else
216  {
217  // OK, the vsnprintf() succeeded:
218  return std::string(&buf[0], nchars);
219  }
220  }
221  return std::string(); // can't happen, but placate the compiler
222  }
223 }
224 
225 // ####################################################################################################
226 std::string jevois::sformat(char const * fmt, ...)
227 {
228  va_list a;
229  va_start(a, fmt);
230  std::string result = vsformat(fmt, a);
231  va_end(a);
232  return result;
233 }
234 
235 // ####################################################################################################
237 {
238 #ifdef JEVOIS_PLATFORM
239  std::ofstream ofs("/proc/sys/vm/drop_caches");
240  if (ofs.is_open()) ofs << "3" << std::endl;
241  else LERROR("Failed to flush cache -- ignored");
242 #endif
243 }
244 
245 // ####################################################################################################
246 // This code modified from here: https://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-
247 // output-of-command-within-c-using-posix
248 std::string jevois::system(std::string const & cmd, bool errtoo)
249 {
250  std::array<char, 128> buffer; std::string result;
251  std::shared_ptr<FILE> pip;
252  if (errtoo) pip.reset(popen((cmd + " 2>&1").c_str(), "r"), pclose);
253  else pip.reset(popen(cmd.c_str(), "r"), pclose);
254  if (!pip) LFATAL("popen() failed for command [" << cmd << ']');
255  while (!feof(pip.get())) if (fgets(buffer.data(), 128, pip.get()) != NULL) result += buffer.data();
256  return result;
257 }
std::string strip(std::string const &str)
Strip white space (including CR, LF, tabs, etc) from the end of a string.
Definition: Utils.C:180
unsigned int whiteColor(unsigned int fcc)
Return a value that corresponds to white for the given video format.
Definition: Utils.C:127
void flushcache()
Flush the caches, may sometimes be useful when running the camera in turbo mode.
Definition: Utils.C:236
std::string cvtypestr(unsigned int cvtype)
Convert cv::Mat::type() code to to a string (e.g., CV_8UC1, CV_32SC3, etc)
Definition: Utils.C:52
unsigned int blackColor(unsigned int fcc)
Return a value that corresponds to black for the given video format.
Definition: Utils.C:112
std::string sformat(char const *fmt,...) __attribute__((format(__printf__
Create a string using printf style arguments.
Definition: Utils.C:226
std::string replaceWhitespace(std::string const &str, char rep='_')
Replace white space characters in a string with underscore (default) or another characters.
Definition: Utils.C:172
unsigned int v4l2BytesPerPix(unsigned int fcc)
Return the number of bytes per pixel for a given V4L2_PIX_FMT_...
Definition: Utils.C:92
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level. ...
Definition: Log.H:193
std::string join(std::vector< std::string > const &strings, std::string const &delimiter)
Concatenate a vector of tokens into a string.
Definition: Utils.C:152
std::string system(std::string const &cmd, bool errtoo=true)
Execute a command and grab stdout output to a string.
Definition: Utils.C:248
bool stringStartsWith(std::string const &str, std::string const &prefix)
Return true if str starts with prefix (including if both strings are equal)
Definition: Utils.C:166
std::string fccstr(unsigned int fcc)
Convert a V4L2 four-cc code (V4L2_PIX_FMT_...) to a 4-char string.
Definition: Utils.C:39
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level. ...
Definition: Log.H:212
unsigned int v4l2ImageSize(unsigned int fcc, unsigned int width, unsigned int height)
Return the image size in bytes for a given V4L2_PIX_FMT_..., width, height.
Definition: Utils.C:108
unsigned int strfcc(std::string const &str)
Convert a JeVois video format string to V4L2 four-cc code (V4L2_PIX_FMT_...)
Definition: Utils.C:79
std::vector< std::string > split(std::string const &input, std::string const &regex="\+")
Split string into vector of tokens using a regex to specify what to split on; default regex splits by...
Definition: Utils.C:142