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 
23 #include <string>
24 
25 #include <QImage>
26 
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, SIGNAL(arrowDrawn(const QPoint&, const QPoint&)), this, SLOT(arrowDrawn(const QPoint&, const QPoint&)));
53 
54  connect(_widget.spinBoxPenWidth, SIGNAL(valueChanged(int)), _maskEditor, SLOT(setPenWidth(int)));
55  connect(_widget.spinBoxPenAlpha, SIGNAL(valueChanged(int)), _maskEditor, SLOT(setMaskAlpha(int)));
56  connect(_widget.pushButtonClear, SIGNAL(clicked()), _maskEditor, SLOT(clearMaskImage()));
57 
58  connect(_widget.spinBoxImageIndex, SIGNAL(valueChanged(int)), this, SLOT(imageIndexChanged(int)));
59  connect(_widget.checkBoxErase, SIGNAL(clicked()), this, SLOT(updatePenColor()));
60 
61  startTimer(1);
62 }
63 
65  = default;
66 
67 QPointer<QDialog> ImageMaskPainterWidgetController::getConfigDialog(QWidget* parent)
68 {
69  if (!_dialog)
70  {
71  _dialog = new SimpleConfigDialog(parent);
72  _dialog->addProxyFinder<visionx::ImageProviderInterfacePrx>({"ImageProvider", "ImageProvider", "Image*|*Provider"});
73  }
74  return qobject_cast<SimpleConfigDialog*>(_dialog);
75 }
76 
78 {
79  usingImageProvider(_imageProviderName);
80 }
81 
83 {
84  _imageProviderName = _dialog->getProxyName("ImageProvider");
85 }
86 
88 {
89  _imageProviderName = settings->value("_imageProviderName", "OpenNIPointCloudProvider").toString().toStdString();
90 }
91 
93 {
94  settings->setValue("_imageProviderName", QString::fromStdString(_imageProviderName));
95 }
96 
98 {
99  if (!_providerImagesOwner.empty())
100  {
101  return;
102  }
103  _imageProviderInfo = getImageProvider(_imageProviderName, true);
104  _imageProvider = _imageProviderInfo.proxy;
105  ARMARX_CHECK_GREATER(_imageProviderInfo.numberImages, 0);
106  ARMARX_CHECK_EQUAL(_imageProviderInfo.imageFormat.type, visionx::ImageType::eRgb);
107  //reserve buffers
108  _providerImagesOwner.reserve(_imageProviderInfo.numberImages);
109  _providerImages.reserve(_imageProviderInfo.numberImages);
110  for (int i = 0; i < _imageProviderInfo.numberImages; ++i)
111  {
112  _providerImagesOwner.emplace_back(visionx::tools::createByteImage(_imageProviderInfo));
113  _providerImages.emplace_back(static_cast<void*>(_providerImagesOwner.back()->pixels));
114  }
115  _numberOfImages = _imageProviderInfo.numberImages;
116  _resultImage.reset(visionx::tools::createByteImage(_imageProviderInfo));
117  enableResultImages(1, _imageProviderInfo.imageFormat.dimension, visionx::ImageType::eRgb, _imageProviderName + "_Mask");
118 
119  {
120  _imageProviderReferenceFrame = "Global";
121  auto frameprov = visionx::ReferenceFrameInterfacePrx::checkedCast(_imageProvider);
122  if (frameprov)
123  {
124  _imageProviderReferenceFrame = frameprov->getReferenceFrame();
125  }
126  }
127  {
128  _imageProviderAreImagesUndistorted = true;
129 
130  auto mcalibprov = visionx::MonocularCalibrationCapturingProviderInterfacePrx::checkedCast(_imageProvider);
131  auto scalibprov = visionx::StereoCalibrationInterfacePrx::checkedCast(_imageProvider);
132  if (scalibprov)
133  {
134  _imageProviderCalibration = scalibprov->getStereoCalibration();
135  _imageProviderAreImagesUndistorted = scalibprov->getImagesAreUndistorted();
136  }
137  else if (mcalibprov)
138  {
139  ARMARX_WARNING << "only monoocular upstream calibration! duplicating it and using identity matices";
140  auto mono = mcalibprov->getCalibration();
141  _imageProviderCalibration.calibrationLeft = mono;
142  _imageProviderCalibration.calibrationRight = mono;
143  _imageProviderCalibration.rectificationHomographyLeft = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
144  _imageProviderCalibration.rectificationHomographyRight = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
145 
146  _imageProviderAreImagesUndistorted = true;
147  }
148  else
149  {
150  ARMARX_WARNING << "no upstream calibration! using default values";
151  _imageProviderCalibration.calibrationLeft.cameraParam.distortion = {0, 0};
152  _imageProviderCalibration.calibrationLeft.cameraParam.focalLength = {50, 50};
153  _imageProviderCalibration.calibrationLeft.cameraParam.height = _imageProviderInfo.imageFormat.dimension.height;
154  _imageProviderCalibration.calibrationLeft.cameraParam.width = _imageProviderInfo.imageFormat.dimension.width;
155  _imageProviderCalibration.calibrationLeft.cameraParam.principalPoint =
156  {
157  _imageProviderInfo.imageFormat.dimension.width / 2.f,
158  _imageProviderInfo.imageFormat.dimension.height / 2.f
159  };
160  _imageProviderCalibration.calibrationLeft.cameraParam.rotation = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
161  _imageProviderCalibration.calibrationLeft.cameraParam.translation = {0, 0, 0};
162 
163  _imageProviderCalibration.calibrationRight = _imageProviderCalibration.calibrationLeft;
164  _imageProviderCalibration.rectificationHomographyLeft = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
165  _imageProviderCalibration.rectificationHomographyRight = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
166  }
167  }
168 }
169 
171 {
172  if (!waitForImages(_imageProviderName, 1000))
173  {
174  return;
175  }
176  getImages(_providerImages.data());
177  const CByteImage& img = *(_providerImagesOwner.at(_imageIndex));
178  {
179  std::lock_guard<std::mutex> guard {_currentImageMutex};
180  _currentImage = QImage(img.width, img.height, QImage::Format_RGB888);
181  ARMARX_CHECK_NOT_NULL(_currentImage.bits());
182  ARMARX_CHECK_NOT_NULL(img.pixels);
183  std::memcpy(_currentImage.bits(), img.pixels, 3 * img.width * img.height);
184  _currentImageDirty = true;
185  }
186  ARMARX_INFO << deactivateSpam() << "received image";
187 }
188 
190 {
191  _widget.spinBoxImageIndex->setMaximum(std::max(1, _numberOfImages.load()) - 1);
192  if (!_currentImageDirty)
193  {
194  return;
195  }
196  {
197  std::lock_guard<std::mutex> guard {_currentImageMutex};
198  _maskEditor->setBackgroundImage(_currentImage);
199  _currentImageDirty = false;
200  }
201  ARMARX_INFO << deactivateSpam() << "updated displayed image";
202  if (_maskSet)
203  {
204  ARMARX_INFO << deactivateSpam() << "send new mask";
205  auto ptr = _resultImage.get();
206  provideResultImages(&ptr);
207  }
208 }
209 
211 {
212  return "VisionX.ImageMaskPainter";
213 }
214 
215 void ImageMaskPainterWidgetController::updatePenColor()
216 {
217  auto color = _widget.checkBoxErase->isChecked() ? _maskEditor->transparentColor() : QColor(0, 0, 255);
218  _maskEditor->setMaskColor(color);
219 }
220 
221 void ImageMaskPainterWidgetController::imageIndexChanged(int i)
222 {
223  _imageIndex = _widget.spinBoxImageIndex->value();
224 }
225 
226 void ImageMaskPainterWidgetController::maskUpdated()
227 {
228  if (!_resultImage)
229  {
230  //oninit did not run
231  return;
232  }
233  QSize sz = _maskEditor->imageSize();
234  if (sz.width() != _resultImage->width || sz.height() != _resultImage->height)
235  {
236  //the initial mask was set. the mask was not resized to the providers size
237  return;
238  }
239 
240  QImage mask = _maskEditor->maskImage();
241  sz = mask.size();
242  ARMARX_CHECK_EQUAL(sz.width(), _resultImage->width);
243  ARMARX_CHECK_EQUAL(sz.height(), _resultImage->height);
244 
245  //the qimage has an alpha channel!
246  for (int x = 0; x < _resultImage->width; ++x)
247  {
248  for (int y = 0; y < _resultImage->height; ++y)
249  {
250  int offset = (x + y * _resultImage->width) * 3;
251  const QColor color
252  {
253  mask.pixel(x, y)
254  };
255  _resultImage->pixels[offset + 0] = color.red();
256  _resultImage->pixels[offset + 1] = color.green();
257  _resultImage->pixels[offset + 2] = color.blue();
258  }
259  }
260  _maskSet = true;
261 }
262 
263 
264 
ImageMaskEditor::imageSize
QSize imageSize() const
Definition: ImageMaskEditor.cpp:108
armarx::ImageMaskPainterWidgetController::onInitImageProcessor
void onInitImageProcessor() override
Setup the vision component.
Definition: ImageMaskPainterWidgetController.cpp:77
armarx::ImageMaskPainterWidgetController::ImageMaskPainterWidgetController
ImageMaskPainterWidgetController()
Controller Constructor.
Definition: ImageMaskPainterWidgetController.cpp:35
visionx::ImageProviderInfo::numberImages
int numberImages
Number of images.
Definition: ImageProcessor.h:506
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:97
armarx::ImageMaskPainterWidgetController::configured
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
Definition: ImageMaskPainterWidgetController.cpp:82
armarx::ImageMaskPainterWidgetController::getConfigDialog
QPointer< QDialog > getConfigDialog(QWidget *parent) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
Definition: ImageMaskPainterWidgetController.cpp:67
visionx::ImageProcessor::getImageProvider
ImageProviderInfo getImageProvider(std::string name, ImageType destinationImageType=eRgb, bool waitForProxy=false)
Select an ImageProvider.
Definition: ImageProcessor.cpp:152
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:169
ImageMaskEditor::maskImage
QImage maskImage() const
Definition: ImageMaskEditor.cpp:86
ImageMaskEditor::setBackgroundImage
void setBackgroundImage(const QImage &i)
Definition: ImageMaskEditor.cpp:205
visionx::ImageProviderInfo::imageFormat
ImageFormatInfo imageFormat
Image format struct that contains all necessary image information.
Definition: ImageProcessor.h:496
armarx::ImageMaskPainterWidgetController::process
void process() override
Process the vision component.
Definition: ImageMaskPainterWidgetController.cpp:170
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:71
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:117
ImageMaskEditor
Definition: ImageMaskEditor.h:8
max
T max(T t1, T t2)
Definition: gdiam.h:48
visionx::ImageProcessor::getImages
int getImages(CByteImage **ppImages)
Poll images from provider.
Definition: ImageProcessor.cpp:351
armarx::red
QColor red()
Definition: StyleSheets.h:76
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:210
armarx::ImageMaskPainterWidgetController::~ImageMaskPainterWidgetController
virtual ~ImageMaskPainterWidgetController()
Controller destructor.
visionx::ImageProviderInfo::proxy
ImageProviderInterfacePrx proxy
proxy to image provider
Definition: ImageProcessor.h:472
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::ImageMaskPainterWidgetController::loadSettings
void loadSettings(QSettings *settings) override
Definition: ImageMaskPainterWidgetController.cpp:87
visionx::ImageProcessor::enableResultImages
void enableResultImages(int numberImages, ImageDimension imageDimension, ImageType imageType, const std::string &name="")
Enables visualization.
Definition: ImageProcessor.cpp:227
armarx::ImageMaskPainterWidgetController::timerEvent
void timerEvent(QTimerEvent *) override
Definition: ImageMaskPainterWidgetController.cpp:189
ImageMaskPainterWidgetController.h
ImageUtil.h
visionx::ImageProcessor::provideResultImages
void provideResultImages(CByteImage **images, armarx::MetaInfoSizeBasePtr info=nullptr)
sends result images for visualization
Definition: ImageProcessor.cpp:245
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:92
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:118
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:186
ImageMaskEditor::setPenCircleVisible
void setPenCircleVisible(bool b=true)
Definition: ImageMaskEditor.cpp:359
armarx::ImageMaskPainterWidgetController::saveSettings
void saveSettings(QSettings *settings) override
Definition: ImageMaskPainterWidgetController.cpp:92
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
ImageMaskEditor::setMaskAlpha
void setMaskAlpha(int newAlpha)
Definition: ImageMaskEditor.cpp:174
visionx::ImageProcessor::waitForImages
bool waitForImages(int milliseconds=1000)
Wait for new images.
Definition: ImageProcessor.cpp:275
armarx::SimpleConfigDialog
A config-dialog containing one (or multiple) proxy finders.
Definition: SimpleConfigDialog.h:84