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
28
31
32#include <Image/ImageProcessor.h>
33
34namespace armarx
35{
36
37 void
39 {
40 defaultProvider = getProperty<std::string>("defaultProviderName").getValue();
41 usingImageProvider(defaultProvider);
42
44 }
45
46 void
48 {
49 imageDisplayType = visionx::tools::typeNameToImageType("rgb");
50
51 imageProviderInfo = getImageProvider(defaultProvider, imageDisplayType);
52 numImages = getProperty<int>("NumberOfImages").getValue() <= 0
53 ? imageProviderInfo.numberImages
54 : getProperty<int>("NumberOfImages").getValue();
55 ARMARX_INFO << defaultProvider << " " << imageProviderInfo.imageFormat.dimension.width
56 << "x" << imageProviderInfo.imageFormat.dimension.height;
57
58 cameraImages[defaultProvider].resize(imageProviderInfo.numberImages);
59 for (int i = 0; i < imageProviderInfo.numberImages; i++)
60 {
61 cameraImages[defaultProvider].at(i).reset(
62 visionx::tools::createByteImage(imageProviderInfo));
63 }
64
65
66 visionx::ImageDimension targetDimension =
67 getProperty<visionx::ImageDimension>("TargetDimension").getValue();
68 visionx::ImageFormatInfo info;
69 info.bytesPerPixel = 3;
70 info.dimension = targetDimension;
71 info.type = imageDisplayType;
72 for (int i = 0; i < numImages; ++i)
73 {
74 resultCameraImages.push_back(
76 }
77
78 if (numImages == 2)
79 {
80 enableStereoResultImages(targetDimension, imageDisplayType);
81 }
82 else
83 {
84 enableResultImages(numImages,
85 targetDimension,
86 imageDisplayType,
87 getProperty<std::string>("resultProviderName"));
88 }
89
90 setImageSource(defaultProvider);
91 }
92
93 void
95 {
96 // for (int i = 0; i < numImages; i++)
97 // {
98 // delete cameraImages[i];
99 // }
100
101 // delete [] cameraImages;
102
103 // if (scaleFactorX > 0.0)
104 // {
105 // for (int i = 0; i < numImages; i++)
106 // {
107 // delete scaledCameraImages[i];
108 // }
109 // }
110 // delete [] scaledCameraImages;
111 }
112
113 void
114 ImageSourceSelection::deleteTimedOutProviders()
115 {
116 std::unique_lock lock(imageSourceMutex);
117
118 std::map<std::string, int> deletionMap;
119 for (auto it = providerTimeouts.begin(); it != providerTimeouts.end(); it++)
120 {
121 deletionMap[it->first] = 0;
122 }
123 // delete providers that are timed out
124 for (auto it = providerTimeouts.begin(); it != providerTimeouts.end(); it++)
125 {
126 if (TimeUtil::GetTime() > it->second)
127 {
128
129 if (it->first != defaultProvider)
130 {
131 deletionMap[it->first]++;
132 }
133 it = providerTimeouts.erase(it);
134 }
135 else
136 {
137 deletionMap[it->first]--;
138 }
139 }
140 for (auto& pair : deletionMap)
141 {
142 if (pair.second > 0)
143 {
144 ARMARX_INFO << "Deleting image source " << pair.first;
145 std::unique_lock lock(mutex);
146 releaseImageProvider(pair.first);
147 }
148 }
149 }
150
151 void
153 {
154
155 deleteTimedOutProviders();
156
157 auto activeProvider = getCurrentImageSource();
158 std::unique_lock lock(mutex);
159 if (!usedImageProviders.count(activeProvider))
160 {
161 setImageSource(activeProvider);
162 }
163 if (!waitForImages(activeProvider))
164 {
165 ARMARX_INFO << deactivateSpam(30, activeProvider)
166 << "Timeout while waiting for images from " << activeProvider;
167 return;
168 }
169 armarx::MetaInfoSizeBasePtr info;
170 ARMARX_DEBUG << deactivateSpam(5, activeProvider) << "Getting image from " << activeProvider
171 << " width: " << cameraImages.at(activeProvider).at(0)->width;
172 if (getImages(activeProvider, cameraImages.at(activeProvider), info) <
173 imageProviderInfoMap.at(activeProvider).numberImages)
174 {
175 ARMARX_WARNING << "Unable to transfer or read images";
176 return;
177 }
178
179 auto currentNumberOfImages =
180 std::min(numImages, imageProviderInfoMap.at(activeProvider).numberImages);
181 ARMARX_DEBUG << deactivateSpam(5, activeProvider) << VAROUT(currentNumberOfImages);
182
183 visionx::ImageDimension targetDimension =
184 getProperty<visionx::ImageDimension>("TargetDimension").getValue();
185 auto providerDimension = imageProviderInfoMap.at(activeProvider).imageFormat.dimension;
186 if (targetDimension != providerDimension &&
187 imageProviderInfo.imageFormat.type != imageDisplayType)
188 {
189 info->capacity = info->size = numImages * resultCameraImages[0]->bytesPerPixel *
190 resultCameraImages[0]->width *
191 resultCameraImages[0]->height;
192 ARMARX_DEBUG << deactivateSpam(30, activeProvider) << "Resizing and converting"
193 << activeProvider;
194 for (int i = 0; i < currentNumberOfImages; i++)
195 {
196 auto otherTypeResizedImage = visionx::CByteImageUPtr(
198 ::ImageProcessor::Resize(cameraImages.at(activeProvider).at(i).get(),
199 otherTypeResizedImage.get());
200 ::ImageProcessor::ConvertImage(otherTypeResizedImage.get(),
201 resultCameraImages.at(i).get());
202 }
203 }
204 else if (targetDimension != providerDimension)
205 {
206 info->capacity = info->size = numImages * resultCameraImages[0]->bytesPerPixel *
207 resultCameraImages[0]->width *
208 resultCameraImages[0]->height;
209 for (int i = 0; i < currentNumberOfImages; i++)
210 {
211 ::ImageProcessor::Resize(cameraImages.at(activeProvider).at(i).get(),
212 resultCameraImages.at(i).get());
213 }
214 provideResultImages(resultCameraImages, info);
215 }
216 else
217 {
218 ARMARX_DEBUG << deactivateSpam(5, activeProvider) << "No resizing";
219 // convert greyscale to rgb
220 if (imageProviderInfo.imageFormat.type != imageDisplayType)
221 {
222 for (int i = 0; i < currentNumberOfImages; i++)
223 {
224 ::ImageProcessor::ConvertImage(cameraImages.at(activeProvider).at(i).get(),
225 resultCameraImages.at(i).get());
226 }
227 provideResultImages(resultCameraImages, info);
228 }
229 else
230 {
231 ARMARX_DEBUG << deactivateSpam(5, activeProvider) << "Same image type";
232 // copy since number of images might be different
233 for (int i = 0; i < currentNumberOfImages; i++)
234 {
235 ::ImageProcessor::CopyImage(cameraImages.at(activeProvider).at(i).get(),
236 resultCameraImages.at(i).get());
237 }
238 provideResultImages(resultCameraImages, info);
239 }
240 }
241 }
242
243 void
244 ImageSourceSelection::setImageSource(const std::string& imageSource,
245 int relativeTimeoutMs,
246 const Ice::Current& c)
247 {
248 ARMARX_CHECK_EXPRESSION(!imageSource.empty());
249 ARMARX_CHECK_GREATER(relativeTimeoutMs, 0);
250 std::unique_lock lock(imageSourceMutex);
251
252 auto newTimeout = TimeUtil::GetTime() + IceUtil::Time::milliSeconds(relativeTimeoutMs);
253
254
255 if (!providerTimeouts.empty() && providerTimeouts.front().first == imageSource)
256 {
257 ARMARX_VERBOSE << "Refreshing timeout: " << newTimeout.toDateTime();
258 providerTimeouts.front().second = newTimeout;
259 }
260 else
261 {
262 ARMARX_VERBOSE << "inserting new imageprovider " << imageSource
263 << " at front with timeout " << newTimeout.toDateTime();
264 providerTimeouts.insert(providerTimeouts.begin(),
265 std::make_pair(imageSource, newTimeout));
266 }
267 // setImageSource(imageSource);
268 }
269
270 void
271 ImageSourceSelection::setImageSource(const std::string& imageSource)
272 {
273 std::unique_lock lock(mutex);
274 if (!usedImageProviders.count(imageSource))
275 {
276 addImageProvider(imageSource);
277 }
278 auto activeProvider = getCurrentImageSource();
279 if (imageSource != activeProvider)
280 {
281 ARMARX_INFO << "getting calibration for image provider " << imageSource;
282 visionx::StereoCalibrationInterfacePrx calibrationProvider =
283 visionx::StereoCalibrationInterfacePrx::checkedCast(
284 imageProviderInfoMap[imageSource].proxy);
285
286 // activeProvider = imageSource.empty() ? defaultProvider : imageSource;
287
288 if (calibrationProvider)
289 {
290
291 visionx::StereoCalibration stereoCalibration =
292 calibrationProvider->getStereoCalibration();
293
294
295 if (scaleFactorX)
296 {
297
298 stereoCalibration.calibrationLeft.cameraParam.focalLength[0] /= scaleFactorX;
299 stereoCalibration.calibrationLeft.cameraParam.focalLength[1] /= scaleFactorX;
300
301 stereoCalibration.calibrationLeft.cameraParam.principalPoint[0] /= scaleFactorX;
302 stereoCalibration.calibrationLeft.cameraParam.principalPoint[1] /= scaleFactorX;
303
304 stereoCalibration.calibrationLeft.cameraParam.width /= scaleFactorX;
305 stereoCalibration.calibrationLeft.cameraParam.height /= scaleFactorX;
306
307 stereoCalibration.calibrationRight.cameraParam.focalLength[0] /= scaleFactorX;
308 stereoCalibration.calibrationRight.cameraParam.focalLength[1] /= scaleFactorX;
309
310
311 stereoCalibration.calibrationRight.cameraParam.principalPoint[0] /=
312 scaleFactorX;
313 stereoCalibration.calibrationRight.cameraParam.principalPoint[1] /=
314 scaleFactorX;
315
316
317 stereoCalibration.calibrationRight.cameraParam.width =
318 ((float)stereoCalibration.calibrationRight.cameraParam.width) /
319 scaleFactorX;
320 stereoCalibration.calibrationRight.cameraParam.height =
321 ((float)stereoCalibration.calibrationRight.cameraParam.height) /
322 scaleFactorX;
323 }
324
325
326 StereoResultImageProviderPtr stereoResultImageProvider =
327 StereoResultImageProviderPtr::dynamicCast(resultImageProvider);
328 if (stereoResultImageProvider)
329 {
330 stereoResultImageProvider->setStereoCalibration(
331 stereoCalibration,
332 calibrationProvider->getImagesAreUndistorted(),
333 calibrationProvider->getReferenceFrame());
334 }
335 }
336 }
337 }
338
339 void
340 ImageSourceSelection::removeImageSource(const std::string& imageSource)
341 {
342 for (auto it = providerTimeouts.begin(); it != providerTimeouts.end(); it++)
343 {
344 if (it->first == imageSource)
345 {
346 providerTimeouts.erase(it);
347 break;
348 }
349 }
350 }
351
352 void
353 ImageSourceSelection::enableStereoResultImages(visionx::ImageDimension imageDimension,
354 visionx::ImageType imageType)
355 {
357 {
358 ARMARX_INFO << "Enabling StereoResultImageProvider";
359
360 StereoResultImageProviderPtr stereoResultImageProvider =
362 stereoResultImageProvider->setName(getProperty<std::string>("resultProviderName"));
364 stereoResultImageProvider);
365
367
368 resultImageProvider->setNumberResultImages(2);
369 resultImageProvider->setResultImageFormat(imageDimension, imageType);
370
371 // wait for resultImageProvider
372 resultImageProvider->getObjectScheduler()->waitForObjectState(eManagedIceObjectStarted);
373 }
374 }
375
382
383 bool
384 ImageSourceSelection::addImageProvider(const std::string& providerName,
385 visionx::ImageType imageDisplayType,
386 visionx::ImageProviderInfo& imageProviderInfo)
387 {
388 bool result = true;
389
390 visionx::ImageProviderInfo otherImageProviderInfo =
391 getImageProvider(providerName, imageDisplayType);
392 ARMARX_INFO << providerName << " " << otherImageProviderInfo.imageFormat.dimension.width
393 << "x" << otherImageProviderInfo.imageFormat.dimension.height;
394 cameraImages[providerName].resize(otherImageProviderInfo.numberImages);
395 for (int i = 0; i < otherImageProviderInfo.numberImages; i++)
396 {
397 cameraImages[providerName].at(i).reset(
398 visionx::tools::createByteImage(otherImageProviderInfo));
399 }
400 visionx::StereoCalibrationInterfacePrx calibrationProvider =
401 visionx::StereoCalibrationInterfacePrx::checkedCast(imageProviderInfo.proxy);
402 if (!calibrationProvider)
403 {
404 ARMARX_WARNING << "image provider does not have a stereo calibration interface";
405 }
406
407
408 if (!result)
409 {
410 releaseImageProvider(providerName);
411 }
412 return result;
413 }
414} // namespace armarx
#define float
Definition 16_Level.h:22
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)
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