JeVoisBase  1.21
JeVois Smart Embedded Machine Vision Toolkit Base Modules
Share this page:
Loading...
Searching...
No Matches
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// ####################################################################################################
24QRcode::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// ####################################################################################################
33
34// ####################################################################################################
35void 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// ####################################################################################################
94void 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// ####################################################################################################
106void 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// ####################################################################################################
126void 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// ####################################################################################################
148void 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// ####################################################################################################
211void 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
#define JEVOIS_UNUSED_PARAM(x)
int h
void onParamChange(qrcode::symbol const &param, std::string const &newval) override
Parse symbol config strings when they change.
Definition QRcode.C:35
void process(zbar::Image &image)
Process a greayscale image.
Definition QRcode.C:94
~QRcode()
Destructor.
Definition QRcode.C:31
void sendSerial(jevois::StdModule *mod, zbar::Image &img, unsigned int camw, unsigned int camh)
Send serial messages about our detections.
Definition QRcode.C:126
QRcode(std::string const &instance)
Constructor.
Definition QRcode.C:24
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
std::shared_ptr< zbar::ImageScanner > itsScanner
Definition QRcode.H:84
void drawRect(float x1, float y1, float x2, float y2, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
void itext(char const *txt, ImU32 const &col=IM_COL32_BLACK_TRANS, int line=-1)
void drawPoly(std::vector< cv::Point > const &pts, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
void sendSerialContour2D(unsigned int camw, unsigned int camh, std::vector< cv::Point_< T > > points, std::string const &id="", std::string const &extra="")
#define LFATAL(msg)
#define LERROR(msg)
void writeText(RawImage &img, std::string const &txt, int x, int y, unsigned int col, Font font=Font6x10)
void drawLine(RawImage &img, int x1, int y1, int x2, int y2, unsigned int thick, unsigned int col)
void drawRect(RawImage &img, int x, int y, unsigned int w, unsigned int h, unsigned int thick, unsigned int col)
std::vector< std::string > split(std::string const &input, std::string const &regex="\\s+")
unsigned short constexpr White
unsigned short constexpr DarkPink