JeVois  1.5
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
tutorial4.C
Go to the documentation of this file.
1 #include <jevois/Core/Module.H>
3 #include <opencv2/core/core.hpp>
4 #include <opencv2/imgproc/imgproc.hpp>
5 #include <future>
6 
7 // Parameters for our module:
8 static jevois::ParameterCategory const ParamCateg("Edge Detection Options");
9 JEVOIS_DECLARE_PARAMETER(thresh1, double, "First threshold for hysteresis", 20.0, ParamCateg);
10 JEVOIS_DECLARE_PARAMETER(thresh2, double, "Second threshold for hysteresis", 60.0, ParamCateg);
11 JEVOIS_DECLARE_PARAMETER(aperture, int, "Aperture size for the Sobel operator", 3, ParamCateg);
12 JEVOIS_DECLARE_PARAMETER(l2grad, bool, "Use more accurate L2 gradient norm if true, L1 if false", false, ParamCateg);
13 JEVOIS_DECLARE_PARAMETER(thresh1delta, double, "First threshold delta over threads", 50.0, ParamCateg);
14 JEVOIS_DECLARE_PARAMETER(thresh2delta, double, "Second threshold delta over threads", 50.0, ParamCateg);
15 
16 // Simple module to detect edges, running 4 filters in parallel with 4 different settings
18  public jevois::Parameter<thresh1, thresh2, aperture, l2grad, thresh1delta, thresh2delta>
19 {
20  public:
21  // Default base class constructor ok
23 
24  // Virtual destructor for safe inheritance
26 
27  // Processing function
28  virtual void process(jevois::InputFrame && inframe, jevois::OutputFrame && outframe) override
29  {
30  // Wait for next available camera image:
31  jevois::RawImage inimg = inframe.get();
32 
33  // Convert to grayscale:
34  cv::Mat grayimg = jevois::rawimage::convertToCvGray(inimg);
35 
36  // Let camera know we are done processing the input image:
37  inframe.done();
38 
39  // Wait for an image from our gadget driver into which we will put our results:
40  jevois::RawImage outimg = outframe.get();
41  outimg.require("output", inimg.width, inimg.height * 4, V4L2_PIX_FMT_GREY);
42 
43  // Launch 4 Canny filters in parallel. We launch 3 threads and will do the fourth in the current thread:
44  std::vector<std::future<void> > fut;
45 
46  for (int i = 0; i < 3; ++i)
47  fut.push_back(std::async(std::launch::async, [&](int i) {
48  // Compute Canny edges directly into the output image, offset by i images down. The last argument of the
49  // cv::Mat constructor below is the address of an already-allocated pixel buffer for the cv::Mat:
50  cv::Mat edges(grayimg.rows, grayimg.cols, CV_8UC1, outimg.pixelsw<unsigned char>() + i * grayimg.total());
51 
52  cv::Canny(grayimg, edges, thresh1::get() + i * thresh1delta::get(),
53  thresh2::get() + i * thresh2delta::get(), aperture::get(), l2grad::get());
54  }, i));
55 
56  // Fourth one (same code as above except for the async, and for i=3):
57  cv::Mat edges(grayimg.rows, grayimg.cols, CV_8UC1, outimg.pixelsw<unsigned char>() + 3 * grayimg.total());
58  cv::Canny(grayimg, edges, thresh1::get() + 3 * thresh1delta::get(),
59  thresh2::get() + 3 * thresh2delta::get(), aperture::get(), l2grad::get());
60 
61  // The fourth one is done now, wait for all the threads to complete. Note: using async() is preferred to using
62  // std::thread, as get() below will throw if any exception was thrown by a thread, as opposed to std::thread
63  // violently terminating the program on exception. In case two or more threads threw, we can here avoid
64  // termination by catching the exceptions one by one. Here we just ignore (since we are done anyway) but could
65  // throw just once if any of the threads threw:
66  for (auto & f : fut) try { f.get(); } catch (...) { jevois::warnAndIgnoreException(); }
67 
68  // Send the output image with our processing results to the host over USB:
69  outframe.send();
70  }
71 };
72 
73 // Allow the module to be loaded as a shared object (.so) file:
std::string warnAndIgnoreException()
Convenience function to catch an exception, issue some LERROR (depending on type), and ignore it.
Definition: Log.C:211
Exception-safe wrapper around a raw camera input frame.
Definition: Module.H:56
JEVOIS_REGISTER_MODULE(TutorialEdgeDetectionX4)
unsigned int height
Image height in pixels.
Definition: RawImage.H:146
Generic variadic template class template definition for Component Parameters.
virtual void process(jevois::InputFrame &&inframe, jevois::OutputFrame &&outframe) override
Processing function, version that receives a frame from camera and sends a frame out over USB...
Definition: tutorial4.C:28
T * pixelsw()
Shortcut access to pixels, read-write.
Definition: RawImageImpl.H:24
Module(std::string const &instance)
Constructor.
Definition: Module.C:181
virtual ~TutorialEdgeDetectionX4()
Definition: tutorial4.C:25
A category to which multiple ParameterDef definitions can belong.
Definition: ParameterDef.H:33
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition: RawImage.H:110
JEVOIS_DECLARE_PARAMETER(help, bool, "Print this help message", false, ParamCateg)
Parameter.
cv::Mat convertToCvGray(RawImage const &src)
Convert RawImage to OpenCV doing color conversion from any RawImage source pixel to OpenCV gray byte...
Definition: RawImageOps.C:245
static ParameterCategory const ParamCateg("General Options")
Parameter category.
Virtual base class for a vision processing module.
Definition: Module.H:279
Exception-safe wrapper around a raw image to be sent over USB.
Definition: Module.H:144
unsigned int width
Image width in pixels.
Definition: RawImage.H:145
void require(char const *info, unsigned int w, unsigned int h, unsigned int f) const
Require a particular image size and format, issue a fatal error message and throw if no match...
Definition: RawImage.C:68