9 #pragma warning(disable : 4996)
39 #include <vtkAxesActor.h>
40 #include <vtkBMPReader.h>
41 #include <vtkCallbackCommand.h>
42 #include <vtkCamera.h>
43 #include <vtkCaptionActor2D.h>
44 #include <vtkCommand.h>
45 #include <vtkContext2D.h>
46 #include <vtkInteractorObserver.h>
47 #include <vtkInteractorStyleImage.h>
48 #include <vtkJPEGReader.h>
49 #include <vtkLookupTable.h>
51 #include <vtkOpenGLRenderWindow.h>
52 #include <vtkPNGReader.h>
53 #include <vtkPNMReader.h>
54 #include <vtkPropAssembly.h>
55 #include <vtkProperty.h>
56 #include <vtkQImageToImageSource.h>
57 #include <vtkRenderWindow.h>
58 #include <vtkRenderWindowInteractor.h>
59 #include <vtkRenderer.h>
60 #include <vtkRendererCollection.h>
61 #include <vtkTIFFReader.h>
62 #include <vtkTextProperty.h>
63 #include <vtkTextureUnitManager.h>
64 #include <vtkTransform.h>
65 #include <vtkUnsignedCharArray.h>
67 #if VTK_MAJOR_VERSION >= 6
69 #include <vtkImageProperty.h>
70 #include <vtkImageSlice.h>
71 #include <vtkImageSliceMapper.h>
75 #include <pcl/common/transforms.h>
76 #include <pcl/visualization/common/float_image_utils.h>
81 #ifdef vtkGenericDataArray_h
82 #define SetTupleValue SetTypedTuple
83 #define InsertNextTupleValue InsertNextTypedTuple
84 #define GetTupleValue GetTypedTuple
95 ImageVis::ImageVis(
const string& viewerName,
bool initIterator)
96 :
pcl::visualization::ImageViewer(viewerName), m_cameraParamsSaved(false) {
98 m_originalCameraParams.parallelProjection =
false;
99 m_originalCameraParams.focalPoint[0] =
100 m_originalCameraParams.focalPoint[1] =
101 m_originalCameraParams.focalPoint[2] = 0.0;
102 m_originalCameraParams.position[0] = m_originalCameraParams.position[1] =
103 m_originalCameraParams.position[2] = 0.0;
104 m_originalCameraParams.viewUp[0] = m_originalCameraParams.viewUp[1] =
105 m_originalCameraParams.viewUp[2] = 0.0;
106 m_originalCameraParams.viewAngle = 30.0;
107 m_originalCameraParams.parallelScale = 1.0;
108 m_originalCameraParams.clippingRange[0] = 0.01;
109 m_originalCameraParams.clippingRange[1] = 1000.0;
119 if (!win || !interactor) {
131 "[ImageVis::enable2Dviewer] Do not support 2D viewer on Linux or "
132 "Mac platform now!");
148 m_mouseConnection.disconnect();
152 void ImageVis::mouseEventProcess(
const pcl::visualization::MouseEvent&
event,
154 if (
event.getButton() == pcl::visualization::MouseEvent::RightButton &&
155 event.getType() == pcl::visualization::MouseEvent::MouseMove) {
158 CVLog::Print(QString(
"Picked item id : %1").arg(
id.c_str()));
164 int x =
event.getX();
165 int y =
event.getY();
174 while (layer->
actor->GetScene()->GetItem(index)) {
178 layer->
actor->GetScene()->GetItem(index));
192 return std::string(
"");
199 if (win && !m_windowResizeCallback) {
201 m_windowResizeCallback->SetCallback(WindowResizeCallback);
202 m_windowResizeCallback->SetClientData(
this);
203 win->AddObserver(vtkCommand::WindowResizeEvent, m_windowResizeCallback);
218 if (interactor && !m_originalInteractorStyle) {
219 m_originalInteractorStyle = interactor->GetInteractorStyle();
229 this->
interactor_->AddObserver(vtkCommand::TimerEvent,
248 LayerMap::const_iterator am_it = std::find_if(
255 #if VTK_MAJOR_VERSION >= 6
256 auto it = m_imageInfoMap.find(
id);
257 if (it != m_imageInfoMap.end() && it->second.imageSlice) {
266 const std::string&
id) {
268 if (l.layer_name ==
id) {
276 double opacity = visibility ? 1.0 : 0.0;
282 while (layer->
actor->GetScene()->GetItem(index)) {
283 layer->
actor->GetScene()->GetItem(index)->SetVisible(visibility);
286 layer->
actor->SetVisibility(opacity);
287 layer->
actor->Modified();
291 #if VTK_MAJOR_VERSION >= 6
292 auto it = m_imageInfoMap.find(viewID);
293 if (it != m_imageInfoMap.end() && it->second.imageSlice) {
294 vtkImageSlice* imageSlice = it->second.imageSlice;
295 imageSlice->SetVisibility(visibility ? 1 : 0);
296 imageSlice->Modified();
302 #if VTK_MAJOR_VERSION >= 6
305 auto it = m_imageInfoMap.find(viewID);
306 if (it != m_imageInfoMap.end() && it->second.imageSlice) {
307 vtkImageSlice* imageSlice = it->second.imageSlice;
308 imageSlice->SetVisibility(opacity > 0.0 ? 1 : 0);
309 imageSlice->GetProperty()->SetOpacity(opacity);
312 "[ImageVis::changeOpacity] Set opacity to %f using "
313 "vtkImageSlice::GetProperty()->SetOpacity()",
327 layer->
actor->SetVisibility(opacity > 0.0 ? 1 : 0);
328 layer->
actor->Modified();
336 #if VTK_MAJOR_VERSION >= 6
338 bool isImageLayer = m_imageInfoMap.find(layer_id) != m_imageInfoMap.end();
341 auto it = m_imageInfoMap.find(layer_id);
342 if (it != m_imageInfoMap.end() && it->second.imageSlice &&
ren_) {
343 ren_->RemoveViewProp(it->second.imageSlice);
347 m_imageInfoMap.erase(layer_id);
351 if (isImageLayer && m_imageInfoMap.empty() &&
interactor_ &&
352 m_originalInteractorStyle) {
353 interactor_->SetInteractorStyle(m_originalInteractorStyle);
355 m_originalInteractorStyle =
nullptr;
358 if (m_cameraParamsSaved &&
ren_ &&
ren_->GetActiveCamera()) {
359 vtkCamera* camera =
ren_->GetActiveCamera();
360 camera->SetFocalPoint(m_originalCameraParams.focalPoint);
361 camera->SetPosition(m_originalCameraParams.position);
362 camera->SetViewUp(m_originalCameraParams.viewUp);
363 camera->SetViewAngle(m_originalCameraParams.viewAngle);
364 camera->SetParallelScale(m_originalCameraParams.parallelScale);
365 camera->SetClippingRange(m_originalCameraParams.clippingRange);
366 if (m_originalCameraParams.parallelProjection) {
367 camera->ParallelProjectionOn();
369 camera->ParallelProjectionOff();
371 m_cameraParamsSaved =
false;
382 const std::string& layer_id,
393 l.
actor->PickableOff();
394 l.
actor->DragableOff();
398 FilledRectangle>::New();
399 rect->setColors(0, 0, 0);
400 rect->setOpacity(opacity);
401 rect->set(
x,
y,
static_cast<float>(
width),
static_cast<float>(
height));
402 l.
actor->GetScene()->AddItem(rect);
404 #if VTK_MAJOR_VERSION < 6
418 const std::string& layer_id,
420 if (qimage.isNull()) {
425 #if VTK_MAJOR_VERSION >= 6
426 unsigned width = qimage.width();
427 unsigned height = qimage.height();
430 QImage rgbaImage = qimage;
431 if (rgbaImage.format() != QImage::Format_RGBA8888) {
432 rgbaImage = rgbaImage.convertToFormat(QImage::Format_RGBA8888);
438 qimageToImageSource->SetQImage(&rgbaImage);
439 qimageToImageSource->Update();
444 imageData->SetOrigin(0.0, 0.0, 0.0);
445 imageData->SetSpacing(1.0, 1.0, 1.0);
449 auto it = m_imageInfoMap.find(layer_id);
450 if (it != m_imageInfoMap.end() && it->second.imageSlice &&
ren_) {
451 ren_->RemoveViewProp(it->second.imageSlice);
457 mapper->SetInputData(imageData);
458 mapper->SetSliceNumber(0);
464 imageSlice->SetMapper(mapper);
465 imageSlice->GetProperty()->SetOpacity(opacity);
466 imageSlice->GetProperty()->SetInterpolationTypeToLinear();
469 imageSlice->SetPosition(
x,
y, 0);
472 if (opacity < 1.0 &&
ren_) {
473 vtkRenderWindow* renderWindow =
ren_->GetRenderWindow();
475 renderWindow->SetAlphaBitPlanes(1);
488 setImageInteractorStyle();
493 ren_->AddViewProp(imageSlice);
499 updateImageSliceTransform(imageSlice,
width,
height);
508 info.originalWidth =
width;
509 info.originalHeight =
height;
510 info.imageSlice = imageSlice;
511 info.imageMapper = mapper;
512 m_imageInfoMap[layer_id] = info;
515 CVLog::Warning(
"[ImageVis::addRGBImage] vtkImageSlice requires VTK >= 6.0");
523 const std::string& layer_id,
530 const std::string& text_string,
534 const std::string& layer_id,
543 LayerMap::iterator am_it = std::find_if(
547 "[pcl::visualization::ImageViewer::addText] No layer with "
548 "ID='%s' found. Creating new one...\n",
552 #if ((VTK_MAJOR_VERSION == 5) && (VTKOR_VERSION > 10))
559 text->setColors(
static_cast<unsigned char>(255.0 * r),
560 static_cast<unsigned char>(255.0 * g),
561 static_cast<unsigned char>(255.0 * b));
562 text->setOpacity(opacity);
564 text->setFontSize(fontSize);
565 #if ((VTK_MAJOR_VERSION >= 6) || \
566 ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION > 7)))
567 text->set(
static_cast<float>(
x),
static_cast<float>(
y), text_string);
569 text->set(
static_cast<float>(
x),
static_cast<float>(
getSize()[1] -
y),
572 am_it->actor->GetScene()->AddItem(text);
577 void ImageVis::WindowResizeCallback(vtkObject* caller,
578 unsigned long eventId,
586 self->onWindowResize();
590 void ImageVis::onWindowResize() {
597 void ImageVis::updateImageScales() {
602 int* winSize =
win_->GetSize();
603 if (!winSize || winSize[0] <= 0 || winSize[1] <= 0) {
607 #if VTK_MAJOR_VERSION >= 6
609 for (
auto& pair : m_imageInfoMap) {
610 if (pair.second.imageSlice && pair.second.originalWidth > 0 &&
611 pair.second.originalHeight > 0) {
612 updateImageSliceTransform(pair.second.imageSlice,
613 pair.second.originalWidth,
614 pair.second.originalHeight);
619 for (
auto& pair : m_imageInfoMap) {
620 if (pair.second.imageItem) {
621 pair.second.imageItem->updateScale(winSize[0], winSize[1]);
627 #if VTK_MAJOR_VERSION >= 6
628 void ImageVis::updateImageSliceTransform(vtkImageSlice* imageSlice,
635 int* winSize =
win_->GetSize();
636 if (!winSize || winSize[0] <= 0 || winSize[1] <= 0) {
641 vtkImageSliceMapper* mapper =
642 vtkImageSliceMapper::SafeDownCast(imageSlice->GetMapper());
644 int extent[6] = {0,
static_cast<int>(
width) - 1,
645 0,
static_cast<int>(
height) - 1,
647 mapper->SetDisplayExtent(extent);
648 mapper->SetBorder(1);
655 vtkCamera* camera =
ren_->GetActiveCamera();
658 double pos[3] = {0.0, 0.0, 0.0};
660 imageSlice->GetPosition(pos);
665 double xc = pos[0] + (
width - 1) * 0.5;
666 double yc = pos[1] + (
height - 1) * 0.5;
667 double zd = 3.346065;
669 camera->SetFocalPoint(xc, yc, 0.0);
670 camera->SetPosition(xc, yc, zd);
672 camera->SetParallelScale(0.5 *
height);
673 camera->ParallelProjectionOn();
681 imageSlice->Modified();
685 void ImageVis::setImageInteractorStyle() {
698 if (!m_originalInteractorStyle) {
699 m_originalInteractorStyle =
interactor_->GetInteractorStyle();
704 if (!m_cameraParamsSaved &&
ren_ &&
ren_->GetActiveCamera()) {
705 vtkCamera* camera =
ren_->GetActiveCamera();
706 m_originalCameraParams.parallelProjection =
707 camera->GetParallelProjection();
708 camera->GetFocalPoint(m_originalCameraParams.focalPoint);
709 camera->GetPosition(m_originalCameraParams.position);
710 camera->GetViewUp(m_originalCameraParams.viewUp);
711 m_originalCameraParams.viewAngle = camera->GetViewAngle();
712 m_originalCameraParams.parallelScale = camera->GetParallelScale();
713 camera->GetClippingRange(m_originalCameraParams.clippingRange);
714 m_cameraParamsSaved =
true;
717 camera->ParallelProjectionOn();
722 vtkInteractorStyleImage* currentImageStyle =
723 vtkInteractorStyleImage::SafeDownCast(
725 if (!currentImageStyle) {
730 imageStyle->SetDefaultRenderer(
ren_);
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool PrintVerbose(const char *format,...)
Prints out a verbose formatted message in console.
void addQImage(const QImage &qimage, const std::string &layer_id="image", double opacity=1.0)
Add a QImage directly (ParaView-style, using vtkQImageToImageSource).
Layer * getLayer(const std::string &id)
void setRender(vtkSmartPointer< vtkRenderer > render)
void removeLayer(const std::string &layer_id)
Remove a layer from the viewer.
vtkSmartPointer< vtkRenderWindowInteractor > getRenderWindowInteractor()
bool addText(unsigned int x, unsigned int y, const std::string &text_string, double r, double g, double b, const std::string &layer_id="line", double opacity=1.0, int fontSize=10, bool bold=false)
std::string pickItem(int x, int y)
void enable2Dviewer(bool state)
void setRenderWindow(vtkSmartPointer< vtkRenderWindow > win)
void hideShowActors(bool visibility, const std::string &viewID)
void changeOpacity(double opacity, const std::string &viewID)
bool contains(const std::string &id) const
Check if the image with the given id was already added to this visualizer.
void setupInteractor(vtkSmartPointer< vtkRenderWindowInteractor > interactor, vtkSmartPointer< vtkRenderWindow > win)
Set up our unique PCL interactor style for a given vtkRenderWindowInteractor object attached to a giv...
void setRenderWindowInteractor(vtkSmartPointer< vtkRenderWindowInteractor > interactor)
void addRGBImage(const QImage &qimage, unsigned x, unsigned y, const std::string &layer_id, double opacity=1.0)
vtkSmartPointer< vtkRenderWindow > getRenderWindow()
vtkSmartPointer< vtkRenderer > getRender()
The renderer.
LayerMap::iterator createLayer(const std::string &layer_id, int x, int y, int width, int height, double opacity=0.5, bool fill_box=true)
Add a new 2D rendering layer to the viewer.
vtkSmartPointer< vtkRenderWindow > win_
The render window.
vtkSmartPointer< vtkImageViewer > image_viewer_
The ImageViewer widget.
void resetStoppedFlag()
Set the stopped flag back to false.
int * getSize()
Return the window size in pixels.
boost::signals2::connection registerMouseCallback(void(*callback)(const pcl::visualization::MouseEvent &, void *), void *cookie=nullptr)
Register a callback std::function for mouse events.
void removeLayer(const std::string &layer_id)
Remove a 2D layer given by its ID.
vtkSmartPointer< vtkImageSlice > slice_
Global prop. This is the actual "actor".
int timer_id_
Global timer ID. Used in destructor only.
LayerMap layer_map_
Internal list with different 2D layers shapes.
vtkSmartPointer< vtkRenderer > ren_
The renderer.
vtkSmartPointer< ExitMainLoopTimerCallback > exit_main_loop_timer_callback_
Callback object enabling us to leave the main loop, when a timer fires.
vtkSmartPointer< vtkRenderWindowInteractor > interactor_
vtkSmartPointer< ImageViewerInteractorStyle > interactor_style_
The interactor style.
vtkSmartPointer< ExitCallback > exit_callback_
void render()
Trigger a render call.
Internal structure describing a layer.
vtkSmartPointer< vtkContextActor > actor
vtkRenderWindowInteractor * vtkRenderWindowInteractorFixNew()