JeVoisBase  1.2
JeVois Smart Embedded Machine Vision Toolkit Base Modules
DemoQRcode.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/Timer.H>
22 #include <linux/videodev2.h> // for v4l2 pixel types
23 #include <opencv2/core/core.hpp>
24 #include <opencv2/imgproc/imgproc.hpp>
25 
26 // icon by Vaadin in shapes at flaticon
27 
28 //! Simple demo of QRcode and barcode detection and decoding using the ZBar library
29 /*! Detect barcodes and QR-codes, and decode their contents.
30 
31  QR-codes (Quick Response Codes) are popular 2D patterns that contain embedded information, such as a string of text,
32  a URL, etc. They basically work like barcodes, coding information into a high-contrast, geometric pattern that is
33  easier to detect and decode by a machine that more conventional human-written text or drawings.
34 
35  One can generate QR-codes containing different kinds of information, for example using online QR-code generators,
36  such as http://www.qr-code-generator.com/
37 
38  JeVois detects and decodes QR-codes and other barcodes. The implementation of the detection and decoding algorithm
39  used in JeVois is from the popular libraru ZBar, found at http://zbar.sourceforge.net/
40 
41  @author Laurent Itti
42 
43  @displayname Demo QR-code
44  @videomapping YUYV 640 526 15.0 YUYV 640 480 15.0 JeVois DemoQRcode
45  @videomapping YUYV 320 286 30.0 YUYV 320 240 30.0 JeVois DemoQRcode
46  @videomapping NONE 0 0 0 YUYV 640 480 15.0 JeVois DemoQRcode
47  @videomapping NONE 0 0 0 YUYV 320 240 30.0 JeVois DemoQRcode
48  @email itti\@usc.edu
49  @address University of Southern California, HNB-07A, 3641 Watt Way, Los Angeles, CA 90089-2520, USA
50  @copyright Copyright (C) 2016 by Laurent Itti, iLab and the University of Southern California
51  @mainurl http://jevois.org
52  @supporturl http://jevois.org/doc
53  @otherurl http://iLab.usc.edu
54  @license GPL v3
55  @distribution Unrestricted
56  @restrictions None
57  \ingroup modules */
58 class DemoQRcode : public jevois::Module
59 {
60  public:
61 
62  // ####################################################################################################
63  //! Constructor
64  // ####################################################################################################
65  DemoQRcode(std::string const & instance) : jevois::Module(instance)
66  { itsQRcode = addSubComponent<QRcode>("qrcode"); }
67 
68  // ####################################################################################################
69  //! Virtual destructor for safe inheritance
70  // ####################################################################################################
71  virtual ~DemoQRcode()
72  { }
73 
74  // ####################################################################################################
75  //! Processing function, no video output
76  // ####################################################################################################
77  virtual void process(jevois::InputFrame && inframe) override
78  {
79  // Wait for next available camera image:
80  jevois::RawImage const inimg = inframe.get();
81 
82  // Convert the image to grayscale:
83  cv::Mat grayimg = jevois::rawimage::convertToCvGray(inimg);
84 
85  // Let camera know we are done processing the input image:
86  inframe.done();
87 
88  // Process gray image through zbar:
89  zbar::Image zgray(grayimg.cols, grayimg.rows, "Y800", grayimg.data, grayimg.total());
90  itsQRcode->process(zgray);
91 
92  // Send all the results over serial:
93  for (zbar::Image::SymbolIterator symbol = zgray.symbol_begin(); symbol != zgray.symbol_end(); ++symbol)
94  sendSerial(std::string(symbol->get_type_name()) + ' ' + symbol->get_data());
95 
96  // Cleanup zbar image data:
97  zgray.set_data(nullptr, 0);
98  }
99 
100  // ####################################################################################################
101  //! Processing function with video output to USB
102  // ####################################################################################################
103  virtual void process(jevois::InputFrame && inframe, jevois::OutputFrame && outframe) override
104  {
105  static jevois::Timer timer("processing", 60, LOG_DEBUG);
106  static unsigned short const txtcol = jevois::yuyv::White;
107  size_t const nshow = 4; // number of lines to show
108 
109  // Wait for next available camera image:
110  jevois::RawImage const inimg = inframe.get();
111 
112  timer.start();
113 
114  // We only handle one specific pixel format, any size in this demo:
115  unsigned int const w = inimg.width, h = inimg.height;
116  inimg.require("input", w, h, V4L2_PIX_FMT_YUYV);
117 
118  // While we process it, start a thread to wait for out frame and paste the input into it:
119  jevois::RawImage outimg;
120  auto paste_fut = std::async(std::launch::async, [&]() {
121  outimg = outframe.get();
122  outimg.require("output", w, h + nshow * 10 + 6, inimg.fmt);
123  jevois::rawimage::paste(inimg, outimg, 0, 0);
124  jevois::rawimage::writeText(outimg, "JeVois QR-code + Barcode Detection Demo", 3, 3, txtcol);
125  jevois::rawimage::drawFilledRect(outimg, 0, h, w, outimg.height-h, 0x8000);
126  });
127 
128  // Convert the image to grayscale and process it through zbar:
129  cv::Mat grayimg = jevois::rawimage::convertToCvGray(inimg);
130  zbar::Image zgray(grayimg.cols, grayimg.rows, "Y800", grayimg.data, grayimg.total());
131  itsQRcode->process(zgray);
132 
133  // Wait for paste to finish up:
134  paste_fut.get();
135 
136  // Let camera know we are done processing the input image:
137  inframe.done();
138 
139  // Show all the results:
140  std::string txt; std::vector<std::string> qdata;
141  for (zbar::Image::SymbolIterator symbol = zgray.symbol_begin(); symbol != zgray.symbol_end(); ++symbol)
142  {
143  // Send to serial:
144  sendSerial(std::string(symbol->get_type_name()) + ' ' + symbol->get_data());
145 
146  // Build up some strings to be displayed as video overlay:
147  txt += ' ' + symbol->get_type_name();
148  qdata.push_back(std::string(symbol->get_type_name()) + ": " + symbol->get_data());
149 
150  // Draw a polygon around the detected symbol: for QR codes, we get 4 points at the corners, but for others we
151  // get a bunch of points all over the barcode:
152  if (symbol->get_type() == zbar::ZBAR_QRCODE)
153  {
154  zbar::Symbol::Point pp(-1000000, -1000000);
155  for (zbar::Symbol::PointIterator pitr = symbol->point_begin(); pitr != symbol->point_end(); ++pitr)
156  {
157  zbar::Symbol::Point p(*pitr);
158  if (pp.x != -1000000) jevois::rawimage::drawLine(outimg, pp.x, pp.y, p.x, p.y, 1, 0xf0f0);
159  pp = p;
160  }
161  if (pp.x != -1000000)
162  {
163  zbar::Symbol::Point p = *(symbol->point_begin());
164  jevois::rawimage::drawLine(outimg, pp.x, pp.y, p.x, p.y, 1, 0xf0f0);
165  }
166  }
167  else
168  {
169  int tlx = w, tly = h, brx = -1, bry = -1;
170  for (zbar::Symbol::PointIterator pitr = symbol->point_begin(); pitr != symbol->point_end(); ++pitr)
171  {
172  zbar::Symbol::Point p(*pitr);
173  if (p.x < tlx) tlx = p.x;
174  if (p.x > brx) brx = p.x;
175  if (p.y < tly) tly = p.y;
176  if (p.y > bry) bry = p.y;
177  }
178  tlx = std::min(int(w)-1, std::max(0, tlx));
179  brx = std::min(int(w)-1, std::max(0, brx));
180  tly = std::min(int(h)-1, std::max(0, tly));
181  bry = std::min(int(h)-1, std::max(0, bry));
182  jevois::rawimage::drawRect(outimg, tlx, tly, brx - tlx, bry - tly, 1, 0xf0f0);
183  }
184  }
185 
186  // Write some strings with what we found and decoded:
187  if (qdata.empty())
188  jevois::rawimage::writeText(outimg, "Found no symbols.", 3, h + 3, txtcol);
189  else
190  {
191  txt = "Found " + std::to_string(qdata.size()) + " symbols:" + txt;
192  jevois::rawimage::writeText(outimg, txt.c_str(), 3, h + 3, txtcol);
193  for (size_t i = 0; i < std::min(qdata.size(), nshow - 1); ++i)
194  jevois::rawimage::writeText(outimg, qdata[i].c_str(), 3, h + 3 + (i+1) * 10, txtcol);
195  }
196 
197  // Cleanup zbar image data:
198  zgray.set_data(nullptr, 0);
199 
200  // Show processing fps:
201  std::string const & fpscpu = timer.stop();
202  jevois::rawimage::writeText(outimg, fpscpu, 3, h - 13, txtcol);
203 
204  // Send the output image with our processing results to the host over USB:
205  outframe.send();
206  }
207 
208  // ####################################################################################################
209  protected:
210  std::shared_ptr<QRcode> itsQRcode;
211 };
212 
213 // Allow the module to be loaded as a shared object (.so) file:
friend friend class Module
DemoQRcode(std::string const &instance)
Constructor.
Definition: DemoQRcode.C:65
virtual void process(jevois::InputFrame &&inframe, jevois::OutputFrame &&outframe) override
Processing function with video output to USB.
Definition: DemoQRcode.C:103
void writeText(RawImage &img, std::string const &txt, int x, int y, unsigned int col, Font font=Font6x10)
void require(char const *info, unsigned int w, unsigned int h, unsigned int f) const
unsigned int height
Simple demo of QRcode and barcode detection and decoding using the ZBar library.
Definition: DemoQRcode.C:58
virtual void process(jevois::InputFrame &&inframe) override
Processing function, no video output.
Definition: DemoQRcode.C:77
void drawLine(RawImage &img, int x1, int y1, int x2, int y2, unsigned int thick, unsigned int col)
unsigned int fmt
virtual ~DemoQRcode()
Virtual destructor for safe inheritance.
Definition: DemoQRcode.C:71
JEVOIS_REGISTER_MODULE(DemoQRcode)
cv::Mat convertToCvGray(RawImage const &src)
virtual void sendSerial(std::string const &str)
void drawFilledRect(RawImage &img, int x, int y, unsigned int w, unsigned int h, unsigned int col)
std::string to_string(T const &val)
void drawRect(RawImage &img, int x, int y, unsigned int w, unsigned int h, unsigned int thick, unsigned int col)
std::shared_ptr< QRcode > itsQRcode
Definition: DemoQRcode.C:210
unsigned int width
std::string const & stop()
void paste(RawImage const &src, RawImage &dest, int dx, int dy)