JeVois  1.10
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
PythonModule.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 
21 
22 // ####################################################################################################
23 // ####################################################################################################
24 // ####################################################################################################
25 
27 { }
28 
30 {
31  if (itsInputFrame == nullptr) LFATAL("Internal error");
32  return itsInputFrame->get(casync);
33 }
34 
36 {
37  if (itsInputFrame == nullptr) LFATAL("Internal error");
38  return itsInputFrame->get();
39 }
40 
42 {
43  if (itsInputFrame == nullptr) LFATAL("Internal error");
44  itsInputFrame->done();
45 }
46 
47 cv::Mat jevois::InputFramePython::getCvGRAY1(bool casync) const
48 {
49  if (itsInputFrame == nullptr) LFATAL("Internal error");
50  return itsInputFrame->getCvGRAY(casync);
51 }
52 
54 {
55  if (itsInputFrame == nullptr) LFATAL("Internal error");
56  return itsInputFrame->getCvGRAY();
57 }
58 
59 cv::Mat jevois::InputFramePython::getCvBGR1(bool casync) const
60 {
61  if (itsInputFrame == nullptr) LFATAL("Internal error");
62  return itsInputFrame->getCvBGR(casync);
63 }
64 
66 {
67  if (itsInputFrame == nullptr) LFATAL("Internal error");
68  return itsInputFrame->getCvBGR();
69 }
70 
71 cv::Mat jevois::InputFramePython::getCvRGB1(bool casync) const
72 {
73  if (itsInputFrame == nullptr) LFATAL("Internal error");
74  return itsInputFrame->getCvRGB(casync);
75 }
76 
78 {
79  if (itsInputFrame == nullptr) LFATAL("Internal error");
80  return itsInputFrame->getCvRGB();
81 }
82 
83 cv::Mat jevois::InputFramePython::getCvRGBA1(bool casync) const
84 {
85  if (itsInputFrame == nullptr) LFATAL("Internal error");
86  return itsInputFrame->getCvRGBA(casync);
87 }
88 
90 {
91  if (itsInputFrame == nullptr) LFATAL("Internal error");
92  return itsInputFrame->getCvRGBA();
93 }
94 
95 // ####################################################################################################
96 // ####################################################################################################
97 // ####################################################################################################
99 { }
100 
102 {
103  if (itsOutputFrame == nullptr) LFATAL("Internal error");
104  return itsOutputFrame->get();
105 }
106 
108 {
109  if (itsOutputFrame == nullptr) LFATAL("Internal error");
110  itsOutputFrame->send();
111 }
112 
113 void jevois::OutputFramePython::sendCv1(cv::Mat const & img, int quality) const
114 {
115  if (itsOutputFrame == nullptr) LFATAL("Internal error");
116  itsOutputFrame->sendCv(img, quality);
117 }
118 
119 void jevois::OutputFramePython::sendCv(cv::Mat const & img) const
120 {
121  if (itsOutputFrame == nullptr) LFATAL("Internal error");
122  itsOutputFrame->sendCv(img);
123 }
124 
125 void jevois::OutputFramePython::sendCvGRAY1(cv::Mat const & img, int quality) const
126 {
127  if (itsOutputFrame == nullptr) LFATAL("Internal error");
128  itsOutputFrame->sendCvGRAY(img, quality);
129 }
130 
131 void jevois::OutputFramePython::sendCvGRAY(cv::Mat const & img) const
132 {
133  if (itsOutputFrame == nullptr) LFATAL("Internal error");
134  itsOutputFrame->sendCvGRAY(img);
135 }
136 
137 void jevois::OutputFramePython::sendCvBGR1(cv::Mat const & img, int quality) const
138 {
139  if (itsOutputFrame == nullptr) LFATAL("Internal error");
140  itsOutputFrame->sendCvBGR(img, quality);
141 }
142 
143 void jevois::OutputFramePython::sendCvBGR(cv::Mat const & img) const
144 {
145  if (itsOutputFrame == nullptr) LFATAL("Internal error");
146  itsOutputFrame->sendCvBGR(img);
147 }
148 
149 void jevois::OutputFramePython::sendCvRGB1(cv::Mat const & img, int quality) const
150 {
151  if (itsOutputFrame == nullptr) LFATAL("Internal error");
152  itsOutputFrame->sendCvRGB(img, quality);
153 }
154 
155 void jevois::OutputFramePython::sendCvRGB(cv::Mat const & img) const
156 {
157  if (itsOutputFrame == nullptr) LFATAL("Internal error");
158  itsOutputFrame->sendCvRGB(img);
159 }
160 
161 void jevois::OutputFramePython::sendCvRGBA1(cv::Mat const & img, int quality) const
162 {
163  if (itsOutputFrame == nullptr) LFATAL("Internal error");
164  itsOutputFrame->sendCvRGBA(img, quality);
165 }
166 
167 void jevois::OutputFramePython::sendCvRGBA(cv::Mat const & img) const
168 {
169  if (itsOutputFrame == nullptr) LFATAL("Internal error");
170  itsOutputFrame->sendCvRGBA(img);
171 }
172 
173 void jevois::OutputFramePython::sendScaledCvGRAY1(cv::Mat const & img, int quality) const
174 {
175  if (itsOutputFrame == nullptr) LFATAL("Internal error");
176  itsOutputFrame->sendScaledCvGRAY(img, quality);
177 }
178 
179 void jevois::OutputFramePython::sendScaledCvGRAY(cv::Mat const & img) const
180 {
181  if (itsOutputFrame == nullptr) LFATAL("Internal error");
182  itsOutputFrame->sendScaledCvGRAY(img);
183 }
184 
185 void jevois::OutputFramePython::sendScaledCvBGR1(cv::Mat const & img, int quality) const
186 {
187  if (itsOutputFrame == nullptr) LFATAL("Internal error");
188  itsOutputFrame->sendScaledCvBGR(img, quality);
189 }
190 
191 void jevois::OutputFramePython::sendScaledCvBGR(cv::Mat const & img) const
192 {
193  if (itsOutputFrame == nullptr) LFATAL("Internal error");
194  itsOutputFrame->sendScaledCvBGR(img);
195 }
196 
197 void jevois::OutputFramePython::sendScaledCvRGB1(cv::Mat const & img, int quality) const
198 {
199  if (itsOutputFrame == nullptr) LFATAL("Internal error");
200  itsOutputFrame->sendScaledCvRGB(img, quality);
201 }
202 
203 void jevois::OutputFramePython::sendScaledCvRGB(cv::Mat const & img) const
204 {
205  if (itsOutputFrame == nullptr) LFATAL("Internal error");
206  itsOutputFrame->sendScaledCvRGB(img);
207 }
208 
209 void jevois::OutputFramePython::sendScaledCvRGBA1(cv::Mat const & img, int quality) const
210 {
211  if (itsOutputFrame == nullptr) LFATAL("Internal error");
212  itsOutputFrame->sendScaledCvRGBA(img, quality);
213 }
214 
215 void jevois::OutputFramePython::sendScaledCvRGBA(cv::Mat const & img) const
216 {
217  if (itsOutputFrame == nullptr) LFATAL("Internal error");
218  itsOutputFrame->sendScaledCvRGBA(img);
219 }
220 
221 
222 // ####################################################################################################
223 namespace
224 {
225  // from https://stackoverflow.com/questions/39924912/finding-if-member-function-exists-in-a-boost-pythonobject
226  bool hasattr(boost::python::object & o, char const * name) { return PyObject_HasAttrString(o.ptr(), name); }
227 }
228 
229 // ####################################################################################################
230 // ####################################################################################################
231 // ####################################################################################################
233  jevois::Module(m.modulename), itsMainModule(), itsMainNamespace(), itsInstance(), itsConstructionError()
234 {
235  if (m.ispython == false) LFATAL("Passed video mapping is not for a python module");
236 
237  // Do not throw during construction because we need users to be able to save modified code from JeVois Inventor, which
238  // requires a valid module with a valid path being set by Engine:
239  try
240  {
241  // Get the python interpreter going:
242  itsMainModule = boost::python::import("__main__");
243  itsMainNamespace = itsMainModule.attr("__dict__");
244 
245  // Import the module. Note that we import the whole directory:
246  std::string const pypath = m.sopath();
247  std::string const pydir = pypath.substr(0, pypath.rfind('/'));
248  std::string const execstr =
249  "import sys\n"
250  "sys.path.append(\"/usr/lib\")\n" // To find libjevois module in /usr/lib
251  "sys.path.append(\"" JEVOIS_OPENCV_PYTHON_PATH "\")\n" // To find cv2 module
252  "sys.path.append(\"" + pydir + "\")\n" +
253  "import " + m.modulename + "\n" +
254  "import importlib\n" +
255  "importlib.reload(" + m.modulename + ")\n"; // reload so we are always fresh if file changed on SD card
256 
257  boost::python::exec(execstr.c_str(), itsMainNamespace, itsMainNamespace);
258 
259  // Create an instance of the python class defined in the module:
260  itsInstance = boost::python::eval((m.modulename + "." + m.modulename + "()").c_str(),
261  itsMainNamespace, itsMainNamespace);
262  }
263  catch (boost::python::error_already_set & e)
264  {
265  itsConstructionError = "Initialization of Module " + m.modulename + " failed:\n\n" +
267  }
268 }
269 
270 // ####################################################################################################
272 {
273  // Call python module's uninit() function if implemented:
274  if (hasattr(itsInstance, "uninit")) itsInstance.attr("uninit")();
275 }
276 
277 // ####################################################################################################
279 { }
280 
281 // ####################################################################################################
283 {
284  if (itsInstance.is_none()) throw std::runtime_error(itsConstructionError);
285 
286  jevois::InputFramePython inframepy(&inframe);
287  jevois::OutputFramePython outframepy(&outframe);
288  itsInstance.attr("process")(boost::ref(inframepy), boost::ref(outframepy));
289 }
290 
291 // ####################################################################################################
293 {
294  if (itsInstance.is_none()) throw std::runtime_error(itsConstructionError);
295 
296  jevois::InputFramePython inframepy(&inframe);
297  itsInstance.attr("processNoUSB")(boost::ref(inframepy));
298 }
299 
300 // ####################################################################################################
301 void jevois::PythonModule::parseSerial(std::string const & str, std::shared_ptr<UserInterface> s)
302 {
303  if (hasattr(itsInstance, "parseSerial"))
304  {
305  boost::python::object ret = itsInstance.attr("parseSerial")(str);
306  std::string retstr = boost::python::extract<std::string>(ret);
307  if (retstr.empty() == false) s->writeString(retstr);
308  }
309  else jevois::Module::parseSerial(str, s);
310 }
311 
312 // ####################################################################################################
314 {
315  if (hasattr(itsInstance, "supportedCommands"))
316  {
317  boost::python::object ret = itsInstance.attr("supportedCommands")();
318  std::string retstr = boost::python::extract<std::string>(ret);
319  if (retstr.empty() == false) os << retstr;
321 }
322 
323 
void sendCvGRAY1(cv::Mat const &img, int quality) const
Shorthand to send a GRAY cv::Mat after converting it to the current output format.
Definition: PythonModule.C:125
void sendScaledCvRGBA1(cv::Mat const &img, int quality) const
Shorthand to send a RGBA cv::Mat after scaling/converting it to the current output format...
Definition: PythonModule.C:209
Exception-safe wrapper around a raw camera input frame.
Definition: Module.H:57
Wrapper around OutputFrame to be used by Python.
Definition: PythonModule.H:97
virtual void supportedCommands(std::ostream &os) override
Human-readable description of this Module&#39;s supported custom commands.
Definition: PythonModule.C:313
void sendCvRGB1(cv::Mat const &img, int quality) const
Shorthand to send a RGB cv::Mat after converting it to the current output format. ...
Definition: PythonModule.C:149
cv::Mat getCvRGBA(bool casync=false) const
Shorthand to get the input image as a RGBA cv::Mat and release the raw buffer.
Definition: Module.C:94
void sendScaledCvRGB(cv::Mat const &img, int quality=75) const
Shorthand to send a RGB cv::Mat after converting it to the current output format. ...
Definition: Module.C:209
void sendScaledCvGRAY1(cv::Mat const &img, int quality) const
Shorthand to send a GRAY cv::Mat after scaling/converting it to the current output format...
Definition: PythonModule.C:173
PythonModule(VideoMapping const &m)
Constructor needs the full path to a Python source code file.
Definition: PythonModule.C:232
void sendScaledCvBGR(cv::Mat const &img, int quality=75) const
Shorthand to send a BGR cv::Mat after converting it to the current output format. ...
Definition: Module.C:201
void sendCvRGBA(cv::Mat const &img, int quality=75) const
Shorthand to send a RGBA cv::Mat after converting it to the current output format.
Definition: Module.C:184
void sendCvBGR1(cv::Mat const &img, int quality) const
Shorthand to send a BGR cv::Mat after converting it to the current output format. ...
Definition: PythonModule.C:137
cv::Mat getCvRGBA1(bool casync) const
Shorthand to get the input image as a RGBA cv::Mat and release the raw buffer.
Definition: PythonModule.C:83
virtual void parseSerial(std::string const &str, std::shared_ptr< UserInterface > s) override
Receive a string from a serial port which contains a user command.
Definition: PythonModule.C:301
void send() const
Send an image out over USB to the host computer.
Definition: Module.C:141
void sendCvRGB(cv::Mat const &img, int quality=75) const
Shorthand to send a RGB cv::Mat after converting it to the current output format. ...
Definition: Module.C:176
void sendCv(cv::Mat const &img, int quality=75) const
Shorthand to send a cv::Mat after converting / scaling it to the current output format.
Definition: Module.C:149
RawImage const & get(bool casync=false) const
Get the next captured camera image.
Definition: Module.C:51
void sendCvGRAY(cv::Mat const &img, int quality=75) const
Shorthand to send a GRAY cv::Mat after converting it to the current output format.
Definition: Module.C:161
virtual void supportedCommands(std::ostream &os)
Human-readable description of this Module&#39;s supported custom commands.
Definition: Module.C:259
void sendCv1(cv::Mat const &img, int quality) const
Shorthand to send a cv::Mat after scaling/converting it to the current output format.
Definition: PythonModule.C:113
std::string modulename
Name of the Module that will process this mapping.
Definition: VideoMapping.H:60
void sendCvGRAY(cv::Mat const &img) const
Shorthand to send a GRAY cv::Mat after converting it to the current output format.
Definition: PythonModule.C:131
void sendCvRGB(cv::Mat const &img) const
Shorthand to send a RGB cv::Mat after converting it to the current output format. ...
Definition: PythonModule.C:155
void sendCvRGBA(cv::Mat const &img) const
Shorthand to send a RGBA cv::Mat after converting it to the current output format.
Definition: PythonModule.C:167
RawImage const & get() const
Get the next captured camera image, thin wrapper for default arg value.
Definition: PythonModule.C:35
RawImage const & get1(bool casync) const
Get the next captured camera image, thin wrapper for default arg value.
Definition: PythonModule.C:29
void sendScaledCvRGBA(cv::Mat const &img, int quality=75) const
Shorthand to send a RGBA cv::Mat after converting it to the current output format.
Definition: Module.C:218
void sendCvBGR(cv::Mat const &img, int quality=75) const
Shorthand to send a BGR cv::Mat after converting it to the current output format. ...
Definition: Module.C:169
void send() const
Indicate that user processing is done with the image previously obtained via get() ...
Definition: PythonModule.C:107
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition: RawImage.H:110
std::string sopath() const
Return the full absolute path and file name of the module&#39;s .so or .py file.
Definition: VideoMapping.C:30
RawImage const & get() const
Get the next captured camera image.
Definition: PythonModule.C:101
cv::Mat getCvRGB(bool casync=false) const
Shorthand to get the input image as a RGB cv::Mat and release the raw buffer.
Definition: Module.C:85
InputFramePython()=default
Default constructor to keep boost::python happy, object is not operational.
#define o
Definition: Font10x20.C:6
Simple struct to hold video mapping definitions for the processing Engine.
Definition: VideoMapping.H:43
void sendScaledCvBGR1(cv::Mat const &img, int quality) const
Shorthand to send a BGR cv::Mat after scaling/converting it to the current output format...
Definition: PythonModule.C:185
cv::Mat getCvBGR1(bool casync) const
Shorthand to get the input image as a BGR cv::Mat and release the raw buffer.
Definition: PythonModule.C:59
std::string getPythonExceptionString(boost::python::error_already_set &)
Python exception translation to string so we can print the traceback to our serlog stream...
void sendCv(cv::Mat const &img) const
Shorthand to send a cv::Mat after scaling/converting it to the current output format.
Definition: PythonModule.C:119
cv::Mat getCvGRAY() const
Shorthand to get the input image as a GRAY cv::Mat and release the raw buffer.
Definition: PythonModule.C:53
void sendCvBGR(cv::Mat const &img) const
Shorthand to send a BGR cv::Mat after converting it to the current output format. ...
Definition: PythonModule.C:143
Wrapper around InputFrame to be used by Python.
Definition: PythonModule.H:45
cv::Mat getCvGRAY(bool casync=false) const
Shorthand to get the input image as a GRAY cv::Mat and release the raw buffer.
Definition: Module.C:67
void sendScaledCvBGR(cv::Mat const &img) const
Shorthand to send a BGR cv::Mat after scaling/converting it to the current output format...
Definition: PythonModule.C:191
cv::Mat getCvGRAY1(bool casync) const
Shorthand to get the input image as a GRAY cv::Mat and release the raw buffer.
Definition: PythonModule.C:47
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level. ...
Definition: Log.H:212
void sendCvRGBA1(cv::Mat const &img, int quality) const
Shorthand to send a RGBA cv::Mat after converting it to the current output format.
Definition: PythonModule.C:161
virtual void process(InputFrame &&inframe, OutputFrame &&outframe) override
Processing function, version that receives a frame from camera and sends a frame out over USB...
Definition: PythonModule.C:282
void done() const
Indicate that user processing is done with the image previously obtained via get() ...
Definition: PythonModule.C:41
cv::Mat getCvRGB1(bool casync) const
Shorthand to get the input image as a RGB cv::Mat and release the raw buffer.
Definition: PythonModule.C:71
void sendScaledCvRGB(cv::Mat const &img) const
Shorthand to send a RGB cv::Mat after scaling/converting it to the current output format...
Definition: PythonModule.C:203
virtual void parseSerial(std::string const &str, std::shared_ptr< UserInterface > s)
Receive a string from a serial port which contains a user command.
Definition: Module.C:254
OutputFramePython()=default
Default constructor to keep boost::python happy, object is not operational.
Virtual base class for a vision processing module.
Definition: Module.H:336
void sendScaledCvGRAY(cv::Mat const &img, int quality=75) const
Shorthand to send a GRAY cv::Mat after converting it to the current output format.
Definition: Module.C:192
cv::Mat getCvBGR() const
Shorthand to get the input image as a BGR cv::Mat and release the raw buffer.
Definition: PythonModule.C:65
Exception-safe wrapper around a raw image to be sent over USB.
Definition: Module.H:145
void postUninit() override
Optionally call uninit() python module function, if implemented.
Definition: PythonModule.C:271
void sendScaledCvRGBA(cv::Mat const &img) const
Shorthand to send a RGBA cv::Mat after scaling/converting it to the current output format...
Definition: PythonModule.C:215
void sendScaledCvGRAY(cv::Mat const &img) const
Shorthand to send a GRAY cv::Mat after scaling/converting it to the current output format...
Definition: PythonModule.C:179
bool ispython
True if the module is written in Python; affects behavior of sopath() only.
Definition: VideoMapping.H:62
RawImage const & get() const
Get a pre-allocated image so that we can fill the pixel data and later send out over USB using send()...
Definition: Module.C:133
virtual ~PythonModule()
Virtual destructor for safe inheritance.
Definition: PythonModule.C:278
cv::Mat getCvBGR(bool casync=false) const
Shorthand to get the input image as a BGR cv::Mat and release the raw buffer.
Definition: Module.C:76
void done() const
Indicate that user processing is done with the image previously obtained via get() ...
Definition: Module.C:60
void sendScaledCvRGB1(cv::Mat const &img, int quality) const
Shorthand to send a RGB cv::Mat after scaling/converting it to the current output format...
Definition: PythonModule.C:197
cv::Mat getCvRGB() const
Shorthand to get the input image as a RGB cv::Mat and release the raw buffer.
Definition: PythonModule.C:77
cv::Mat getCvRGBA() const
Shorthand to get the input image as a RGBA cv::Mat and release the raw buffer.
Definition: PythonModule.C:89