JeVoisBase  1.0
JeVois Smart Embedded Machine Vision Toolkit Base Modules
EdgeDetectionX4.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/Debug/Log.H>
21 
22 #include <linux/videodev2.h>
23 #include <opencv2/core/core.hpp>
24 #include <opencv2/imgproc/imgproc.hpp>
25 #include <future>
26 
27 // icon by Sergiu Bagrin in interface at flaticon
28 
29 static jevois::ParameterCategory const ParamCateg("Edge Detection Options");
30 //! Parameter \relates EdgeDetectionX4
31 JEVOIS_DECLARE_PARAMETER(thresh1, double, "First threshold for hysteresis", 20.0, ParamCateg);
32 //! Parameter \relates EdgeDetectionX4
33 JEVOIS_DECLARE_PARAMETER(thresh2, double, "Second threshold for hysteresis", 60.0, ParamCateg);
34 //! Parameter \relates EdgeDetectionX4
35 JEVOIS_DECLARE_PARAMETER(aperture, int, "Aperture size for the Sobel operator", 3, ParamCateg);
36 //! Parameter \relates EdgeDetectionX4
37 JEVOIS_DECLARE_PARAMETER(l2grad, bool, "Use more accurate L2 gradient norm if true, L1 if false", false, ParamCateg);
38 //! Parameter \relates EdgeDetectionX4
39 JEVOIS_DECLARE_PARAMETER(thresh1delta, double, "First threshold delta over threads", 50.0, ParamCateg);
40 //! Parameter \relates EdgeDetectionX4
41 JEVOIS_DECLARE_PARAMETER(thresh2delta, double, "Second threshold delta over threads", 50.0, ParamCateg);
42 
43 //! Simple module to detect edges, running 4 filters in parallel with 4 different settings
44 /*! Compute 4 Canny edge detection filters with 4 different settings, in parallel.
45 
46  @author Laurent Itti
47 
48  @displayname Edge Detection X4
49  @videomapping GREY 320 960 45.0 YUYV 320 240 45.0 JeVois EdgeDetectionX4
50  @email itti\@usc.edu
51  @address University of Southern California, HNB-07A, 3641 Watt Way, Los Angeles, CA 90089-2520, USA
52  @copyright Copyright (C) 2016 by Laurent Itti, iLab and the University of Southern California
53  @mainurl http://jevois.org
54  @supporturl http://jevois.org/doc
55  @otherurl http://iLab.usc.edu
56  @license GPL v3
57  @distribution Unrestricted
58  @restrictions None
59  \ingroup modules */
61  public jevois::Parameter<thresh1, thresh2, aperture, l2grad, thresh1delta, thresh2delta>
62 {
63  public:
64  //! Default base class constructor ok
66 
67  //! Virtual destructor for safe inheritance
68  virtual ~EdgeDetectionX4() { }
69 
70  //! Processing function
71  virtual void process(jevois::InputFrame && inframe, jevois::OutputFrame && outframe) override
72  {
73  // Wait for next available camera image:
74  jevois::RawImage inimg = inframe.get();
75 
76  // Convert to grayscale:
77  cv::Mat grayimg = jevois::rawimage::convertToCvGray(inimg);
78 
79  // Let camera know we are done processing the input image:
80  inframe.done();
81 
82  // Wait for an image from our gadget driver into which we will put our results:
83  jevois::RawImage outimg = outframe.get();
84  outimg.require("output", inimg.width, inimg.height * 4, V4L2_PIX_FMT_GREY);
85 
86  // Launch 4 Canny filters in parallel. We launch 3 threads and will do the fourth in the current thread:
87  std::vector<std::future<void> > fut;
88 
89  for (int i = 0; i < 3; ++i)
90  fut.push_back(std::async(std::launch::async, [&](int i) {
91  // Compute Canny edges directly into the output image, offset by i images down. The last argument of the
92  // cv::Mat constructor below is the address of an already-allocated pixel buffer for the cv::Mat:
93  cv::Mat edges(grayimg.rows, grayimg.cols, CV_8UC1, outimg.pixelsw<unsigned char>() + i * grayimg.total());
94 
95  cv::Canny(grayimg, edges, thresh1::get() + i * thresh1delta::get(),
96  thresh2::get() + i * thresh2delta::get(), aperture::get(), l2grad::get());
97  }, i));
98 
99  // Fourth one (same code as above except for the async, and for i=3):
100  cv::Mat edges(grayimg.rows, grayimg.cols, CV_8UC1, outimg.pixelsw<unsigned char>() + 3 * grayimg.total());
101  cv::Canny(grayimg, edges, thresh1::get() + 3 * thresh1delta::get(),
102  thresh2::get() + 3 * thresh2delta::get(), aperture::get(), l2grad::get());
103 
104  // The fourth one is done now, wait for all the threads to complete. Note: using async() is preferred to using
105  // std::thread, as get() below will throw if any exception was thrown by a thread, as opposed to std::thread
106  // violently terminating the program on exception. In case two or more threads threw, we can here avoid
107  // termination by catching the exceptions one by one. Here we just ignore (since we are done anyway) but could
108  // throw just once if any of the threads threw:
109  for (auto & f : fut) try { f.get(); } catch (...) { jevois::warnAndIgnoreException(); }
110 
111  // Send the output image with our processing results to the host over USB:
112  outframe.send();
113  }
114 };
115 
116 // Allow the module to be loaded as a shared object (.so) file:
std::string warnAndIgnoreException()
friend friend class Module
void require(char const *info, unsigned int w, unsigned int h, unsigned int f) const
unsigned int height
virtual void process(jevois::InputFrame &&inframe, jevois::OutputFrame &&outframe) override
Processing function.
#define JEVOIS_DECLARE_PARAMETER(ParamName, ParamType,...)
Parameter.
Simple module to detect edges, running 4 filters in parallel with 4 different settings.
JEVOIS_REGISTER_MODULE(EdgeDetectionX4)
cv::Mat convertToCvGray(RawImage const &src)
unsigned int width
virtual ~EdgeDetectionX4()
Virtual destructor for safe inheritance.