JeVoisBase  1.20
JeVois Smart Embedded Machine Vision Toolkit Base Modules
Share this page:
QRcode.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 
19 #include <jevois/Core/Module.H>
21 #include <jevois/Util/Utils.H>
22 
23 // ####################################################################################################
24 QRcode::QRcode(std::string const & instance) :
25  jevois::Component(instance), itsScanner(new zbar::ImageScanner())
26 {
27  itsScanner->set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
28 }
29 
30 // ####################################################################################################
32 { }
33 
34 // ####################################################################################################
35 void QRcode::onParamChange(qrcode::symbol const & JEVOIS_UNUSED_PARAM(param), std::string const & newval)
36 {
37  // Disable scanning for no symbols:
38  itsScanner->set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 0);
39 
40  // Enable the requested ones:
41  std::vector<std::string> vec = jevois::split(newval, "/");
42  for (std::string const & v : vec)
43  if (v == "ALL")
44  {
45  itsScanner->set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);
46  itsScanner->set_config(zbar::ZBAR_EAN2, zbar::ZBAR_CFG_ENABLE, 1);
47  itsScanner->set_config(zbar::ZBAR_EAN5, zbar::ZBAR_CFG_ENABLE, 1);
48  itsScanner->set_config(zbar::ZBAR_EAN8, zbar::ZBAR_CFG_ENABLE, 1);
49  itsScanner->set_config(zbar::ZBAR_EAN13, zbar::ZBAR_CFG_ENABLE, 1);
50  itsScanner->set_config(zbar::ZBAR_UPCE, zbar::ZBAR_CFG_ENABLE, 1);
51  itsScanner->set_config(zbar::ZBAR_UPCA, zbar::ZBAR_CFG_ENABLE, 1);
52  itsScanner->set_config(zbar::ZBAR_ISBN10, zbar::ZBAR_CFG_ENABLE, 1);
53  itsScanner->set_config(zbar::ZBAR_ISBN13, zbar::ZBAR_CFG_ENABLE, 1);
54  itsScanner->set_config(zbar::ZBAR_COMPOSITE, zbar::ZBAR_CFG_ENABLE, 1);
55  itsScanner->set_config(zbar::ZBAR_I25, zbar::ZBAR_CFG_ENABLE, 1);
56  itsScanner->set_config(zbar::ZBAR_DATABAR, zbar::ZBAR_CFG_ENABLE, 1);
57  itsScanner->set_config(zbar::ZBAR_DATABAR_EXP, zbar::ZBAR_CFG_ENABLE, 1);
58  itsScanner->set_config(zbar::ZBAR_CODABAR, zbar::ZBAR_CFG_ENABLE, 1);
59  itsScanner->set_config(zbar::ZBAR_CODE39, zbar::ZBAR_CFG_ENABLE, 1);
60  itsScanner->set_config(zbar::ZBAR_PDF417, zbar::ZBAR_CFG_ENABLE, 1);
61  itsScanner->set_config(zbar::ZBAR_CODE93, zbar::ZBAR_CFG_ENABLE, 1);
62  itsScanner->set_config(zbar::ZBAR_CODE128, zbar::ZBAR_CFG_ENABLE, 1);
63  }
64  else if (v == "QRCODE") itsScanner->set_config(zbar::ZBAR_QRCODE, zbar::ZBAR_CFG_ENABLE, 1);
65  else if (v == "EAN2") itsScanner->set_config(zbar::ZBAR_EAN2, zbar::ZBAR_CFG_ENABLE, 1);
66  else if (v == "EAN5") itsScanner->set_config(zbar::ZBAR_EAN5, zbar::ZBAR_CFG_ENABLE, 1);
67  else if (v == "EAN8") itsScanner->set_config(zbar::ZBAR_EAN8, zbar::ZBAR_CFG_ENABLE, 1);
68  else if (v == "EAN13") itsScanner->set_config(zbar::ZBAR_EAN13, zbar::ZBAR_CFG_ENABLE, 1);
69  else if (v == "UPCE") itsScanner->set_config(zbar::ZBAR_UPCE, zbar::ZBAR_CFG_ENABLE, 1);
70  else if (v == "UPCA") itsScanner->set_config(zbar::ZBAR_UPCA, zbar::ZBAR_CFG_ENABLE, 1);
71  else if (v == "ISBN10")
72  {
73  itsScanner->set_config(zbar::ZBAR_EAN13, zbar::ZBAR_CFG_ENABLE, 1); // required?
74  itsScanner->set_config(zbar::ZBAR_ISBN10, zbar::ZBAR_CFG_ENABLE, 1);
75  }
76  else if (v == "ISBN13")
77  {
78  itsScanner->set_config(zbar::ZBAR_EAN13, zbar::ZBAR_CFG_ENABLE, 1); // required?
79  itsScanner->set_config(zbar::ZBAR_ISBN13, zbar::ZBAR_CFG_ENABLE, 1);
80  }
81  else if (v == "COMPOSITE") itsScanner->set_config(zbar::ZBAR_COMPOSITE, zbar::ZBAR_CFG_ENABLE, 1);
82  else if (v == "I25") itsScanner->set_config(zbar::ZBAR_I25, zbar::ZBAR_CFG_ENABLE, 1);
83  else if (v == "DATABAR") itsScanner->set_config(zbar::ZBAR_DATABAR, zbar::ZBAR_CFG_ENABLE, 1);
84  else if (v == "DATABAREXP") itsScanner->set_config(zbar::ZBAR_DATABAR_EXP, zbar::ZBAR_CFG_ENABLE, 1);
85  else if (v == "CODABAR") itsScanner->set_config(zbar::ZBAR_CODABAR, zbar::ZBAR_CFG_ENABLE, 1);
86  else if (v == "CODE39") itsScanner->set_config(zbar::ZBAR_CODE39, zbar::ZBAR_CFG_ENABLE, 1);
87  else if (v == "PDF417") itsScanner->set_config(zbar::ZBAR_PDF417, zbar::ZBAR_CFG_ENABLE, 1);
88  else if (v == "CODE93") itsScanner->set_config(zbar::ZBAR_CODE93, zbar::ZBAR_CFG_ENABLE, 1);
89  else if (v == "CODE128") itsScanner->set_config(zbar::ZBAR_CODE128, zbar::ZBAR_CFG_ENABLE, 1);
90  else LFATAL("Invalid symbol type [" << v <<']');
91 }
92 
93 // ####################################################################################################
94 void QRcode::process(zbar::Image & image)
95 {
96  // Update config using Component parameters:
97  itsScanner->set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_X_DENSITY, qrcode::xdensity::get());
98  itsScanner->set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_Y_DENSITY, qrcode::ydensity::get());
99 
100  // Scan for barcodes, they will be stored in the image:
101  int n = itsScanner->scan(image);
102  if (n == -1) LERROR("ZBar error");
103 }
104 
105 // ####################################################################################################
106 void QRcode::process(zbar::Image & image, std::vector<std::string> & results)
107 {
108  // Update config using Component parameters:
109  itsScanner->set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_X_DENSITY, qrcode::xdensity::get());
110  itsScanner->set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_Y_DENSITY, qrcode::ydensity::get());
111 
112  // Clear any input junk:
113  results.clear();
114 
115  // Scan for barcodes, they will be stored in the image:
116  int n = itsScanner->scan(image);
117 
118  if (n == -1)
119  LERROR("ZBar error");
120  else if (n > 0)
121  for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol)
122  results.push_back(std::string(symbol->get_type_name()) + ' ' + symbol->get_data());
123 }
124 
125 // ####################################################################################################
126 void QRcode::sendSerial(jevois::StdModule * mod, zbar::Image & img, unsigned int camw, unsigned int camh)
127 {
128  for (zbar::Image::SymbolIterator symbol = img.symbol_begin(); symbol != img.symbol_end(); ++symbol)
129  {
130  std::string id = symbol->get_type_name();
131  std::string extra = symbol->get_data();
132 
133  std::vector<cv::Point> corners;
134 
135  // Note: For QR codes, we get 4 points at the corners, but for others we get a bunch of points all over the
136  // barcode, hopefully users will not select the Fine serial style...
137  for (zbar::Symbol::PointIterator pitr = symbol->point_begin(); pitr != symbol->point_end(); ++pitr)
138  {
139  zbar::Symbol::Point p(*pitr);
140  corners.push_back(cv::Point(p.x, p.y));
141  }
142 
143  mod->sendSerialContour2D(camw, camh, corners, id, extra);
144  }
145 }
146 
147 // ####################################################################################################
148 void QRcode::drawDetections(jevois::RawImage & outimg, int txtx, int txty, zbar::Image & zgray,
149  int w, int h, size_t nshow)
150 {
151  static unsigned short const txtcol = jevois::yuyv::White;
152 
153  // Show all the results:
154  std::string txt; std::vector<std::string> qdata;
155  for (zbar::Image::SymbolIterator symbol = zgray.symbol_begin(); symbol != zgray.symbol_end(); ++symbol)
156  {
157  // Build up some strings to be displayed as video overlay:
158  txt += ' ' + symbol->get_type_name();
159  qdata.push_back(std::string(symbol->get_type_name()) + ": " + symbol->get_data());
160 
161  // Draw a polygon around the detected symbol: for QR codes, we get 4 points at the corners, but for others we
162  // get a bunch of points all over the barcode:
163  if (symbol->get_type() == zbar::ZBAR_QRCODE)
164  {
165  zbar::Symbol::Point pp(-1000000, -1000000);
166  for (zbar::Symbol::PointIterator pitr = symbol->point_begin(); pitr != symbol->point_end(); ++pitr)
167  {
168  zbar::Symbol::Point p(*pitr);
169  if (pp.x != -1000000) jevois::rawimage::drawLine(outimg, pp.x, pp.y, p.x, p.y, 1, jevois::yuyv::DarkPink);
170  pp = p;
171  }
172  if (pp.x != -1000000)
173  {
174  zbar::Symbol::Point p = *(symbol->point_begin());
175  jevois::rawimage::drawLine(outimg, pp.x, pp.y, p.x, p.y, 1, jevois::yuyv::DarkPink);
176  }
177  }
178  else
179  {
180  int tlx = w, tly = h, brx = -1, bry = -1;
181  for (zbar::Symbol::PointIterator pitr = symbol->point_begin(); pitr != symbol->point_end(); ++pitr)
182  {
183  zbar::Symbol::Point p(*pitr);
184  if (p.x < tlx) tlx = p.x;
185  if (p.x > brx) brx = p.x;
186  if (p.y < tly) tly = p.y;
187  if (p.y > bry) bry = p.y;
188  }
189  tlx = std::min(int(w)-1, std::max(0, tlx));
190  brx = std::min(int(w)-1, std::max(0, brx));
191  tly = std::min(int(h)-1, std::max(0, tly));
192  bry = std::min(int(h)-1, std::max(0, bry));
193  jevois::rawimage::drawRect(outimg, tlx, tly, brx - tlx, bry - tly, 1, jevois::yuyv::DarkPink);
194  }
195  }
196 
197  // Write some strings in the output video with what we found and decoded:
198  if (qdata.empty())
199  jevois::rawimage::writeText(outimg, "Found no symbols.", txtx, txty, txtcol);
200  else
201  {
202  txt = "Found " + std::to_string(qdata.size()) + " symbols:" + txt;
203  jevois::rawimage::writeText(outimg, txt.c_str(), txtx, txty, txtcol);
204  for (size_t i = 0; i < std::min(qdata.size(), nshow - 1); ++i)
205  jevois::rawimage::writeText(outimg, qdata[i].c_str(), txtx, txty + (i+1) * 10, txtcol);
206  }
207 }
208 
209 #ifdef JEVOIS_PRO
210 // ####################################################################################################
211 void QRcode::drawDetections(jevois::GUIhelper & helper, zbar::Image & zgray, int w, int h)
212 {
213  ImU32 const col = ImColor(255, 192, 64, 255); // for lines
214 
215  // Show all the results:
216  std::vector<std::string> qdata;
217  for (zbar::Image::SymbolIterator symbol = zgray.symbol_begin(); symbol != zgray.symbol_end(); ++symbol)
218  {
219  // Build up some strings to be displayed as video overlay:
220  qdata.push_back(" - " + std::string(symbol->get_type_name()) + ": " + symbol->get_data());
221 
222  // Draw a polygon around the detected symbol: for QR codes, we get 4 points at the corners, but for others we
223  // get a bunch of points all over the barcode:
224  if (symbol->get_type() == zbar::ZBAR_QRCODE)
225  {
226  std::vector<cv::Point2f> points;
227  for (zbar::Symbol::PointIterator pitr = symbol->point_begin(); pitr != symbol->point_end(); ++pitr)
228  {
229  zbar::Symbol::Point p(*pitr);
230  points.emplace_back(cv::Point2f(p.x, p.y));
231  }
232  helper.drawPoly(points, col, true);
233  }
234  else
235  {
236  int tlx = w, tly = h, brx = -1, bry = -1;
237  for (zbar::Symbol::PointIterator pitr = symbol->point_begin(); pitr != symbol->point_end(); ++pitr)
238  {
239  zbar::Symbol::Point p(*pitr);
240  if (p.x < tlx) tlx = p.x;
241  if (p.x > brx) brx = p.x;
242  if (p.y < tly) tly = p.y;
243  if (p.y > bry) bry = p.y;
244  }
245  tlx = std::min(int(w)-1, std::max(0, tlx));
246  brx = std::min(int(w)-1, std::max(0, brx));
247  tly = std::min(int(h)-1, std::max(0, tly));
248  bry = std::min(int(h)-1, std::max(0, bry));
249  helper.drawRect(tlx, tly, brx, bry, col, true);
250  }
251  }
252 
253  // Write some strings in the output video with what we found and decoded:
254  helper.itext("Detected " + std::to_string(qdata.size()) + " QRcode/Barcode symbols.");
255  for (size_t i = 0; i < qdata.size(); ++i) helper.itext(qdata[i]);
256 }
257 
258 #endif
jevois::GUIhelper
QRcode::~QRcode
~QRcode()
Destructor.
Definition: QRcode.C:31
jevois::StdModule::sendSerialContour2D
void sendSerialContour2D(unsigned int camw, unsigned int camh, std::vector< cv::Point_< T > > points, std::string const &id="", std::string const &extra="")
QRcode::QRcode
QRcode(std::string const &instance)
Constructor.
Definition: QRcode.C:24
jevois::GUIhelper::itext
void itext(char const *txt, ImU32 const &col=IM_COL32_BLACK_TRANS, int line=-1)
Module.H
jevois::split
std::vector< std::string > split(std::string const &input, std::string const &regex="\\s+")
demo.points
points
Definition: demo.py:68
QRcode::onParamChange
void onParamChange(qrcode::symbol const &param, std::string const &newval) override
Parse symbol config strings when they change.
Definition: QRcode.C:35
QRcode::sendSerial
void sendSerial(jevois::StdModule *mod, zbar::Image &img, unsigned int camw, unsigned int camh)
Send serial messages about our detections.
Definition: QRcode.C:126
jevois::RawImage
LERROR
#define LERROR(msg)
jevois::GUIhelper::drawRect
void drawRect(float x1, float y1, float x2, float y2, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
demo.image
image
Definition: demo.py:84
jevois::rawimage::writeText
void writeText(RawImage &img, std::string const &txt, int x, int y, unsigned int col, Font font=Font6x10)
QRcode::itsScanner
std::shared_ptr< zbar::ImageScanner > itsScanner
Definition: QRcode.H:84
jevois
jevois::GUIhelper::drawPoly
void drawPoly(std::vector< cv::Point > const &pts, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
demo.results
results
Definition: demo.py:89
LFATAL
#define LFATAL(msg)
RawImageOps.H
QRcode::process
void process(zbar::Image &image)
Process a greayscale image.
Definition: QRcode.C:94
to_string
std::string to_string(T const &val)
Utils.H
jevois::rawimage::drawRect
void drawRect(RawImage &img, int x, int y, unsigned int w, unsigned int h, unsigned int thick, unsigned int col)
QRcode::drawDetections
void drawDetections(jevois::RawImage &outimg, int txtx, int txty, zbar::Image &zgray, int w, int h, size_t nshow)
Draw any markers previously detected by process()
Definition: QRcode.C:148
h
int h
jevois::StdModule
jevois::rawimage::drawLine
void drawLine(RawImage &img, int x1, int y1, int x2, int y2, unsigned int thick, unsigned int col)
QRcode.H
demo.w
w
Definition: demo.py:85