JeVoisBase  1.20
JeVois Smart Embedded Machine Vision Toolkit Base Modules
Share this page:
DemoGPU.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/Module.H>
19 #include <jevois/Types/Enum.H>
20 #include <jevois/Debug/Timer.H>
21 
23 
25 #include <linux/videodev2.h>
26 
27 #include <opencv2/core/core.hpp>
28 #include <opencv2/imgproc/imgproc.hpp>
29 
30 static jevois::ParameterCategory const ParamCateg("DemoGPU Parameters");
31 
32 // Note: we use NoEffect here as None seems to be defined a s anumeric constant somewhere, when compiling on host
33 
34 //! Parameter \relates DemoGPU
35 JEVOIS_DEFINE_ENUM_CLASS(Effect, (NoEffect) (Blur) (Sobel) (Median) (Mult) (Thresh) (Dilate) (Erode) (Twirl) (Dewarp));
36 
37 //! Parameter \relates DemoGPU
38 JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(effect, Effect, "GPU image processing effect to apply",
39  Effect::Twirl, Effect_Values, ParamCateg);
40 
41 // icon by by Freepik in technology at flaticon
42 
43 //! Simple image filtering demo using OpenGL-ES shaders on the Mali-400MP2 GPU
44 /*! This class first copies the given input image into an OpenGL texture, then applies OpenGL-ES vertex and fragment
45  shaders to achieve some image processing, and finally gets the resulting pixels back into an image.
46 
47  This code is inspired somewhat from the tutorial and code examples found on this page:
48  http://robotblogging.blogspot.com/2013/10/gpu-accelerated-camera-processing-on.html
49 
50  But an important distinction is that we render to a framebuffer with an RGB565 renderbuffer attached, which
51  accelerates processing and transfer of the results a lot.
52 
53  Dewarp algorithm contributed by JeVois user [Ali AlSaibie](https://github.com/alsaibie). It is to be used with a
54  modified JeVois camera sensor that has a wide-angle lens. See http://jevois.org/qa/index.php?qa=153 for details.
55 
56  \youtube{rxsWR3I_LnM}
57 
58  Using this module
59  -----------------
60 
61  Unfortunately, MacOS computers refuse to detect the JeVois smart camera as soon as it exposes one or more RGB565
62  video modes. Thus, you cannot use this module with Macs in its native version (but see below), and the module is
63  disabled by default. In addition, RGB565 does not seem to work in older \c guvcview either, on Ubuntu prior to
64  17.04! Proceed as follows to enable and use this module on a Linux host:
65 
66  Edit <b>JEVOIS:/jevois/config/videomappings.cfg</b> and look for the line that mentions \jvmod{DemoGPU}. It is
67  commented out, so just remove the leading \b # sign. The line should then look like this:
68 
69  \verbatim
70  RGB565 320 240 22.0 YUYV 320 240 22.0 JeVois DemoGPU
71  \endverbatim
72 
73  Restart JeVois and run this on your Linux host if older than Ubuntu 17.04:
74 
75  \verbatim
76  sudo apt install ffmpeg
77  ffplay /dev/video0 -pixel_format rgb565 -video_size 320x240
78  \endverbatim
79 
80  or, with Ubuntu 17.04 and later:
81 
82  \verbatim
83  guvcview -f RGBP -x 320x240
84  \endverbatim
85 
86  This module can also work with YUYV output, which is then compatible with MacOS, JeVois Inventor, etc. But note
87  that the conversion from RGB565 to YUYV consumes some CPU on the JeVois camera.
88 
89  @author Laurent Itti
90 
91  @displayname Demo GPU
92  @videomapping RGB565 320 240 22.0 YUYV 320 240 22.0 JeVois DemoGPU # Native mode
93  @videomapping YUYV 320 240 22.0 YUYV 320 240 22.0 JeVois DemoGPU # With CPU-based conversion from RGB565 to YUYV
94  @email itti\@usc.edu
95  @address University of Southern California, HNB-07A, 3641 Watt Way, Los Angeles, CA 90089-2520, USA
96  @copyright Copyright (C) 2016 by Laurent Itti, iLab and the University of Southern California
97  @mainurl http://jevois.org
98  @supporturl http://jevois.org/doc
99  @otherurl http://iLab.usc.edu
100  @license GPL v3
101  @distribution Unrestricted
102  @restrictions None
103  \ingroup modules */
104 class DemoGPU : public jevois::Module,
105  public jevois::Parameter<effect>
106 {
107  public:
108  //! Constrctor
109  DemoGPU(std::string const & instance) : jevois::Module(instance)
110  {
111  itsFilter = addSubComponent<FilterGPU>("gpu");
112  }
113 
114  //! Virtual destructor for safe inheritance
115  virtual ~DemoGPU() { }
116 
117  //! Processing function
118  virtual void process(jevois::InputFrame && inframe, jevois::OutputFrame && outframe) override
119  {
120  static jevois::Timer timer("DemoGPU");
121 
122  // Wait for next available camera image:
123  jevois::RawImage const inimg = inframe.get();
124 
125  timer.start();
126 
127  // Convert input image to RGBA:
128  cv::Mat inimgcv = jevois::rawimage::convertToCvRGBA(inimg);
129 
130  // Let camera know we are done processing the input image:
131  inframe.done();
132 
133  // Wait for an image from our gadget driver into which we will put our results:
134  jevois::RawImage outimg = outframe.get();
135  if (outimg.width != inimg.width || outimg.height != inimg.height)
136  LFATAL("Input and output image sizes must match");
137  unsigned int col; // color for our text
138 
139  if (outimg.fmt == V4L2_PIX_FMT_RGB565)
140  {
141  // Process input to output, going from YUYV to RGBA internally, to RGB565 rendering:
142  cv::Mat outimgcv = jevois::rawimage::cvImage(outimg);
143  itsFilter->process(inimgcv, outimgcv);
144  col = jevois::rgb565::White;
145  }
146  else if (outimg.fmt == V4L2_PIX_FMT_YUYV)
147  {
148  // Process input into a temporary RGB565 buffer, then convert RGB565 to RGB to YUYV on CPU.
149  // Clearly this uses a lot of CPU that would offset any gains of GPU computation. For demo purposes only.
150  cv::Mat tmpcv(inimg.height, inimg.width, CV_8UC2);
151  itsFilter->process(inimgcv, tmpcv);
152  cv::Mat tmpcvbgr; cv::cvtColor(tmpcv, tmpcvbgr, cv::COLOR_BGR5652BGR); // note: swap red/blue
153  jevois::rawimage::convertCvBGRtoRawImage(tmpcvbgr, outimg, 100); // note: swap red/blue
154  col = jevois::yuyv::White;
155  }
156  else LFATAL("output format must be RGB565 or YUYV");
157 
158  // Show processing fps:
159  std::string const & fpscpu = timer.stop();
160  jevois::rawimage::writeText(outimg, fpscpu, 3, outimg.height - 13, col);
161  std::ostringstream oss; oss << "JeVois DemoGPU - Effect: " << effect::get();
162  jevois::rawimage::writeText(outimg, oss.str(), 3, 3, col);
163 
164  // Send the output image with our processing results to the host over USB:
165  outframe.send();
166  }
167 
168 
169  // ####################################################################################################
170  void onParamChange(effect const & JEVOIS_UNUSED_PARAM(param), Effect const & newval) override
171  {
172  switch (newval)
173  {
174  case Effect::NoEffect:
175  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/simplefragshader.glsl");
176  break;
177 
178  case Effect::Blur:
179  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/blurfragshader.glsl");
180  break;
181 
182  case Effect::Sobel:
183  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/sobelfragshader.glsl");
184  break;
185 
186  case Effect::Median:
187  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/medianfragshader.glsl");
188  break;
189 
190  case Effect::Mult:
191  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/multfragshader.glsl");
192  break;
193 
194  case Effect::Thresh:
195  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/threshfragshader.glsl");
196  break;
197 
198  case Effect::Dilate:
199  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/dilatefragshader.glsl");
200  break;
201 
202  case Effect::Erode:
203  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/erodefragshader.glsl");
204  break;
205 
206  case Effect::Twirl:
207  itsFilter->setProgram("shaders/simplevertshader.glsl", "shaders/twirlfragshader.glsl");
208  itsFilter->setProgramParam1f("twirlamount", 2.0F);
209  break;
210 
211  // See fragment shader dewarpfragshader.glsl file for details
212  case Effect::Dewarp:
213  itsFilter->setProgram("shaders/dewarpvertshader.glsl", "shaders/dewarpfragshader.glsl");
214  break;
215  }
216 
217  // These parameters are used by the vertex shader and hence apply to most demo programs:
218  itsFilter->setProgramParam2f("offset", -1.0F, -1.0F);
219  itsFilter->setProgramParam2f("scale", 2.0F, 2.0F);
220 
221  // Crop Dewarped Image - change According to dewarped image
222  itsFilter->setProgramParam2f("offsetd", -1.2F, -1.2F);
223  itsFilter->setProgramParam2f("scaled", 2.4F, 2.4F);
224  }
225 
226  private:
227  std::shared_ptr<FilterGPU> itsFilter;
228 };
229 
230 // Allow the module to be loaded as a shared object (.so) file:
jevois::OutputFrame
Timer.H
Module.H
DemoGPU::onParamChange
void onParamChange(effect const &JEVOIS_UNUSED_PARAM(param), Effect const &newval) override
Definition: DemoGPU.C:170
jevois::RawImage
jevois::Timer::start
void start()
jevois::ParameterCategory
FilterGPU.H
jevois::RawImage::width
unsigned int width
jevois::rawimage::writeText
void writeText(RawImage &img, std::string const &txt, int x, int y, unsigned int col, Font font=Font6x10)
jevois
F
float F
ARtoolkit::JEVOIS_DEFINE_ENUM_CLASS
JEVOIS_DEFINE_ENUM_CLASS(Dict,(AR_MATRIX_CODE_3x3)(AR_MATRIX_CODE_3x3_HAMMING63)(AR_MATRIX_CODE_3x3_PARITY65))
Enum for parameter.
Enum.H
jevois::Timer::stop
const std::string & stop(double *seconds)
DemoGPU::DemoGPU
DemoGPU(std::string const &instance)
Constrctor.
Definition: DemoGPU.C:109
LFATAL
#define LFATAL(msg)
jevois::rawimage::convertCvBGRtoRawImage
void convertCvBGRtoRawImage(cv::Mat const &src, RawImage &dst, int quality)
jevois::Module
DemoGPU::process
virtual void process(jevois::InputFrame &&inframe, jevois::OutputFrame &&outframe) override
Processing function.
Definition: DemoGPU.C:118
DemoGPU
Simple image filtering demo using OpenGL-ES shaders on the Mali-400MP2 GPU.
Definition: DemoGPU.C:104
RawImageOps.H
JEVOIS_REGISTER_MODULE
JEVOIS_REGISTER_MODULE(DemoGPU)
jevois::RawImage::height
unsigned int height
jevois::InputFrame
jevois::rawimage::cvImage
cv::Mat cvImage(RawImage const &src)
jevois::RawImage::fmt
unsigned int fmt
jevois::rawimage::convertToCvRGBA
cv::Mat convertToCvRGBA(RawImage const &src)
Darknet::JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK
JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(dataroot, std::string, "Root path for data, config, and weight files. " "If empty, use the module's path.", JEVOIS_SHARE_PATH "/darknet/single", ParamCateg)
Parameter.
DemoGPU::~DemoGPU
virtual ~DemoGPU()
Virtual destructor for safe inheritance.
Definition: DemoGPU.C:115
jevois::Timer
jevois::Component::Module
friend friend class Module