ArMarkerLocalizerOpenCV.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package VisionX::Component
19  * @author David Schiebener (schiebener at kit dot edu)
20  * @date 2015
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
26 
27 #include <Eigen/Core>
28 #include <Eigen/src/Geometry/Transform.h>
29 
30 #include <opencv2/calib3d.hpp>
31 #include <opencv2/core/eigen.hpp>
32 #include <opencv2/highgui.hpp>
33 
34 // IVT
35 #include <SimoxUtility/algorithm/string.h>
36 
39 
41 
44 
45 #include <Calibration/Calibration.h>
46 #include <Image/IplImageAdaptor.h>
47 
48 namespace visionx
49 {
50 
52  std::string prefix) :
54  {
55  }
56 
59  {
62 
63  defs->optional(
64  p.imageProviderName, "img.ImageProviderName", "Name of the image provider to use.");
65  defs->optional(
66  p.referenceFrame, "img.ReferenceFrameName", "Name of the ReferenceFrameName");
67  defs->optional(p.agentName, "img.AgentName", "Name of the agent");
68  defs->optional(p.cameraIndex, "img.cameraIndex", "Camera index. Left = 0, Right = 1, ...");
69 
70  std::string pattern = "[ k3 [, k4, k5, k6 [, s1, s2, s3, s4 ] ] ]";
71  // defs->optional(p.extraDistortionCoeffs, "cam.ExtraDistortionCoeffs",
72  defs->defineOptionalProperty<std::vector<std::string>>(
73  "cam.ExtraDistortionCoeffs",
74  {},
75  "Optional extra distortion coefficients (which cannot be retrieved from the image "
76  "provider)."
77  "\nThe expected parameters are: " +
78  pattern +
79  ""
80  "\nThat is, you must specifiy 1 (k3), 4 (k3-k6), or 8 (k3-k6, s1-s4) elements."
81  "\nNote: k1, k2, p1, p2 are retrieved from the image provider.")
82  .map(pattern, {});
83 
84  defs->defineOptionalProperty<float>(
85  "ar.MarkerSize", p.markerSize.load(), "The side length of the marker(s)");
86  defs->optional(p.dictionary, "ar.Dictionary", "The ArUco dictionary.")
87  .map("4X4_50", cv::aruco::DICT_4X4_50)
88  .map("4X4_100", cv::aruco::DICT_4X4_100)
89  .map("4X4_250", cv::aruco::DICT_4X4_250)
90  .map("4X4_1000", cv::aruco::DICT_4X4_1000)
91  .map("5X5_50", cv::aruco::DICT_5X5_50)
92  .map("5X5_100", cv::aruco::DICT_5X5_100)
93  .map("5X5_250", cv::aruco::DICT_5X5_250)
94  .map("5X5_1000", cv::aruco::DICT_5X5_1000)
95  .map("6X6_50", cv::aruco::DICT_6X6_50)
96  .map("6X6_100", cv::aruco::DICT_6X6_100)
97  .map("6X6_250", cv::aruco::DICT_6X6_250)
98  .map("6X6_1000", cv::aruco::DICT_6X6_1000)
99  .map("7X7_50", cv::aruco::DICT_7X7_50)
100  .map("7X7_100", cv::aruco::DICT_7X7_100)
101  .map("7X7_250", cv::aruco::DICT_7X7_250)
102  .map("7X7_1000", cv::aruco::DICT_7X7_1000)
103  .map("ARUCO_ORIGINAL", cv::aruco::DICT_ARUCO_ORIGINAL);
104 
105  defs->defineOptionalProperty<std::string>("ar.MarkerGeneration",
106  "https://chev.me/arucogen/",
107  "You can generate ArUco markers here.");
108 
109  defs->defineOptionalProperty<bool>(
110  "visu.Enabled", p.visuEnabled.load(), "If true, visualize marker poses.");
111 
112  return defs;
113  }
114 
116  {
117  addPlugin(virtualRobotReaderPlugin);
118  }
119 
120  std::string
122  {
123  return "ArMarkerLocalizerOpenCV";
124  }
125 
126  void
128  {
129  ARMARX_INFO << VAROUT(p.dictionary);
130  *arucoDictionary = cv::aruco::getPredefinedDictionary(p.dictionary);
131  p.markerSize = getProperty<float>("ar.MarkerSize").getValue();
132  ARMARX_INFO << VAROUT(p.markerSize);
133 
134  p.visuEnabled = getProperty<bool>("visu.Enabled").getValue();
135 
136  {
137  std::string propName = "cam.ExtraDistortionCoeffs";
138  std::vector<std::string> coeffsStr;
139  getProperty(coeffsStr, "cam.ExtraDistortionCoeffs");
140 
141  p.extraDistortionCoeffs.clear();
142  for (const auto& coeffStr : coeffsStr)
143  {
144  try
145  {
146  p.extraDistortionCoeffs.push_back(std::stof(coeffStr));
147  }
148  catch (const std::invalid_argument&)
149  {
150  ARMARX_WARNING << "Could not parse '" << coeffStr << "' as float in property "
151  << propName << "." << "\nIgnoring extra parameters.";
152  p.extraDistortionCoeffs.clear();
153  break;
154  }
155  }
156  }
157  }
158 
159  void
161  {
162  ARMARX_CHECK_NOT_NULL(virtualRobotReaderPlugin);
163 
164  robot = virtualRobotReaderPlugin->get().getRobot(p.agentName);
165  ARMARX_CHECK_NOT_NULL(robot) << p.agentName;
166 
167  referenceNode = robot->getRobotNode(p.referenceFrame);
168  ARMARX_CHECK_NOT_NULL(referenceNode) << p.referenceFrame;
169 
170  ARMARX_VERBOSE << "Marker size: " << p.markerSize;
171 
172  visionx::ImageProviderInfo imageProviderInfo = getImageProvider(p.imageProviderName);
173  StereoCalibrationInterfacePrx calibrationProvider =
174  StereoCalibrationInterfacePrx::checkedCast(imageProviderInfo.proxy);
175 
176  std::unique_ptr<CStereoCalibration> stereoCalibration(
177  visionx::tools::convert(calibrationProvider->getStereoCalibration()));
178  CCalibration::CCameraParameters ivtCameraParameters =
179  stereoCalibration->GetLeftCalibration()->GetCameraParameters();
180 
181  this->cameraMatrix = visionx::makeCameraMatrix(ivtCameraParameters);
182  ARMARX_VERBOSE << "Camera matrix: \n" << this->cameraMatrix;
183 
184  {
185  // "Vector of distortion coefficients (k1,k2,p1,p2 [,k3 [,k4,k5,k6], [s1,s2,s3,s4]]) of 4, 5, 8 or 12 elements"
186  // Source: https://docs.opencv.org/3.2.0/d9/d6a/group__aruco.html#ga7da45d2e8139504f3a532d884b4fb4ac
187 
188  std::set<int> allowedSizes = {4, 5, 8, 12};
189  ARMARX_VERBOSE << "Got " << p.extraDistortionCoeffs.size()
190  << " extra distortion coefficients.";
191 
192  int num = int(4 + p.extraDistortionCoeffs.size());
193  ARMARX_CHECK_POSITIVE(allowedSizes.count(num))
194  << "Allowed sizes: "
195  << simox::alg::join(
196  simox::alg::multi_to_string(allowedSizes.begin(), allowedSizes.end()), " ")
197  << "\n num = " << num << " = 4 + " << p.extraDistortionCoeffs.size()
198  << " = 4 + #extra coeffs";
199 
200  cv::Mat distortionParameters(num, 1, cv::DataType<float>::type);
201 
202  if (!calibrationProvider->getImagesAreUndistorted())
203  {
204  // k1, k2, p1, p2
205  for (int i = 0; i < 4; ++i)
206  {
207  distortionParameters.at<float>(i, 0) = ivtCameraParameters.distortion[i];
208  }
209  // extra
210  for (int i = 0; size_t(i) < p.extraDistortionCoeffs.size(); ++i)
211  {
212  distortionParameters.at<float>(4 + i, 0) =
213  p.extraDistortionCoeffs.at(size_t(i));
214  }
215  }
216  else
217  {
218  for (int i = 0; i < distortionParameters.rows; ++i)
219  {
220  distortionParameters.at<float>(i, 0) = 0;
221  }
222  }
223 
224  this->distortionCoeffs = distortionParameters;
225  ARMARX_CHECK_POSITIVE(allowedSizes.count(this->distortionCoeffs.rows));
226  }
227  ARMARX_VERBOSE << "Distortion coefficients: \n" << this->distortionCoeffs;
228 
229 
230  cameraImages = new CByteImage*[2];
231 
232  cameraImages[0] = tools::createByteImage(imageProviderInfo);
233  cameraImages[1] = tools::createByteImage(imageProviderInfo);
234 
237  }
238 
239  void
241  {
242  if (waitForImages(500))
243  {
244  getImages(cameraImages);
245  }
246  else
247  {
248  ARMARX_VERBOSE << "Timeout or error in wait for images.";
249  return;
250  }
251 
252  ArMarkerLocalizationResultList result = localizeAllMarkersInternal();
253  {
254  std::unique_lock lock(resultMutex);
255  lastLocalizationResult = result;
256  }
257 
258  {
259  armarx::viz::Layer layer = arviz.layer("Marker Poses");
260  if (p.visuEnabled)
261  {
262  const Eigen::Isometry3f global_T_frame{referenceNode->getGlobalPose()};
263 
264  for (const auto& r : result)
265  {
266  const Eigen::Isometry3f frame_T_marker{
267  armarx::FramedPosePtr::dynamicCast(r.pose)->toEigen()};
268  const Eigen::Isometry3f global_T_marker = global_T_frame * frame_T_marker;
269 
270  layer.add(
271  armarx::viz::Pose(std::to_string(r.id)).pose(global_T_marker.matrix()));
272  }
273  }
274  arviz.commit({layer});
275  }
276  }
277 
278  ArMarkerLocalizationResultList
279  ArMarkerLocalizerOpenCV::localizeAllMarkersInternal()
280  {
281  ARMARX_TRACE;
282  ARMARX_CHECK(
283  virtualRobotReaderPlugin->get().synchronizeRobot(*robot, armarx::Clock::Now()));
284 
285  cameraImages[0]->bytesPerPixel = 3;
286  cameraImages[1]->bytesPerPixel = 3;
287 
288  IplImage* imageIpl = IplImageAdaptor::Adapt(cameraImages[p.cameraIndex]);
289  cv::Mat imageOpenCV = cv::cvarrToMat(imageIpl);
290 
291  // cv::imshow("Input", imageOpenCV);
292  // cv::waitKey(10);
293 
294  // Detect markers in image.
295 
296  ARMARX_DEBUG << "Calling marker detection";
297 
298  std::vector<int> markerIDs;
299  std::vector<std::vector<cv::Point2f>> markerCorners;
300  cv::aruco::detectMarkers(
301  imageOpenCV, arucoDictionary, markerCorners, markerIDs, arucoParameters);
302 
303 
304  ARMARX_CHECK_EQUAL(markerIDs.size(), markerCorners.size());
305 
306  ARMARX_VERBOSE << "Localized " << markerIDs.size() << " markers: "
307  << simox::alg::join(simox::alg::multi_to_string(markerIDs), " ");
308 
309  // We could draw an visu image:
310  cv::Mat outputImage = imageOpenCV.clone();
311  if (not markerIDs.empty())
312  {
313  cv::aruco::drawDetectedMarkers(outputImage, markerCorners, markerIDs);
314  }
315  // cv::aruco::drawDetectedMarkers(imageOpenCV, markerCorners, markerIDs);
316 
317 
318  // Estimate marker poses.
319  ARMARX_DEBUG << "Estimating marker poses.";
320 
321  std::vector<cv::Vec3d> rvecs, tvecs;
322  cv::aruco::estimatePoseSingleMarkers(
323  markerCorners, p.markerSize, cameraMatrix, distortionCoeffs, rvecs, tvecs);
324  ARMARX_CHECK_EQUAL(rvecs.size(), markerCorners.size());
325  ARMARX_CHECK_EQUAL(tvecs.size(), markerCorners.size());
326  ARMARX_VERBOSE << "Estimated " << rvecs.size() << " marker poses.";
327 
328  // Assemble results
329 
330  visionx::ArMarkerLocalizationResultList resultList;
331 
332  for (size_t i = 0; i < markerIDs.size(); ++i)
333  {
334  visionx::ArMarkerLocalizationResult& result = resultList.emplace_back();
335 
336  const cv::Vec3d& tvec = tvecs.at(i);
337  Eigen::Vector3f position = Eigen::Vector3d(tvec(0), tvec(1), tvec(2)).cast<float>();
338 
339  cv::Mat cvOrientation;
340  try
341  {
342  cv::Rodrigues(rvecs.at(i), cvOrientation);
343  }
344  catch (const std::exception& e)
345  {
346  ARMARX_ERROR << "Caught exception when running cv::aruco::Rodrigues(): \n"
347  << e.what();
348  return {};
349  }
350  ARMARX_CHECK_EQUAL(cvOrientation.rows, 3);
351  ARMARX_CHECK_EQUAL(cvOrientation.cols, 3);
352 
353  Eigen::Matrix3d orientation;
354  cv::cv2eigen(cvOrientation, orientation);
355 
356  result.pose = new armarx::FramedPose(
357  orientation.cast<float>(), position, p.referenceFrame, p.agentName);
358  result.id = markerIDs.at(i);
359 
360  cv::drawFrameAxes(outputImage, cameraMatrix, distortionCoeffs, rvecs[i], tvecs[i], 0.1);
361  }
362 
363  CByteImage* output_cimage =
364  new CByteImage(outputImage.size[0], outputImage.size[1], CByteImage::ImageType::eRGB24);
365  copyCvMatToIVT(outputImage, output_cimage);
366 
367  CByteImage* result_images[2] = {cameraImages[0], output_cimage};
368  provideResultImages(result_images);
369  delete output_cimage;
370  return resultList;
371  }
372 
373  visionx::ArMarkerLocalizationResultList
375  {
376  if (waitForImages(500))
377  {
378  getImages(cameraImages);
379  return localizeAllMarkersInternal();
380  }
381  else
382  {
383  ARMARX_WARNING << "No new Images available!";
384  return {};
385  }
386  }
387 
388  ArMarkerLocalizationResultList
390  {
391  std::unique_lock lock(resultMutex);
392  return lastLocalizationResult;
393  }
394 
395  void
397  {
398  using namespace armarx::RemoteGui::Client;
399 
400  GridLayout grid;
401  int row = 0;
402 
403  tab.markerSize.setRange(1.0, 1000.0);
404  tab.markerSize.setSteps(1000);
405  tab.markerSize.setDecimals(1);
406  tab.markerSize.setValue(p.markerSize);
407 
408  tab.visuEnabled.setValue(p.visuEnabled);
409 
410  grid.add(Label("Marker size:"), {row, 0}).add(tab.markerSize, {row, 1});
411  row++;
412  grid.add(Label("Enable visu:"), {row, 0}).add(tab.visuEnabled, {row, 1});
413  row++;
414 
415  VBoxLayout root = {grid, VSpacer()};
416  RemoteGui_createTab(getName(), root, &tab);
417  }
418 
419  void
421  {
422  if (tab.markerSize.hasValueChanged())
423  {
424  p.markerSize = tab.markerSize.getValue();
425  }
426  if (tab.visuEnabled.hasValueChanged())
427  {
428  p.visuEnabled = tab.visuEnabled.getValue();
429  }
430  }
431 
432 } // namespace visionx
visionx::ArMarkerLocalizerOpenCV::onInitImageProcessor
void onInitImageProcessor() override
Setup the vision component.
Definition: ArMarkerLocalizerOpenCV.cpp:127
visionx::ArMarkerLocalizerOpenCV::getDefaultName
std::string getDefaultName() const override
Definition: ArMarkerLocalizerOpenCV.cpp:121
armarx::viz::Client::commit
CommitResult commit(StagedCommit const &commit)
Definition: Client.cpp:80
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
visionx::ArMarkerLocalizerOpenCV::createRemoteGuiTab
void createRemoteGuiTab()
Definition: ArMarkerLocalizerOpenCV.cpp:396
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
visionx::ArMarkerLocalizerOpenCVPropertyDefinitions
Definition: ArMarkerLocalizerOpenCV.h:50
visionx::ArMarkerLocalizerOpenCV::RemoteGui_update
void RemoteGui_update() override
Definition: ArMarkerLocalizerOpenCV.cpp:420
armarx::VariantType::FramedPose
const VariantTypeId FramedPose
Definition: FramedPose.h:37
visionx::ArMarkerLocalizerOpenCV::process
void process() override
Process the vision component.
Definition: ArMarkerLocalizerOpenCV.cpp:240
armarx::RemoteGui::Client::VBoxLayout
Definition: Widgets.h:167
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
armarx::RemoteGui::Client::GridLayout::add
GridLayout & add(Widget const &child, Pos pos, Span span=Span{1, 1})
Definition: Widgets.cpp:412
visionx::ImageProcessor::getImageProvider
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
Definition: ImageProcessor.cpp:152
visionx::ArMarkerLocalizerOpenCV::LocalizeAllMarkersNow
visionx::ArMarkerLocalizationResultList LocalizeAllMarkersNow(const Ice::Current &) override
Definition: ArMarkerLocalizerOpenCV.cpp:374
visionx::ArMarkerLocalizerOpenCV::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: ArMarkerLocalizerOpenCV.cpp:58
armarx::ManagedIceObject::addPlugin
PluginT * addPlugin(const std::string prefix="", ParamsT &&...params)
Definition: ManagedIceObject.h:182
armarx::viz::Layer::add
void add(ElementT const &element)
Definition: Layer.h:29
armarx::RemoteGui::Client::VSpacer
Definition: Widgets.h:204
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
visionx::tools::createByteImage
CByteImage * createByteImage(const ImageFormatInfo &imageFormat, const ImageType imageType)
Creates a ByteImage for the destination type specified in the given imageProviderInfo.
Clock.h
visionx::ArMarkerLocalizerOpenCV::onConnectImageProcessor
void onConnectImageProcessor() override
Implement this method in the ImageProcessor in order execute parts when the component is fully initia...
Definition: ArMarkerLocalizerOpenCV.cpp:160
visionx::ImageProviderInfo
Definition: ImageProcessor.h:466
visionx::tools::convert
CByteImage::ImageType convert(const ImageType visionxImageType)
Converts a VisionX image type into an image type of IVT's ByteImage.
Definition: TypeMapping.cpp:95
ArMarkerLocalizerOpenCV.h
visionx::voxelgrid::Label
uint32_t Label
Type of an object label.
Definition: types.h:7
armarx::RemoteGui::Client::GridLayout
Definition: Widgets.h:186
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
FramedPose.h
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:695
armarx::conversions::cv2eigen
Eigen::Vector2f cv2eigen(const cv::Point2f &pt)
Definition: opencv_eigen.h:47
visionx::ArMarkerLocalizerOpenCV::GetLatestLocalizationResult
visionx::ArMarkerLocalizationResultList GetLatestLocalizationResult(const Ice::Current &) override
Definition: ArMarkerLocalizerOpenCV.cpp:389
armarx::viz::Pose
Definition: Elements.h:179
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
visionx::ImageProcessor::getImages
int getImages(CByteImage **ppImages)
Poll images from provider.
Definition: ImageProcessor.cpp:351
ARMARX_CHECK_POSITIVE
#define ARMARX_CHECK_POSITIVE(number)
This macro evaluates whether number is positive (> 0) and if it turns out to be false it will throw a...
Definition: ExpressionException.h:145
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_startRunningTask
void RemoteGui_startRunningTask()
Definition: LightweightRemoteGuiComponentPlugin.cpp:110
ExpressionException.h
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:74
visionx::copyCvMatToIVT
void copyCvMatToIVT(cv::Mat const &input, CByteImage *output)
Copies the contents of an OpenCV matrix to an IVT CByteImage.
Definition: OpenCVUtil.cpp:13
visionx::ImageProviderInfo::proxy
ImageProviderInterfacePrx proxy
proxy to image provider
Definition: ImageProcessor.h:472
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::viz::ElementOps::pose
DerivedT & pose(Eigen::Matrix4f const &pose)
Definition: ElementOps.h:159
armarx::ArVizComponentPluginUser::arviz
armarx::viz::Client arviz
Definition: ArVizComponentPlugin.h:43
armarx::PropertyUser::getProperty
Property< PropertyType > getProperty(const std::string &name)
Property creation and retrieval.
Definition: PropertyUser.h:179
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::LightweightRemoteGuiComponentPluginUser::RemoteGui_createTab
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)
Definition: LightweightRemoteGuiComponentPlugin.cpp:95
IceUtil::Handle< class PropertyDefinitionContainer >
OpenCVUtil.h
visionx::ImageProcessorPropertyDefinitions
Definition: ImageProcessor.h:61
ImageUtil.h
visionx::ImageProcessor::provideResultImages
void provideResultImages(CByteImage **images, armarx::MetaInfoSizeBasePtr info=nullptr)
sends result images for visualization
Definition: ImageProcessor.cpp:245
armarx::core::time::Clock::Now
static DateTime Now()
Current time on the virtual clock.
Definition: Clock.cpp:97
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:107
visionx::makeCameraMatrix
cv::Mat makeCameraMatrix(const visionx::CameraParameters &cameraParams)
Definition: opencv_conversions.cpp:25
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::viz::Client::layer
Layer layer(std::string const &name) const
Definition: Client.cpp:73
armarx::RemoteGui::Client
Definition: EigenWidgets.cpp:8
armarx::viz::Layer
Definition: Layer.h:12
visionx::ArMarkerLocalizerOpenCV::ArMarkerLocalizerOpenCV
ArMarkerLocalizerOpenCV()
Definition: ArMarkerLocalizerOpenCV.cpp:115
visionx::ArMarkerLocalizerOpenCVPropertyDefinitions::ArMarkerLocalizerOpenCVPropertyDefinitions
ArMarkerLocalizerOpenCVPropertyDefinitions(std::string prefix)
Definition: ArMarkerLocalizerOpenCV.cpp:51
visionx::ImageProcessor::waitForImages
bool waitForImages(int milliseconds=1000)
Wait for new images.
Definition: ImageProcessor.cpp:275