ImageToArMem.cpp
Go to the documentation of this file.
1#include "ImageToArMem.h"
2
3#include <sstream>
4#include <unordered_set>
5
9
13
15#include <VisionX/libraries/armem/vision/camera/core/aron/CameraCalibration.aron.generated.h>
18
19#include <Image/ByteImage.h>
20#include <Image/ImageProcessor.h>
21
23{
24
26 {
27 }
28
29 template <class AronImageT>
30 void
31 ImageToArMem::addImages(const armarx::armem::MemoryID& entityID,
32 const std::vector<size_t>& imageIndices)
33 {
34 auto& images = imagesByEntity[entityID];
35
36 for (size_t i = 0; i < imageIndices.size(); ++i)
37 {
38 armarx::armem::MemoryID instanceID = entityID;
39 instanceID.instanceIndex = static_cast<int>(i);
40
41 size_t index = imageIndices[i];
42 images.emplace_back(std::make_unique<Image<AronImageT>>(instanceID, index));
43 }
44 }
45
46 void
47 ImageToArMem::setWritingMemory(armarx::armem::server::WritingMemoryInterfacePrx memory)
48 {
49 memoryWriter.setWritingMemory(memory);
50 }
51
52 void
57
58 void
60 const std::vector<size_t>& imageIndices)
61 {
62 if (imageIndices.empty())
63 {
64 return;
65 }
66
67 addImages<arondto::ImageRGB>(entityID, imageIndices);
68 for (const auto& image : imagesByEntity.at(entityID))
69 {
70 ARMARX_CHECK_EQUAL(image->getImage().type(), CV_8UC3);
71 }
72 }
73
74 void
76 const std::vector<size_t>& imageIndices)
77 {
78 if (imageIndices.empty())
79 {
80 return;
81 }
82
83 addImages<arondto::ImageDepth>(entityID, imageIndices);
84 for (const auto& image : imagesByEntity.at(entityID))
85 {
86 ARMARX_CHECK_EQUAL(image->getImage().type(), CV_32FC1);
87 }
88 }
89
92 {
93 auto it = imagesByEntity.begin();
94 armarx::armem::MemoryID id = it->first;
95 for (; it != imagesByEntity.end(); ++it)
96 {
97 ARMARX_CHECK_EQUAL(it->first.memoryName, id.memoryName)
98 << "Currently, all images must be from the same memory.";
99
100 ARMARX_CHECK_EQUAL(it->first.providerSegmentName, id.providerSegmentName)
101 << "Currently, all images must be from the same provider.";
102 }
103 return id;
104 }
105
106 armarx::armem::data::AddSegmentsInput
108 {
109 std::unordered_set<armarx::armem::MemoryID> providerIDs;
110 for (const auto& [entityID, image] : imagesByEntity)
111 {
112 providerIDs.insert(entityID.getProviderSegmentID());
113 }
114 armarx::armem::data::AddSegmentsInput inputs;
115 for (const armarx::armem::MemoryID& id : providerIDs)
116 {
117 armarx::armem::data::AddSegmentInput& input = inputs.emplace_back();
118 input.coreSegmentName = id.coreSegmentName;
119 input.providerSegmentName = id.providerSegmentName;
120 input.clearWhenExists = clearWhenExists;
121 }
122 return inputs;
123 }
124
125 armarx::armem::data::AddSegmentsResult
126 ImageToArMem::addProviderSegments(bool clearWhenExists, int verbose)
127 {
128 const armarx::armem::data::AddSegmentsInput inputs = makeAddSegmentsInput(clearWhenExists);
129 const armarx::armem::data::AddSegmentsResult results = memoryWriter.addSegments(inputs);
130 if (verbose >= 1)
131 {
132 for (size_t i = 0; i < results.size(); ++i)
133 {
134 if (!results.at(i).success)
135 {
136 const armarx::armem::data::AddSegmentInput& in = inputs.at(i);
137 ARMARX_ERROR << "Failed to add provider segment '" << in.coreSegmentName << "/"
138 << in.providerSegmentName << "'."
139 << "\n"
140 << results.at(0).errorMessage;
141 }
142 }
143 }
144 return results;
145 }
146
147 void
148 ImageToArMem::useImageBuffers(CByteImage** inputImageBuffer, armarx::armem::Time timeProvided)
149 {
150 for (auto& [entityID, images] : imagesByEntity)
151 {
152 for (std::unique_ptr<ImageBase>& image : images)
153 {
154 image->usePixels(inputImageBuffer);
155 }
156 }
157 this->timestamp = timeProvided;
158 }
159
160 void
161 ImageToArMem::usePixelBuffers(void** inputImageBuffers, armarx::armem::Time timeProvided)
162 {
163 for (auto& [entityID, images] : imagesByEntity)
164 {
165 for (std::unique_ptr<ImageBase>& image : images)
166 {
167 image->usePixels(inputImageBuffers);
168 }
169 }
170 this->timestamp = timeProvided;
171 }
172
175 {
177 for (const auto& [entityID, images] : imagesByEntity)
178 {
179 if (images.size())
180 {
181 armarx::armem::EntityUpdate& update = commit.updates.emplace_back();
182 update.entityID = entityID;
183 update.referencedTime = timestamp;
184 for (const auto& image : images)
185 {
186 update.instancesData.push_back(image->toAron());
187 }
188 }
189 }
190 return commit;
191 }
192
193 void
195 {
197 ARMARX_DEBUG << "Got a new image for processing. Sending images to vision memory.";
198
199 TIMING_START(ToAron);
202
203 TIMING_START(Commit);
204 armarx::armem::CommitResult results = memoryWriter.commit(commit);
206
207 ARMARX_CHECK_EQUAL(results.results.size(), commit.updates.size());
208 {
209 std::stringstream ss;
210 for (size_t i = 0; i < results.results.size(); ++i)
211 {
212 ss << "\n- " << commit.updates.at(i).entityID << ": \n" << results.results.at(i);
213 }
214 ARMARX_DEBUG << "Commit results: " << ss.str();
215 }
216
217 if (debugObserver)
218 {
219 debugObserver->setDebugChannel(
221 {
222 {"ToAron [us]", new armarx::Variant(ToAron.toMicroSecondsDouble())},
223 {"Commit [us]", new armarx::Variant(Commit.toMicroSecondsDouble())},
224 });
225 }
226 }
227
228 void
229 ImageToArMem::commitCameraCalibration(const visionx::StereoCalibration& calib)
230 {
231 visionx::arondto::StereoCameraCalibration aron;
233
235 armarx::armem::EntityUpdate& eu = c.add();
236
237 eu.confidence = 1.0;
238
240 getMemoryID().memoryName,
242 getMemoryID().providerSegmentName,
244
245 eu.instancesData = {aron.toAron()};
246
249 auto result = memoryWriter.commit(c);
250
251 if (not result.allSuccess())
252 {
253 ARMARX_ERROR << "An error occured when sending pointclouds to the memory. "
254 "Try to continue with next PC. The message was: "
255 << result.allErrorMessages();
256 }
257 }
258
259 void
260 ImageToArMem::commitCameraCalibration(const visionx::MonocularCalibration& calib)
261 {
262 visionx::arondto::MonocularCameraCalibration aron;
264
266 armarx::armem::EntityUpdate& eu = c.add();
267
268 eu.confidence = 1.0;
269
271 getMemoryID().memoryName,
273 getMemoryID().providerSegmentName,
275
276 eu.instancesData = {aron.toAron()};
277
280 auto result = memoryWriter.commit(c);
281
282 if (not result.allSuccess())
283 {
284 ARMARX_ERROR << "An error occured when sending pointclouds to the memory. "
285 "Try to continue with next PC. The message was: "
286 << result.allErrorMessages();
287 }
288 }
289
290 std::string
292 {
293 std::stringstream ss;
294 for (const auto& [entityID, images] : imagesByEntity)
295 {
296 ss << "- Entity " << entityID << ": \n";
297 for (const auto& image : images)
298 {
299 ss << "- - [image #" << image->imageIndex << "] id = " << image->instanceID << "\n";
300 }
301 }
302 return ss.str();
303 }
304
305 void
306 ImageToArMem::initImages(int width, int height, CByteImage::ImageType type)
307 {
308 for (auto& [entityID, images] : imagesByEntity)
309 {
310 for (auto& image : images)
311 {
312 image->resetImage(height, width);
313 }
314 }
315 }
316
317 void
318 ImageToArMem::initImages(const ImageFormatInfo& info)
319 {
320 for (auto& [entityID, images] : imagesByEntity)
321 {
322 for (auto& image : images)
323 {
324 image->resetImage(info.dimension.height, info.dimension.width);
325 }
326 }
327 }
328
329 std::vector<CByteImage>
331 {
332 std::vector<CByteImage> buffer;
333 for (auto& [entityID, images] : imagesByEntity)
334 {
335 for (auto& image : images)
336 {
337 if (image->imageIndex >= buffer.size())
338 {
339 buffer.resize(image->imageIndex + 1);
340 }
341 cv::Mat& mat = image->getImage();
342 buffer[image->imageIndex].Set(mat.cols, mat.rows, CByteImage::eRGB24);
343 }
344 }
345 return buffer;
346 }
347
348} // namespace visionx::armem_images
uint8_t index
constexpr T c
The Variant class is described here: Variants.
Definition Variant.h:224
MemoryID getProviderSegmentID() const
Definition MemoryID.cpp:302
Helps a memory client sending data to a memory.
Definition Writer.h:23
static DateTime Now()
Definition DateTime.cpp:51
void useImageBuffers(CByteImage **inputImageBuffer, armarx::armem::Time timeProvided)
Store image data from the given buffer.
void initImages(int width, int height, CByteImage::ImageType type)
std::string summarizeStructure() const override
std::vector< CByteImage > makeCByteImageBuffer()
armarx::armem::Commit makeCommit() const
Build the commit.
armarx::armem::MemoryID getMemoryID() const override
void usePixelBuffers(void **inputImageBuffer, armarx::armem::Time timeProvided)
armarx::armem::client::Writer memoryWriter
void addImagesDepth(const armarx::armem::MemoryID &entityID, const std::vector< size_t > &imageIndices) override
void commitImages()
Commit the stored image data.
void setWritingMemory(armarx::armem::server::WritingMemoryInterfacePrx memory)
armarx::armem::data::AddSegmentsInput makeAddSegmentsInput(bool clearWhenExists=true)
Build inputs for adding the required provider segments.
void addImagesRGB(const armarx::armem::MemoryID &entityID, const std::vector< size_t > &imageIndices) override
void setWriter(const armarx::armem::client::Writer &writer)
armarx::armem::data::AddSegmentsResult addProviderSegments(bool clearWhenExists=true, int verbose=1)
Add the required provider segments.
std::map< armarx::armem::MemoryID, std::vector< std::unique_ptr< ImageBase > > > imagesByEntity
Entity ID to memory images (instances).
void commitCameraCalibration(const visionx::StereoCalibration &)
Calibration.
A class template implementing the interface defined by ImageBase for a specific aron-generated class.
Definition Image.h:88
armarx::DebugObserverInterfacePrx debugObserver
ImageAdapter(const std::string &debugObserverChannelName="ImageAdapter")
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#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...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
#define TIMING_START(name)
Helper macro to do timing tests.
Definition TimeUtil.h:289
#define TIMING_END_STREAM(name, os)
Prints duration.
Definition TimeUtil.h:310
armarx::core::time::DateTime Time
const constexpr char * MONOCULAR_CAMERA_CALIBRATION_CORE_SEGMENT_NAME
Definition constants.h:11
const constexpr char * STEREO_CAMERA_CALIBRATION_CORE_SEGMENT_NAME
Definition constants.h:13
const constexpr char * ENTITY_NAME
Definition constants.h:16
void fromIce(visionx::arondto::CameraParameters &aron, const visionx::CameraParameters &ice)
Result of a Commit.
Definition Commit.h:111
std::vector< EntityUpdateResult > results
Definition Commit.h:112
A bundle of updates to be sent to the memory.
Definition Commit.h:90
std::vector< EntityUpdate > updates
The entity updates.
Definition Commit.h:97
An update of an entity for a specific point in time.
Definition Commit.h:26
float confidence
An optional confidence, may be used for things like decay.
Definition Commit.h:43
MemoryID entityID
The entity's ID.
Definition Commit.h:28
Time referencedTime
Time when this entity update was created (e.g.
Definition Commit.h:37
std::vector< aron::data::DictPtr > instancesData
The entity data.
Definition Commit.h:31
Time sentTime
Time when this update was sent to the memory server.
Definition Commit.h:53