JeVois  1.20
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
PreProcessorPython.C
Go to the documentation of this file.
1 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2021 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 #include <jevois/DNN/Utils.H>
22 
23 // ####################################################################################################
24 namespace jevois
25 {
26  namespace dnn
27  {
29  {
30  public:
32  void loadpy(std::string const & pypath);
33  virtual ~PreProcessorPythonImpl();
34  void freeze(bool doit);
35  std::vector<cv::Mat> process(cv::Mat const & img, bool swaprb, std::vector<vsi_nn_tensor_attr_t> const & attrs,
36  std::vector<cv::Rect> & crops);
37  void report(jevois::StdModule * mod, jevois::RawImage * outimg = nullptr,
38  jevois::OptGUIhelper * helper = nullptr, bool overlay = true, bool idle = false);
39  };
40  }
41 }
42 
43 // ####################################################################################################
44 // ####################################################################################################
46 { }
47 
48 // ####################################################################################################
50 {
51  if (jevois::python::hasattr(PythonWrapper::pyinst(), "freeze")) PythonWrapper::pyinst().attr("freeze")(doit);
52 }
53 
54 // ####################################################################################################
55 void jevois::dnn::PreProcessorPythonImpl::loadpy(std::string const & pypath)
56 {
57  // Load the code and instantiate the python object:
58  PythonWrapper::pythonload(JEVOIS_SHARE_PATH "/" + pypath);
59  LINFO("Loaded " << pypath);
60 
61  // Now that we are fully up and ready, call python module's init() function if implemented:
63 }
64 
65 // ####################################################################################################
66 std::vector<cv::Mat> jevois::dnn::PreProcessorPythonImpl::process(cv::Mat const & img, bool swaprb,
67  std::vector<vsi_nn_tensor_attr_t> const & attrs,
68  std::vector<cv::Rect> & crops)
69 {
70  // Convert the attrs to a list of strings:
71  boost::python::list alist;
72  for (vsi_nn_tensor_attr_t const & a : attrs) alist.append(jevois::dnn::attrstr(a));
73 
74  // Run the python code:
75  boost::python::object ret = PythonWrapper::pyinst().attr("process")(img, swaprb, alist);
76 
77  // We expect a tuple with first a vector of blobs, then a vector of crops:
78  if (boost::python::len(ret) != 2)
79  throw std::invalid_argument("Expected two return lists for blobs,crops but received " +
80  std::to_string(boost::python::len(ret)));
81 
82  // For the crops, we want cv::Rect but they are not exposing it to python it seems. So let's just accept tuples
83  // ( (x,y), (w,h) )
84 #define CROPERR "PreProcessorPython::process: crops should be ( (x,y), (w,h) )"
85 
86  crops.clear();
87  boost::python::list cl = boost::python::extract<boost::python::list>(ret[1]);
88  for (ssize_t i = 0; i < boost::python::len(cl); ++i)
89  {
90  boost::python::tuple tup = boost::python::extract<boost::python::tuple>(cl[i]);
91  if (boost::python::len(tup) != 2) throw std::runtime_error(CROPERR);
92  boost::python::tuple xy = boost::python::extract<boost::python::tuple>(tup[0]);
93  if (boost::python::len(xy) != 2) throw std::runtime_error(CROPERR);
94  boost::python::tuple wh = boost::python::extract<boost::python::tuple>(tup[1]);
95  if (boost::python::len(wh) != 2) throw std::runtime_error(CROPERR);
96 
97  float x = boost::python::extract<float>(xy[0]);
98  float y = boost::python::extract<float>(xy[1]);
99  float w = boost::python::extract<float>(wh[0]);
100  float h = boost::python::extract<float>(wh[1]);
101  crops.emplace_back(cv::Rect(x, y, w, h));
102  }
103 
104  // For the blobs, we have a converter:
105  boost::python::list ml = boost::python::extract<boost::python::list>(ret[0]);
106  return jevois::python::pyListToVec<cv::Mat>(ml);
107 }
108 
109 // ####################################################################################################
111  jevois::RawImage * outimg, jevois::OptGUIhelper * helper,
112  bool overlay, bool idle)
113 {
114  // default constructed boost::python::object is None on the python side
115  if (outimg)
116  {
117 #ifdef JEVOIS_PRO
118  if (helper)
119  {
120  jevois::GUIhelperPython helperpy(helper);
121  PythonWrapper::pyinst().attr("report")(boost::ref(*outimg), boost::ref(helperpy), overlay, idle);
122  }
123  else
124 #endif
125  PythonWrapper::pyinst().attr("report")(boost::ref(*outimg), boost::python::object(), overlay, idle);
126  }
127  else
128  {
129 #ifdef JEVOIS_PRO
130  if (helper)
131  {
132  jevois::GUIhelperPython helperpy(helper);
133  PythonWrapper::pyinst().attr("report")(boost::python::object(), boost::ref(helperpy), overlay, idle);
134  }
135  else
136 #endif
137  PythonWrapper::pyinst().attr("report")(boost::python::object(), boost::python::object(), overlay, idle);
138  }
139 
140 #ifndef JEVOIS_PRO
141  (void)helper; // avoid compiler warning
142 #endif
143 }
144 
145 // ####################################################################################################
146 // ####################################################################################################
148  jevois::dnn::PreProcessor(instance)
149 {
150  itsImpl = addSubComponent<jevois::dnn::PreProcessorPythonImpl>("pypre");
151 }
152 
153 // ####################################################################################################
155 { }
156 
157 // ####################################################################################################
159 {
160  // First our own params:
161  pypre::freeze(doit);
162 
163  // Then our python params:
164  itsImpl->freeze(doit);
165 }
166 
167 // ####################################################################################################
168 void jevois::dnn::PreProcessorPython::onParamChange(jevois::dnn::preprocessor::pypre const &
169  JEVOIS_UNUSED_PARAM(param), std::string const & newval)
170 {
171  if (newval.empty() == false) itsImpl->loadpy(newval);
172 }
173 
174 // ####################################################################################################
175 std::vector<cv::Mat> jevois::dnn::PreProcessorPython::process(cv::Mat const & img, bool swaprb,
176  std::vector<vsi_nn_tensor_attr_t> const & attrs,
177  std::vector<cv::Rect> & crops)
178 { return itsImpl->process(img, swaprb, attrs, crops); }
179 
180 // ####################################################################################################
182  jevois::OptGUIhelper * helper, bool overlay, bool idle)
183 { itsImpl->report(mod, outimg, helper, overlay, idle); }
184 
jevois::dnn::PreProcessorPython::~PreProcessorPython
virtual ~PreProcessorPython()
Destructor.
Definition: PreProcessorPython.C:154
jevois::ParameterRegistry::Component
friend class Component
Allow Component and DynamicParameter to access our registry data, everyone else is locked out.
Definition: ParameterRegistry.H:51
jevois::dnn::PreProcessorPython::itsImpl
std::shared_ptr< PreProcessorPythonImpl > itsImpl
Definition: PreProcessorPython.H:59
PythonSupport.H
CROPERR
#define CROPERR
jevois::PythonWrapper::pyinst
boost::python::object & pyinst()
Get the python class pyinst, or throw if construction error occurred (e.g., file not found)
Definition: PythonWrapper.C:85
jevois::Component
A component of a model hierarchy.
Definition: Component.H:181
Utils.H
jevois::RawImage
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition: RawImage.H:110
jevois::dnn::PreProcessorPythonImpl
Definition: PreProcessorPython.C:28
jevois::dnn::PreProcessorPythonImpl::report
void report(jevois::StdModule *mod, jevois::RawImage *outimg=nullptr, jevois::OptGUIhelper *helper=nullptr, bool overlay=true, bool idle=false)
Definition: PreProcessorPython.C:110
jevois::dnn::PreProcessorPython::PreProcessorPython
PreProcessorPython(std::string const &instance)
Constructor.
Definition: PreProcessorPython.C:147
jevois::GUIhelperPython
Wrapper around GUIhelper to be used by Python.
Definition: PythonModule.H:224
jevois::GUIhelper
Helper class to assist modules in creating graphical and GUI elements.
Definition: GUIhelper.H:128
PreProcessorPython.H
jevois::dnn::PreProcessorPythonImpl::~PreProcessorPythonImpl
virtual ~PreProcessorPythonImpl()
Definition: PreProcessorPython.C:45
jevois
Definition: Concepts.dox:1
jevois::dnn::PreProcessor
Pre-Processor for neural network pipeline.
Definition: PreProcessor.H:108
jevois::python::hasattr
bool hasattr(boost::python::object &o, char const *name)
Check whether a boost::python::object has an attribute.
Definition: PythonSupport.C:108
jevois::dnn::PreProcessorPythonImpl::loadpy
void loadpy(std::string const &pypath)
Definition: PreProcessorPython.C:55
jevois::dnn::PreProcessorPythonImpl::freeze
void freeze(bool doit)
Definition: PreProcessorPython.C:49
jevois::dnn::PreProcessorPython::freeze
void freeze(bool doit) override
Freeze/unfreeze parameters that users should not change while running.
Definition: PreProcessorPython.C:158
jevois::dnn::PreProcessorPythonImpl::process
std::vector< cv::Mat > process(cv::Mat const &img, bool swaprb, std::vector< vsi_nn_tensor_attr_t > const &attrs, std::vector< cv::Rect > &crops)
Definition: PreProcessorPython.C:66
PythonModule.H
jevois::to_string
std::string to_string(T const &val)
Convert from type to string.
jevois::dnn::attrstr
std::string attrstr(vsi_nn_tensor_attr_t const &attr)
Get a string describing the specs of a tensor, including quantification specs (not provided by shapes...
Definition: Utils.C:511
jevois::PythonWrapper::pythonload
void pythonload(std::string const &path)
Init from path if default constructor was used.
Definition: PythonWrapper.C:34
jevois::PythonWrapper
Helper class to run python code from C++.
Definition: PythonWrapper.H:41
h
int h
Definition: GUIhelper.C:2373
jevois::StdModule
Base class for a module that supports standardized serial messages.
Definition: Module.H:232
jevois::dnn::PreProcessorPython::report
void report(jevois::StdModule *mod, jevois::RawImage *outimg=nullptr, jevois::OptGUIhelper *helper=nullptr, bool overlay=true, bool idle=false) override
Report what happened in last process() to console/output video/GUI.
Definition: PreProcessorPython.C:181
LINFO
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition: Log.H:194
jevois::dnn::PreProcessorPython::onParamChange
void onParamChange(preprocessor::pypre const &param, std::string const &newval) override
Definition: PreProcessorPython.C:168
jevois::dnn::PreProcessorPython::process
std::vector< cv::Mat > process(cv::Mat const &img, bool swaprb, std::vector< vsi_nn_tensor_attr_t > const &attrs, std::vector< cv::Rect > &crops) override
Extract blobs from input image.
Definition: PreProcessorPython.C:175