ImageMaskPainterWidgetController.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::gui-plugins::ImageMaskPainterWidgetController
17  * \author Raphael Grimm ( raphael dot grimm at kit dot edu )
18  * \date 2018
19  * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
24 
25 #include <string>
26 
27 #include <QImage>
28 
30 
32 
33 using namespace armarx;
34 
36 {
37  _widget.setupUi(getWidget());
38 
39  _maskEditor = new ImageMaskEditor;
40  _widget.horizontalLayoutImageMonitors->addWidget(_maskEditor);
41 
42  _maskEditor->setPenCircleVisible(true);
43  QImage bg(512, 512, QImage::Format_ARGB32);
44  bg.fill(Qt::red);
45  _maskEditor->setBackgroundImage(bg);
46  _maskEditor->setPenWidth(_widget.spinBoxPenWidth->value());
47  _maskEditor->setMaskAlpha(_widget.spinBoxPenAlpha->value());
48 
49  updatePenColor();
50 
51  connect(_maskEditor, SIGNAL(maskUpdateFinished()), this, SLOT(maskUpdated()));
52  connect(_maskEditor,
53  SIGNAL(arrowDrawn(const QPoint&, const QPoint&)),
54  this,
55  SLOT(arrowDrawn(const QPoint&, const QPoint&)));
56 
57  connect(
58  _widget.spinBoxPenWidth, SIGNAL(valueChanged(int)), _maskEditor, SLOT(setPenWidth(int)));
59  connect(
60  _widget.spinBoxPenAlpha, SIGNAL(valueChanged(int)), _maskEditor, SLOT(setMaskAlpha(int)));
61  connect(_widget.pushButtonClear, SIGNAL(clicked()), _maskEditor, SLOT(clearMaskImage()));
62 
63  connect(
64  _widget.spinBoxImageIndex, SIGNAL(valueChanged(int)), this, SLOT(imageIndexChanged(int)));
65  connect(_widget.checkBoxErase, SIGNAL(clicked()), this, SLOT(updatePenColor()));
66 
67  startTimer(1);
68 }
69 
71 
72 QPointer<QDialog>
74 {
75  if (!_dialog)
76  {
77  _dialog = new SimpleConfigDialog(parent);
78  _dialog->addProxyFinder<visionx::ImageProviderInterfacePrx>(
79  {"ImageProvider", "ImageProvider", "Image*|*Provider"});
80  }
81  return qobject_cast<SimpleConfigDialog*>(_dialog);
82 }
83 
84 void
86 {
87  usingImageProvider(_imageProviderName);
88 }
89 
90 void
92 {
93  _imageProviderName = _dialog->getProxyName("ImageProvider");
94 }
95 
96 void
98 {
99  _imageProviderName =
100  settings->value("_imageProviderName", "OpenNIPointCloudProvider").toString().toStdString();
101 }
102 
103 void
105 {
106  settings->setValue("_imageProviderName", QString::fromStdString(_imageProviderName));
107 }
108 
109 void
111 {
112  if (!_providerImagesOwner.empty())
113  {
114  return;
115  }
116  _imageProviderInfo = getImageProvider(_imageProviderName, true);
117  _imageProvider = _imageProviderInfo.proxy;
118  ARMARX_CHECK_GREATER(_imageProviderInfo.numberImages, 0);
119  ARMARX_CHECK_EQUAL(_imageProviderInfo.imageFormat.type, visionx::ImageType::eRgb);
120  //reserve buffers
121  _providerImagesOwner.reserve(_imageProviderInfo.numberImages);
122  _providerImages.reserve(_imageProviderInfo.numberImages);
123  for (int i = 0; i < _imageProviderInfo.numberImages; ++i)
124  {
125  _providerImagesOwner.emplace_back(visionx::tools::createByteImage(_imageProviderInfo));
126  _providerImages.emplace_back(static_cast<void*>(_providerImagesOwner.back()->pixels));
127  }
128  _numberOfImages = _imageProviderInfo.numberImages;
129  _resultImage.reset(visionx::tools::createByteImage(_imageProviderInfo));
131  _imageProviderInfo.imageFormat.dimension,
132  visionx::ImageType::eRgb,
133  _imageProviderName + "_Mask");
134 
135  {
136  _imageProviderReferenceFrame = "Global";
137  auto frameprov = visionx::ReferenceFrameInterfacePrx::checkedCast(_imageProvider);
138  if (frameprov)
139  {
140  _imageProviderReferenceFrame = frameprov->getReferenceFrame();
141  }
142  }
143  {
144  _imageProviderAreImagesUndistorted = true;
145 
146  auto mcalibprov =
147  visionx::MonocularCalibrationCapturingProviderInterfacePrx::checkedCast(_imageProvider);
148  auto scalibprov = visionx::StereoCalibrationInterfacePrx::checkedCast(_imageProvider);
149  if (scalibprov)
150  {
151  _imageProviderCalibration = scalibprov->getStereoCalibration();
152  _imageProviderAreImagesUndistorted = scalibprov->getImagesAreUndistorted();
153  }
154  else if (mcalibprov)
155  {
156  ARMARX_WARNING << "only monoocular upstream calibration! duplicating it and using "
157  "identity matices";
158  auto mono = mcalibprov->getCalibration();
159  _imageProviderCalibration.calibrationLeft = mono;
160  _imageProviderCalibration.calibrationRight = mono;
161  _imageProviderCalibration.rectificationHomographyLeft = {
162  {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
163  _imageProviderCalibration.rectificationHomographyRight = {
164  {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
165 
166  _imageProviderAreImagesUndistorted = true;
167  }
168  else
169  {
170  ARMARX_WARNING << "no upstream calibration! using default values";
171  _imageProviderCalibration.calibrationLeft.cameraParam.distortion = {0, 0};
172  _imageProviderCalibration.calibrationLeft.cameraParam.focalLength = {50, 50};
173  _imageProviderCalibration.calibrationLeft.cameraParam.height =
174  _imageProviderInfo.imageFormat.dimension.height;
175  _imageProviderCalibration.calibrationLeft.cameraParam.width =
176  _imageProviderInfo.imageFormat.dimension.width;
177  _imageProviderCalibration.calibrationLeft.cameraParam.principalPoint = {
178  _imageProviderInfo.imageFormat.dimension.width / 2.f,
179  _imageProviderInfo.imageFormat.dimension.height / 2.f};
180  _imageProviderCalibration.calibrationLeft.cameraParam.rotation = {
181  {1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
182  _imageProviderCalibration.calibrationLeft.cameraParam.translation = {0, 0, 0};
183 
184  _imageProviderCalibration.calibrationRight = _imageProviderCalibration.calibrationLeft;
185  _imageProviderCalibration.rectificationHomographyLeft = {
186  {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
187  _imageProviderCalibration.rectificationHomographyRight = {
188  {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
189  }
190  }
191 }
192 
193 void
195 {
196  if (!waitForImages(_imageProviderName, 1000))
197  {
198  return;
199  }
200  getImages(_providerImages.data());
201  const CByteImage& img = *(_providerImagesOwner.at(_imageIndex));
202  {
203  std::lock_guard<std::mutex> guard{_currentImageMutex};
204  _currentImage = QImage(img.width, img.height, QImage::Format_RGB888);
205  ARMARX_CHECK_NOT_NULL(_currentImage.bits());
206  ARMARX_CHECK_NOT_NULL(img.pixels);
207  std::memcpy(_currentImage.bits(), img.pixels, 3 * img.width * img.height);
208  _currentImageDirty = true;
209  }
210  ARMARX_INFO << deactivateSpam() << "received image";
211 }
212 
213 void
215 {
216  _widget.spinBoxImageIndex->setMaximum(std::max(1, _numberOfImages.load()) - 1);
217  if (!_currentImageDirty)
218  {
219  return;
220  }
221  {
222  std::lock_guard<std::mutex> guard{_currentImageMutex};
223  _maskEditor->setBackgroundImage(_currentImage);
224  _currentImageDirty = false;
225  }
226  ARMARX_INFO << deactivateSpam() << "updated displayed image";
227  if (_maskSet)
228  {
229  ARMARX_INFO << deactivateSpam() << "send new mask";
230  auto ptr = _resultImage.get();
231  provideResultImages(&ptr);
232  }
233 }
234 
235 QString
237 {
238  return "VisionX.ImageMaskPainter";
239 }
240 
241 void
242 ImageMaskPainterWidgetController::updatePenColor()
243 {
244  auto color =
245  _widget.checkBoxErase->isChecked() ? _maskEditor->transparentColor() : QColor(0, 0, 255);
246  _maskEditor->setMaskColor(color);
247 }
248 
249 void
250 ImageMaskPainterWidgetController::imageIndexChanged(int i)
251 {
252  _imageIndex = _widget.spinBoxImageIndex->value();
253 }
254 
255 void
256 ImageMaskPainterWidgetController::maskUpdated()
257 {
258  if (!_resultImage)
259  {
260  //oninit did not run
261  return;
262  }
263  QSize sz = _maskEditor->imageSize();
264  if (sz.width() != _resultImage->width || sz.height() != _resultImage->height)
265  {
266  //the initial mask was set. the mask was not resized to the providers size
267  return;
268  }
269 
270  QImage mask = _maskEditor->maskImage();
271  sz = mask.size();
272  ARMARX_CHECK_EQUAL(sz.width(), _resultImage->width);
273  ARMARX_CHECK_EQUAL(sz.height(), _resultImage->height);
274 
275  //the qimage has an alpha channel!
276  for (int x = 0; x < _resultImage->width; ++x)
277  {
278  for (int y = 0; y < _resultImage->height; ++y)
279  {
280  int offset = (x + y * _resultImage->width) * 3;
281  const QColor color{mask.pixel(x, y)};
282  _resultImage->pixels[offset + 0] = color.red();
283  _resultImage->pixels[offset + 1] = color.green();
284  _resultImage->pixels[offset + 2] = color.blue();
285  }
286  }
287  _maskSet = true;
288 }
ImageMaskEditor::imageSize
QSize imageSize() const
Definition: ImageMaskEditor.cpp:118
armarx::ImageMaskPainterWidgetController::onInitImageProcessor
void onInitImageProcessor() override
Setup the vision component.
Definition: ImageMaskPainterWidgetController.cpp:85
armarx::ImageMaskPainterWidgetController::ImageMaskPainterWidgetController
ImageMaskPainterWidgetController()
Controller Constructor.
Definition: ImageMaskPainterWidgetController.cpp:35
visionx::ImageProviderInfo::numberImages
int numberImages
Number of images.
Definition: ImageProcessor.h:519
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::ImageMaskPainterWidgetController::onConnectImageProcessor
void onConnectImageProcessor() override
Implement this method in the ImageProcessor in order execute parts when the component is fully initia...
Definition: ImageMaskPainterWidgetController.cpp:110
armarx::ImageMaskPainterWidgetController::configured
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
Definition: ImageMaskPainterWidgetController.cpp:91
armarx::ImageMaskPainterWidgetController::getConfigDialog
QPointer< QDialog > getConfigDialog(QWidget *parent) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
Definition: ImageMaskPainterWidgetController.cpp:73
visionx::ImageProcessor::getImageProvider
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
Definition: ImageProcessor.cpp:167
ARMARX_CHECK_GREATER
#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...
Definition: ExpressionException.h:116
ImageMaskEditor::setPenWidth
void setPenWidth(int newWidth)
Definition: ImageMaskEditor.cpp:187
ImageMaskEditor::maskImage
QImage maskImage() const
Definition: ImageMaskEditor.cpp:95
ImageMaskEditor::setBackgroundImage
void setBackgroundImage(const QImage &i)
Definition: ImageMaskEditor.cpp:228
visionx::ImageProviderInfo::imageFormat
ImageFormatInfo imageFormat
Image format struct that contains all necessary image information.
Definition: ImageProcessor.h:509
armarx::ImageMaskPainterWidgetController::process
void process() override
Process the vision component.
Definition: ImageMaskPainterWidgetController.cpp:194
visionx::tools::createByteImage
CByteImage * createByteImage(const ImageFormatInfo &imageFormat, const ImageType imageType)
Creates a ByteImage for the destination type specified in the given imageProviderInfo.
ImageMaskEditor::transparentColor
const QColor & transparentColor() const
Definition: ImageMaskEditor.cpp:77
visionx::ImageProcessor::usingImageProvider
void usingImageProvider(std::string name)
Registers a delayed topic subscription and a delayed provider proxy retrieval which all will be avail...
Definition: ImageProcessor.cpp:128
ImageMaskEditor
Definition: ImageMaskEditor.h:8
max
T max(T t1, T t2)
Definition: gdiam.h:51
visionx::ImageProcessor::getImages
int getImages(CByteImage **ppImages)
Poll images from provider.
Definition: ImageProcessor.cpp:395
armarx::red
QColor red()
Definition: StyleSheets.h:78
ExpressionException.h
armarx::ImageMaskPainterWidgetController::GetWidgetName
static QString GetWidgetName()
Returns the Widget name displayed in the ArmarXGui to create an instance of this class.
Definition: ImageMaskPainterWidgetController.cpp:236
armarx::ImageMaskPainterWidgetController::~ImageMaskPainterWidgetController
virtual ~ImageMaskPainterWidgetController()
Controller destructor.
visionx::ImageProviderInfo::proxy
ImageProviderInterfacePrx proxy
proxy to image provider
Definition: ImageProcessor.h:485
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::ImageMaskPainterWidgetController::loadSettings
void loadSettings(QSettings *settings) override
Definition: ImageMaskPainterWidgetController.cpp:97
visionx::ImageProcessor::enableResultImages
void enableResultImages(int numberImages, ImageDimension imageDimension, ImageType imageType, const std::string &name="")
Enables visualization.
Definition: ImageProcessor.cpp:251
armarx::ImageMaskPainterWidgetController::timerEvent
void timerEvent(QTimerEvent *) override
Definition: ImageMaskPainterWidgetController.cpp:214
ImageMaskPainterWidgetController.h
ImageUtil.h
visionx::ImageProcessor::provideResultImages
void provideResultImages(CByteImage **images, armarx::MetaInfoSizeBasePtr info=nullptr)
sends result images for visualization
Definition: ImageProcessor.cpp:274
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:99
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
ImageMaskEditor::setMaskColor
void setMaskColor(const QColor &newColor)
Definition: ImageMaskEditor.cpp:130
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:193
ImageMaskEditor::setPenCircleVisible
void setPenCircleVisible(bool b=true)
Definition: ImageMaskEditor.cpp:381
armarx::ImageMaskPainterWidgetController::saveSettings
void saveSettings(QSettings *settings) override
Definition: ImageMaskPainterWidgetController.cpp:104
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
ImageMaskEditor::setMaskAlpha
void setMaskAlpha(int newAlpha)
Definition: ImageMaskEditor.cpp:193
visionx::ImageProcessor::waitForImages
bool waitForImages(int milliseconds=1000)
Wait for new images.
Definition: ImageProcessor.cpp:309
armarx::SimpleConfigDialog
A config-dialog containing one (or multiple) proxy finders.
Definition: SimpleConfigDialog.h:84