MaskRobotInImage.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2018, 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
19 * @author Julian Zimmer ( urdbu at student dot kit dot edu )
20 * @date 2018
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25#include "MaskRobotInImage.h"
26
27#include <inttypes.h>
28
29#include <VirtualRobot/CollisionDetection/CollisionModel.h>
30
32
34
35#include <Inventor/SoOffscreenRenderer.h>
36
37
38using namespace armarx;
39
41 std::string cameraFrameName,
42 visionx::ImageFormatInfo imageFormat,
43 float fov,
44 SbColor backgroundColor,
45 bool flipImages,
46 bool useFullModel,
47 float collisionModelInflationMargin)
48{
49 VirtualRobot::init("MaskRobotInImage");
50 // needed for SoSelection
51 SoInteraction::init();
52
53 this->cameraFrameName = cameraFrameName;
54 this->fov = fov;
55 this->imageWidth = imageFormat.dimension.width;
56 this->imageHeight = imageFormat.dimension.height;
57 this->backgroundColor = backgroundColor;
58 this->flipImages = flipImages;
59 this->useFullModel = useFullModel;
60 this->collisionModelInflationMargin = collisionModelInflationMargin;
61
62
63 renderedImage = new CByteImage(imageWidth, imageHeight, CByteImage::eRGB24);
64 maskImage = new CByteImage(imageWidth, imageHeight, CByteImage::eGrayScale);
65
66 //get the local robot
67 ARMARX_CHECK_EXPRESSION(robotStateComponent);
68
69 this->robotStateComponent = robotStateComponent;
70
72 robotStateComponent, VirtualRobot::RobotIO::RobotDescription::eFull);
73
74
75 //create the offscreen renderer
76 renderer.reset(
77 VirtualRobot::CoinVisualizationFactory::createOffscreenRenderer(imageWidth, imageHeight));
78 renderBuffer.resize(imageWidth * imageHeight * 3);
79
80
81 renderer->setBackgroundColor(backgroundColor);
82
83
84 if (!useFullModel)
85 {
86 if (collisionModelInflationMargin > 0.f)
87 {
88 //inflate the collision model
89 for (auto& model : localRobot->getCollisionModels())
90 {
91 model->setUpdateVisualization(true);
92 model->inflateModel(collisionModelInflationMargin);
93 ARMARX_INFO << "MARGIN AFTER INITIALIZATION: " << model->getMargin();
94 }
95 }
96 }
97 else
98 {
99 if (collisionModelInflationMargin > 0.f)
100 {
101 ARMARX_IMPORTANT << "Inflating collisionModel but not rendering collisionModel!";
102 }
103 }
104
105
106 //ARMARX_INFO << "HASTIMESERVER: " << TimeUtil::HasTimeServer();
107
108
109 ARMARX_INFO << "RENDERER BACKGROUND COLOR IS: " << renderer->getBackgroundColor().getValue()[0]
110 << ";" << renderer->getBackgroundColor().getValue()[1] << ";"
111 << renderer->getBackgroundColor().getValue()[2] << "]";
112}
113
117
118CByteImage*
120{
121 ARMARX_CHECK_EXPRESSION(robotStateComponent);
122 //synchronize the localRobot
123 RemoteRobot::synchronizeLocalCloneToTimestamp(localRobot, robotStateComponent, timestamp);
124 ARMARX_CHECK_EXPRESSION(localRobot);
125 //get the cameraNode
126 VirtualRobot::RobotNodePtr cameraNode = localRobot->getRobotNode(cameraFrameName);
127 ARMARX_CHECK_EXPRESSION(cameraNode);
128
129
130 //get the visualization
131 VirtualRobot::SceneObject::VisualizationType visuType = VirtualRobot::SceneObject::Collision;
132
133 if (useFullModel)
134 {
135 visuType = VirtualRobot::SceneObject::Full;
136 }
137
138
139 VirtualRobot::CoinVisualizationPtr visualization = localRobot->getVisualization(visuType);
140 ARMARX_CHECK_EXPRESSION(visualization);
141
142
143 SoNode* visualisationNode = NULL;
144 ARMARX_CHECK_EXPRESSION(visualization);
145
146 visualisationNode = visualization->getCoinVisualization();
147
148 ARMARX_CHECK_EXPRESSION(renderer);
149
150
151 //feed it into the renderer
152 bool renderOK = false;
153
154 auto bufferPtr = renderBuffer.data();
155
156
157 //increasing the zNear drawing distance, because the DepthCameraSim camera node is inside the depth camera model
158 renderOK = VirtualRobot::CoinVisualizationFactory::renderOffscreen(
159 renderer.get(), cameraNode, visualisationNode, &bufferPtr, 20.0f, 100000.0f, fov);
160
161 //Depending on the pose of the camera node, the image should be flipped upside down
162 //If the nodes like EyeLeftCameraSim or DepthCameraSim are used, this has to be performed,
163 //since the orientation of these nodes is flipped in comparison to the orientation expected by the offscreen renderer
164
165 //copy rendering into image and create the image mask
166 unsigned char* pRenderedImage = renderer->getBuffer();
167 if (renderOK)
168 {
169 std::uint8_t* pixelsRow = renderedImage->pixels;
170 std::uint8_t* maskPixelsRow = maskImage->pixels;
171 for (int y = 0; y < imageHeight; y++)
172 {
173 for (int x = 0; x < imageWidth; x++)
174 {
175 int adjustedX = x;
176 int adjustedY = y;
177 if (flipImages)
178 {
179 adjustedX = imageWidth - 1 - x;
180 adjustedY = imageHeight - 1 - y;
181 }
182
183
184 pixelsRow[x * 3 + 0] =
185 pRenderedImage[3 * (imageWidth * (imageHeight - adjustedY) + adjustedX) + 0];
186 pixelsRow[x * 3 + 1] =
187 pRenderedImage[3 * (imageWidth * (imageHeight - adjustedY) + adjustedX) + 1];
188 pixelsRow[x * 3 + 2] =
189 pRenderedImage[3 * (imageWidth * (imageHeight - adjustedY) + adjustedX) + 2];
190
191 //set the masking pixel to 255 if the background color is in the image pixel, else set it to 0
192 SbColor pixelColor(((float)pixelsRow[x * 3 + 0]) / 255.f,
193 ((float)pixelsRow[x * 3 + 1]) / 255.f,
194 ((float)pixelsRow[x * 3 + 2]) / 255.f);
195 if (backgroundColor.equals(pixelColor, 0.004f))
196 {
197 maskPixelsRow[x] = 0;
198 }
199 else
200 {
201 maskPixelsRow[x] = 255;
202 }
203 }
204 pixelsRow += imageWidth * 3;
205 maskPixelsRow += imageWidth;
206 }
207 }
208
209
210 return maskImage;
211}
212
213void
214MaskRobotInImage::setBackgroundColor(SbColor newBackgroundColor)
215{
216 backgroundColor = newBackgroundColor;
217 renderer->setBackgroundColor(newBackgroundColor);
218}
std::string timestamp()
CByteImage * getMaskImage(Ice::Long timestamp)
MaskRobotInImage(RobotStateComponentInterfacePrx robotStateComponent, std::string cameraFrameName, visionx::ImageFormatInfo imageFormat, float fov, SbColor backgroundColor=SbColor(0.f,(177.f/255.f),(64.f/255.f)), bool flipImages=true, bool useFullModel=true, float collisionModelInflationMargin=0.f)
MaskRobotInImage Constructor.
void setBackgroundColor(SbColor newBackgroundColor)
~MaskRobotInImage()
MaskRobotInImage Destructor.
static VirtualRobot::RobotPtr createLocalCloneFromFile(RobotStateComponentInterfacePrx robotStatePrx, VirtualRobot::RobotIO::RobotDescription loadMode=VirtualRobot::RobotIO::eFull)
This is a convenience function for createLocalClone, which automatically gets the filename from the R...
static bool synchronizeLocalCloneToTimestamp(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx, Ice::Long timestamp)
Synchronizes a local robot to a robot state at timestamp.
#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_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface > RobotStateComponentInterfacePrx