UsTK : Ultrasound ToolKit  version 2.0.1 under development (2023-12-07)
usImageDisplayWidgetQmlOverlayServoing.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ustk software.
4  * Copyright (C) 2016 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ustk with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * This software was developed at:
17  * Inria Rennes - Bretagne Atlantique
18  * Campus Universitaire de Beaulieu
19  * 35042 Rennes Cedex
20  * France
21  *
22  * If you have questions regarding the use of this file, please contact
23  * Inria at ustk@inria.fr
24  *
25  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27  *
28  * Authors:
29  * Marc Pouliquen
30  *
31  *****************************************************************************/
32 
39 #include <visp3/ustk_gui/usImageDisplayWidgetQmlOverlayServoing.h>
40 
41 #if (defined(USTK_HAVE_VTK_QT5) || defined(USTK_HAVE_QT5))
42 
43 #include <QQuickItem>
44 
49  : usImageDisplayWidget(), m_qQuickOverlay(), m_useFeatureDisplay(false), m_confidence(), m_plot(), m_startTime()
50 {
51  this->setMinimumSize(200, 200);
52  m_qQuickOverlay = new QQuickWidget(m_label);
53  m_qQuickOverlay->setAttribute(Qt::WA_AlwaysStackOnTop);
54  m_qQuickOverlay->setClearColor(Qt::transparent);
55  m_qQuickOverlay->setSource(QUrl("qrc:/qml/overlay-servoing-rect-centering.qml"));
56 
57  connect(m_qQuickOverlay->rootObject(), SIGNAL(startTracking()), this, SLOT(startTrackingSlot()));
58  connect(m_qQuickOverlay->rootObject(), SIGNAL(stopTracking()), this, SIGNAL(stopTrackingRect()));
59  connect(m_qQuickOverlay->rootObject(), SIGNAL(startServoing()), this, SIGNAL(startServoingRect()));
60  connect(m_qQuickOverlay->rootObject(), SIGNAL(stopServoing()), this, SIGNAL(stopServoingRect()));
61 
62  QQuickWidget::Status status(QQuickWidget::Null);
63 
64  while (status != QQuickWidget::Ready) {
65  status = m_qQuickOverlay->status();
66  vpTime::wait(50);
67  }
68 
69 #if defined(VISP_HAVE_GDI)
70  m_display = new vpDisplayGDI;
71 #elif defined(VISP_HAVE_OPENCV)
72  m_display = new vpDisplayOpenCV;
73 #endif
74 }
75 
80 
82 {
83  event->accept();
85  if (m_qQuickOverlay->rootObject()) {
86  m_qQuickOverlay->rootObject()->setProperty("width", event->size().width());
87  m_qQuickOverlay->rootObject()->setProperty("height", event->size().height());
88 
89  QObject *rectItem = m_qQuickOverlay->rootObject()->findChild<QObject *>("selectionRectangle");
90  if (rectItem) {
91  int x = rectItem->property("x").toInt() * event->size().height() / (double)size().height();
92  int y = rectItem->property("y").toInt() * event->size().width() / (double)size().width();
93  rectItem->setProperty("x", x);
94  rectItem->setProperty("y", y);
95  }
96  }
97 }
98 
104 {
105  if (m_useScanConversion) {
107  m_QImage = QImage(m_postScan.bitmap, m_postScan.getWidth(), m_postScan.getHeight(), m_postScan.getWidth(),
108  QImage::Format_Indexed8);
109  } else
110  m_QImage = QImage(img.bitmap, img.getWidth(), img.getHeight(), img.getWidth(), QImage::Format_Indexed8);
111 
112  QImage I = m_QImage.convertToFormat(QImage::Format_RGB888);
113  I = I.scaled(this->width(), this->height());
114  m_pixmap = QPixmap::fromImage(I);
115  m_label->setPixmap(m_pixmap);
116  m_label->update();
117 
118  // update feature display
119  if (m_useFeatureDisplay) {
120 #if (defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
121  if (m_confidence.getSize() > 0) {
122  if (m_confidence.display == NULL)
123  m_display->init(m_confidence);
124  vpDisplay::display(m_confidence);
125  }
126 #endif
127  }
128 }
129 
130 vpImagePoint usImageDisplayWidgetQmlOverlayServoing::displayImageToRealImageDimentions(const vpImagePoint displayPoint)
131 {
132  vpImagePoint p;
133  unsigned int imageHeight;
134  unsigned int imageWidth;
135  if (m_useScanConversion) {
136  imageHeight = m_postScan.getHeight();
137  imageWidth = m_postScan.getWidth();
138  } else {
139  imageHeight = m_image.getHeight();
140  imageWidth = m_image.getWidth();
141  }
142  p.set_i((displayPoint.get_i() * imageHeight) / (double)height());
143  p.set_j((displayPoint.get_j() * imageWidth) / (double)width());
144 
145  return p;
146 }
147 
148 vpImagePoint
149 usImageDisplayWidgetQmlOverlayServoing::realImageToDisplayImageDimentions(const vpImagePoint realImagePoint)
150 {
151  vpImagePoint p;
152  unsigned int imageHeight;
153  unsigned int imageWidth;
154  if (m_useScanConversion) {
155  imageHeight = m_postScan.getHeight();
156  imageWidth = m_postScan.getWidth();
157  } else {
158  imageHeight = m_image.getHeight();
159  imageWidth = m_image.getWidth();
160  }
161  p.set_i((realImagePoint.get_i() * height()) / (double)imageHeight);
162  p.set_j((realImagePoint.get_j() * width()) / (double)imageWidth);
163 
164  return p;
165 }
166 
167 vpRectOriented
168 usImageDisplayWidgetQmlOverlayServoing::displayImageToRealImageDimentions(const vpRectOriented displayRectangle)
169 {
170  // center point
171  vpImagePoint center;
172  center = displayImageToRealImageDimentions(displayRectangle.getCenter());
173 
174  // rectangle height & width scaling using angular parameter
175  unsigned int imageHeight;
176  unsigned int imageWidth;
177  if (m_useScanConversion) {
178  imageHeight = m_postScan.getHeight();
179  imageWidth = m_postScan.getWidth();
180  } else {
181  imageHeight = m_image.getHeight();
182  imageWidth = m_image.getWidth();
183  }
184  int newHeight =
185  (displayRectangle.getHeight() * imageHeight / (double)height()) * std::cos(displayRectangle.getOrientation()) +
186  (displayRectangle.getWidth() * imageWidth / (double)width()) * std::sin(displayRectangle.getOrientation());
187  int newWidth =
188  (displayRectangle.getHeight() * imageHeight / (double)height()) * std::sin(displayRectangle.getOrientation()) +
189  (displayRectangle.getWidth() * imageWidth / (double)width()) * std::cos(displayRectangle.getOrientation());
190 
191  return vpRectOriented(center, newWidth, newHeight, displayRectangle.getOrientation());
192 }
193 
194 vpRectOriented
195 usImageDisplayWidgetQmlOverlayServoing::realImageToDisplayImageDimentions(const vpRectOriented realRectangle)
196 {
197  // center point
198  vpImagePoint center;
199  center = realImageToDisplayImageDimentions(realRectangle.getCenter());
200 
201  // rectangle height & width scaling using angular parameter
202  unsigned int imageHeight;
203  unsigned int imageWidth;
204  if (m_useScanConversion) {
205  imageHeight = m_postScan.getHeight();
206  imageWidth = m_postScan.getWidth();
207  } else {
208  imageHeight = m_image.getHeight();
209  imageWidth = m_image.getWidth();
210  }
211  int newHeight =
212  (realRectangle.getHeight() * height() / (double)imageHeight) * std::cos(realRectangle.getOrientation()) +
213  (realRectangle.getWidth() * width() / (double)imageWidth) * std::sin(realRectangle.getOrientation());
214 
215  int newWidth =
216  (realRectangle.getHeight() * height() / (double)imageHeight) * std::sin(realRectangle.getOrientation()) +
217  (realRectangle.getWidth() * width() / (double)imageWidth) * std::cos(realRectangle.getOrientation());
218 
219  return vpRectOriented(center, newWidth, newHeight, realRectangle.getOrientation());
220 }
221 
227 {
228  // transform rectangle from real image size to display dimentions
229  vpRectOriented displayRectangle;
230  displayRectangle = realImageToDisplayImageDimentions(newRectangle);
231 
232  QObject *rectItem = m_qQuickOverlay->rootObject()->findChild<QObject *>("selectionRectangle");
233  rectItem->setProperty("x", displayRectangle.getCenter().get_j() - (displayRectangle.getWidth() / 2.0));
234  rectItem->setProperty("y", displayRectangle.getCenter().get_i() - (displayRectangle.getHeight() / 2.0));
235  rectItem->setProperty("rotation", vpMath::deg(displayRectangle.getOrientation()));
236  rectItem->setProperty("height", displayRectangle.getHeight());
237  rectItem->setProperty("width", displayRectangle.getWidth());
238 }
239 
245 {
246  QObject *rectangleObject = m_qQuickOverlay->rootObject()->findChild<QObject *>("selectionRectangle");
247  int topLeftX = rectangleObject->property("x").toInt();
248  int topLeftY = rectangleObject->property("y").toInt();
249  int height = rectangleObject->property("height").toInt();
250  int width = rectangleObject->property("width").toInt();
251  int centerX = topLeftX + (width / 2.0);
252  int centerY = topLeftY + (height / 2.0);
253  int rotation = rectangleObject->property("rotation").toInt();
254 
255  vpRectOriented displayRect(vpImagePoint(centerY, centerX), width, height, vpMath::rad(rotation));
256 
257  emit(startTrackingRect(displayImageToRealImageDimentions(displayRect)));
258 }
259 
261 {
262  m_useFeatureDisplay = true;
263 
264  m_plot.init(2);
265  m_plot.initGraph(0, 1);
266  m_plot.setTitle(0, "confidence barycenter error");
267  m_plot.setUnitY(0, "error");
268  m_plot.setLegend(0, 0, "time");
269  m_plot.initGraph(1, 1);
270  m_plot.setTitle(1, "Lateral tracking error");
271  m_plot.setUnitY(1, "error");
272  m_plot.setLegend(1, 0, "time");
273  m_startTime = vpTime::measureTimeMs();
274 }
275 
277 
279 {
280 #if (defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
281  if (m_useFeatureDisplay) {
282  vpImagePoint p0 = vpImagePoint(0, scanline);
283  vpImagePoint p1 = vpImagePoint(m_confidence.getHeight() - 1, scanline);
284  vpImagePoint p2 = vpImagePoint(0, m_confidence.getWidth() / 2);
285  vpImagePoint p3 = vpImagePoint(m_confidence.getHeight() - 1, m_confidence.getWidth() / 2);
286  vpDisplay::displayLine(m_confidence, p0, p1, vpColor::red);
287  vpDisplay::displayLine(m_confidence, p2, p3, vpColor::green);
288  vpDisplay::flush(m_confidence);
289 
290  // plot errors
291  m_plot.plot(0, 0, vpTime::measureTimeMs() - m_startTime,
292  vpMath::deg(scanline * m_confidence.getScanLinePitch() - m_confidence.getFieldOfView() / 2.0));
293  }
294 #endif
295 }
296 
298 {
299  m_confidence = confidence;
300 }
301 
303 {
304 #if (defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
305  if (m_useFeatureDisplay) {
306  // plot errors
307  m_plot.plot(1, 0, vpTime::measureTimeMs() - m_startTime, error);
308  }
309 #endif
310 }
311 
312 #endif
void startTrackingRect(vpRectOriented)
void updateConfidenceMap(usImagePreScan2D< unsigned char > confidence)
void updateFrame(const usImagePreScan2D< unsigned char > img)
Qt widget class for 2D ultrasound image display.
vpImage< unsigned char > m_image
void resizeEvent(QResizeEvent *event)
usPreScanToPostScan2DConverter m_scanConverter
usImagePostScan2D< unsigned char > m_postScan
void convert(const usImagePreScan2D< unsigned char > &preScanImage, usImagePostScan2D< unsigned char > &postScanImage, double xResolution=0., double yResolution=0.)