ImageSourceSelection.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package VisionX::ArmarXObjects::ImageSourceSelection
17 * @author Markus Grotz ( markus dot grotz at kit dot edu )
18 * @date 2016
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
26
30
33
34#include <Image/ImageProcessor.h>
35
36namespace armarx
37{
38
39 void
41 {
42 defaultProvider = getProperty<std::string>("defaultProviderName").getValue();
43 usingImageProvider(defaultProvider);
44
46 }
47
48 void
50 {
51 imageDisplayType = visionx::tools::typeNameToImageType("rgb");
52
53 imageProviderInfo = getImageProvider(defaultProvider, imageDisplayType);
54 numImages = getProperty<int>("NumberOfImages").getValue() <= 0
55 ? imageProviderInfo.numberImages
56 : getProperty<int>("NumberOfImages").getValue();
57 ARMARX_INFO << defaultProvider << " " << imageProviderInfo.imageFormat.dimension.width
58 << "x" << imageProviderInfo.imageFormat.dimension.height;
59
60 cameraImages[defaultProvider].resize(imageProviderInfo.numberImages);
61 for (int i = 0; i < imageProviderInfo.numberImages; i++)
62 {
63 cameraImages[defaultProvider].at(i).reset(
64 visionx::tools::createByteImage(imageProviderInfo));
65 }
66
67
68 visionx::ImageDimension targetDimension =
69 getProperty<visionx::ImageDimension>("TargetDimension").getValue();
70 visionx::ImageFormatInfo info;
71 info.bytesPerPixel = 3;
72 info.dimension = targetDimension;
73 info.type = imageDisplayType;
74 for (int i = 0; i < numImages; ++i)
75 {
76 resultCameraImages.push_back(
78 }
79
80 if (numImages == 2)
81 {
82 enableStereoResultImages(targetDimension, imageDisplayType);
83 }
84 else
85 {
86 enableResultImages(numImages,
87 targetDimension,
88 imageDisplayType,
89 getProperty<std::string>("resultProviderName"));
90 }
91
92 setImageSource(defaultProvider);
93 }
94
95 void
97 {
98 // for (int i = 0; i < numImages; i++)
99 // {
100 // delete cameraImages[i];
101 // }
102
103 // delete [] cameraImages;
104
105 // if (scaleFactorX > 0.0)
106 // {
107 // for (int i = 0; i < numImages; i++)
108 // {
109 // delete scaledCameraImages[i];
110 // }
111 // }
112 // delete [] scaledCameraImages;
113 }
114
115 void
116 ImageSourceSelection::deleteTimedOutProviders()
117 {
118 std::unique_lock lock(imageSourceMutex);
119
120 std::map<std::string, int> deletionMap;
121 for (auto it = providerTimeouts.begin(); it != providerTimeouts.end(); it++)
122 {
123 deletionMap[it->first] = 0;
124 }
125 // delete providers that are timed out
126 for (auto it = providerTimeouts.begin(); it != providerTimeouts.end(); it++)
127 {
128 if (TimeUtil::GetTime() > it->second)
129 {
130
131 if (it->first != defaultProvider)
132 {
133 deletionMap[it->first]++;
134 }
135 it = providerTimeouts.erase(it);
136 }
137 else
138 {
139 deletionMap[it->first]--;
140 }
141 }
142 for (auto& pair : deletionMap)
143 {
144 if (pair.second > 0)
145 {
146 ARMARX_INFO << "Deleting image source " << pair.first;
147 std::unique_lock lock(mutex);
148 releaseImageProvider(pair.first);
149 }
150 }
151 }
152
153 void
155 {
156
157 deleteTimedOutProviders();
158
159 auto activeProvider = getCurrentImageSource();
160 std::unique_lock lock(mutex);
161 if (!usedImageProviders.count(activeProvider))
162 {
163 setImageSource(activeProvider);
164 }
165 if (!waitForImages(activeProvider))
166 {
167 ARMARX_INFO << deactivateSpam(30, activeProvider)
168 << "Timeout while waiting for images from " << activeProvider;
169 return;
170 }
171 armarx::MetaInfoSizeBasePtr info;
172 ARMARX_DEBUG << deactivateSpam(5, activeProvider) << "Getting image from " << activeProvider
173 << " width: " << cameraImages.at(activeProvider).at(0)->width;
174 if (getImages(activeProvider, cameraImages.at(activeProvider), info) <
175 imageProviderInfoMap.at(activeProvider).numberImages)
176 {
177 ARMARX_WARNING << "Unable to transfer or read images";
178 return;
179 }
180
181 auto currentNumberOfImages =
182 std::min(numImages, imageProviderInfoMap.at(activeProvider).numberImages);
183 ARMARX_DEBUG << deactivateSpam(5, activeProvider) << VAROUT(currentNumberOfImages);
184
185 visionx::ImageDimension targetDimension =
186 getProperty<visionx::ImageDimension>("TargetDimension").getValue();
187 auto providerDimension = imageProviderInfoMap.at(activeProvider).imageFormat.dimension;
188 if (targetDimension != providerDimension &&
189 imageProviderInfo.imageFormat.type != imageDisplayType)
190 {
191 info->capacity = info->size = numImages * resultCameraImages[0]->bytesPerPixel *
192 resultCameraImages[0]->width *
193 resultCameraImages[0]->height;
194 ARMARX_DEBUG << deactivateSpam(30, activeProvider) << "Resizing and converting"
195 << activeProvider;
196 for (int i = 0; i < currentNumberOfImages; i++)
197 {
198 auto otherTypeResizedImage = visionx::CByteImageUPtr(
200 ::ImageProcessor::Resize(cameraImages.at(activeProvider).at(i).get(),
201 otherTypeResizedImage.get());
202 ::ImageProcessor::ConvertImage(otherTypeResizedImage.get(),
203 resultCameraImages.at(i).get());
204 }
205 }
206 else if (targetDimension != providerDimension)
207 {
208 info->capacity = info->size = numImages * resultCameraImages[0]->bytesPerPixel *
209 resultCameraImages[0]->width *
210 resultCameraImages[0]->height;
211 for (int i = 0; i < currentNumberOfImages; i++)
212 {
213 ::ImageProcessor::Resize(cameraImages.at(activeProvider).at(i).get(),
214 resultCameraImages.at(i).get());
215 }
216 provideResultImages(resultCameraImages, info);
217 }
218 else
219 {
220 ARMARX_DEBUG << deactivateSpam(5, activeProvider) << "No resizing";
221 // convert greyscale to rgb
222 if (imageProviderInfo.imageFormat.type != imageDisplayType)
223 {
224 for (int i = 0; i < currentNumberOfImages; i++)
225 {
226 ::ImageProcessor::ConvertImage(cameraImages.at(activeProvider).at(i).get(),
227 resultCameraImages.at(i).get());
228 }
229 provideResultImages(resultCameraImages, info);
230 }
231 else
232 {
233 ARMARX_DEBUG << deactivateSpam(5, activeProvider) << "Same image type";
234 // copy since number of images might be different
235 for (int i = 0; i < currentNumberOfImages; i++)
236 {
237 ::ImageProcessor::CopyImage(cameraImages.at(activeProvider).at(i).get(),
238 resultCameraImages.at(i).get());
239 }
240 provideResultImages(resultCameraImages, info);
241 }
242 }
243 }
244
245 void
246 ImageSourceSelection::setImageSource(const std::string& imageSource,
247 int relativeTimeoutMs,
248 const Ice::Current& c)
249 {
250 ARMARX_CHECK_EXPRESSION(!imageSource.empty());
251 ARMARX_CHECK_GREATER(relativeTimeoutMs, 0);
252 std::unique_lock lock(imageSourceMutex);
253
254 auto newTimeout = TimeUtil::GetTime() + IceUtil::Time::milliSeconds(relativeTimeoutMs);
255
256
257 if (!providerTimeouts.empty() && providerTimeouts.front().first == imageSource)
258 {
259 ARMARX_VERBOSE << "Refreshing timeout: " << newTimeout.toDateTime();
260 providerTimeouts.front().second = newTimeout;
261 }
262 else
263 {
264 ARMARX_VERBOSE << "inserting new imageprovider " << imageSource
265 << " at front with timeout " << newTimeout.toDateTime();
266 providerTimeouts.insert(providerTimeouts.begin(),
267 std::make_pair(imageSource, newTimeout));
268 }
269 // setImageSource(imageSource);
270 }
271
272 void
273 ImageSourceSelection::setImageSource(const std::string& imageSource)
274 {
275 std::unique_lock lock(mutex);
276 if (!usedImageProviders.count(imageSource))
277 {
278 addImageProvider(imageSource);
279 }
280 auto activeProvider = getCurrentImageSource();
281 if (imageSource != activeProvider)
282 {
283 ARMARX_INFO << "getting calibration for image provider " << imageSource;
284 visionx::StereoCalibrationInterfacePrx calibrationProvider =
285 visionx::StereoCalibrationInterfacePrx::checkedCast(
286 imageProviderInfoMap[imageSource].proxy);
287
288 // activeProvider = imageSource.empty() ? defaultProvider : imageSource;
289
290 if (calibrationProvider)
291 {
292
293 visionx::StereoCalibration stereoCalibration =
294 calibrationProvider->getStereoCalibration();
295
296
297 if (scaleFactorX)
298 {
299
300 stereoCalibration.calibrationLeft.cameraParam.focalLength[0] /= scaleFactorX;
301 stereoCalibration.calibrationLeft.cameraParam.focalLength[1] /= scaleFactorX;
302
303 stereoCalibration.calibrationLeft.cameraParam.principalPoint[0] /= scaleFactorX;
304 stereoCalibration.calibrationLeft.cameraParam.principalPoint[1] /= scaleFactorX;
305
306 stereoCalibration.calibrationLeft.cameraParam.width /= scaleFactorX;
307 stereoCalibration.calibrationLeft.cameraParam.height /= scaleFactorX;
308
309 stereoCalibration.calibrationRight.cameraParam.focalLength[0] /= scaleFactorX;
310 stereoCalibration.calibrationRight.cameraParam.focalLength[1] /= scaleFactorX;
311
312
313 stereoCalibration.calibrationRight.cameraParam.principalPoint[0] /=
314 scaleFactorX;
315 stereoCalibration.calibrationRight.cameraParam.principalPoint[1] /=
316 scaleFactorX;
317
318
319 stereoCalibration.calibrationRight.cameraParam.width =
320 ((float)stereoCalibration.calibrationRight.cameraParam.width) /
321 scaleFactorX;
322 stereoCalibration.calibrationRight.cameraParam.height =
323 ((float)stereoCalibration.calibrationRight.cameraParam.height) /
324 scaleFactorX;
325 }
326
327
328 StereoResultImageProviderPtr stereoResultImageProvider =
329 StereoResultImageProviderPtr::dynamicCast(resultImageProvider);
330 if (stereoResultImageProvider)
331 {
332 stereoResultImageProvider->setStereoCalibration(
333 stereoCalibration,
334 calibrationProvider->getImagesAreUndistorted(),
335 calibrationProvider->getReferenceFrame());
336 }
337 }
338 }
339 }
340
341 void
342 ImageSourceSelection::removeImageSource(const std::string& imageSource)
343 {
344 for (auto it = providerTimeouts.begin(); it != providerTimeouts.end(); it++)
345 {
346 if (it->first == imageSource)
347 {
348 providerTimeouts.erase(it);
349 break;
350 }
351 }
352 }
353
354 void
355 ImageSourceSelection::enableStereoResultImages(visionx::ImageDimension imageDimension,
356 visionx::ImageType imageType)
357 {
359 {
360 ARMARX_INFO << "Enabling StereoResultImageProvider";
361
362 StereoResultImageProviderPtr stereoResultImageProvider =
364 stereoResultImageProvider->setName(getProperty<std::string>("resultProviderName"));
366 stereoResultImageProvider);
367
369
370 resultImageProvider->setNumberResultImages(2);
371 resultImageProvider->setResultImageFormat(imageDimension, imageType);
372
373 // wait for resultImageProvider
374 resultImageProvider->getObjectScheduler()->waitForObjectState(eManagedIceObjectStarted);
375 }
376 }
377
384
385 bool
386 ImageSourceSelection::addImageProvider(const std::string& providerName,
387 visionx::ImageType imageDisplayType,
388 visionx::ImageProviderInfo& imageProviderInfo)
389 {
390 bool result = true;
391
392 visionx::ImageProviderInfo otherImageProviderInfo =
393 getImageProvider(providerName, imageDisplayType);
394 ARMARX_INFO << providerName << " " << otherImageProviderInfo.imageFormat.dimension.width
395 << "x" << otherImageProviderInfo.imageFormat.dimension.height;
396 cameraImages[providerName].resize(otherImageProviderInfo.numberImages);
397 for (int i = 0; i < otherImageProviderInfo.numberImages; i++)
398 {
399 cameraImages[providerName].at(i).reset(
400 visionx::tools::createByteImage(otherImageProviderInfo));
401 }
402 visionx::StereoCalibrationInterfacePrx calibrationProvider =
403 visionx::StereoCalibrationInterfacePrx::checkedCast(imageProviderInfo.proxy);
404 if (!calibrationProvider)
405 {
406 ARMARX_WARNING << "image provider does not have a stereo calibration interface";
407 }
408
409
410 if (!result)
411 {
412 releaseImageProvider(providerName);
413 }
414 return result;
415 }
417
418} // namespace armarx
#define float
Definition 16_Level.h:22
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define VAROUT(x)
constexpr T c
static TPtr create(Ice::PropertiesPtr properties=Ice::createProperties(), const std::string &configName="", const std::string &configDomain="ArmarX")
Factory method for a component.
Definition Component.h:116
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
Property< PropertyType > getProperty(const std::string &name)
Brief description of class ImageSourceSelection.
bool addImageProvider(const std::string &providerName)
void enableStereoResultImages(visionx::ImageDimension imageDimension, visionx::ImageType imageType)
enable stereo result images
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void removeImageSource(const std::string &imageSource)
std::string getCurrentImageSource(const Ice::Current &c=Ice::emptyCurrent) override
void setImageSource(const std::string &imageSource, int relativeTimeoutMs, const Ice::Current &c) override
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
std::string getName() const
Retrieve name of object.
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition TimeUtil.cpp:42
IceInternal::Handle< ResultImageProvider > resultImageProvider
std::map< std::string, ImageProviderInfo > imageProviderInfoMap
void enableResultImages(int numberImages, ImageDimension imageDimension, ImageType imageType, const std::string &name="")
Enables visualization.
void usingImageProvider(std::string name)
Registers a delayed topic subscription and a delayed provider proxy retrieval which all will be avail...
bool waitForImages(int milliseconds=1000)
Wait for new images.
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
int getImages(CByteImage **ppImages)
Poll images from provider.
void provideResultImages(CByteImage **images, armarx::MetaInfoSizeBasePtr info=nullptr)
sends result images for visualization
void releaseImageProvider(std::string providerName)
ImageProviderMap usedImageProviders
int numberImages
Number of images.
ImageFormatInfo imageFormat
Image format struct that contains all necessary image information.
#define ARMARX_CHECK_GREATER(lhs, rhs)
This macro evaluates whether lhs is greater (>) than rhs and if it turns out to be false it will thro...
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< StereoResultImageProvider > StereoResultImageProviderPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
ImageType typeNameToImageType(const std::string &imageTypeName)
Converts an image type name as string into an ImageType integer.
CByteImage * createByteImage(const ImageFormatInfo &imageFormat, const ImageType imageType)
Creates a ByteImage for the destination type specified in the given imageProviderInfo.
std::unique_ptr< CByteImage > CByteImageUPtr