1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2024 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#include "ImagePicking.h"
#include <ImageComponent.h>
#include <Application.h>
#include <InteractiveSliceViewer.h>
#include <Log.h>
using namespace camitk;
// Qt
#include <QPushButton>
#include <QVBoxLayout>
// -------------------- ImagePicking --------------------
ImagePicking::ImagePicking(ActionExtension* extension) : Action(extension) {
setName("Basic Image Picking");
// NOTE try to call setEmbedded(false) to see the difference
setDescription("Tutorial action that retrieve pixel information from the image");
setComponentClassName("ImageComponent");
setFamily("Tutorial");
addTag("Picking");
addTag("Image Processing");
//-- widget lazy instantiation
informationFrame = nullptr;
isConnected = false;
}
// --------------- getWidget -------------------
QWidget* ImagePicking::getWidget() {
if (!informationFrame) {
//-- the frame
informationFrame = new QFrame();
informationFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
informationFrame->setLineWidth(3);
//-- the information label
informationLabel = new QLabel();
//-- the vertical layout, put every GUI elements in it
auto* informationFrameLayout = new QVBoxLayout();
informationFrameLayout->addWidget(informationLabel);
//-- set the layout for the action widget
informationFrame->setLayout(informationFrameLayout);
}
CAMITK_TRACE("Connecting viewers signals to automatically apply this action at each user picking")
if (!isConnected && Application::getViewer("Axial Viewer") != nullptr) {
//-- run the action every time a picking is done in the axial/sagittal or coronal planes
QObject::connect(Application::getViewer("Axial Viewer"), SIGNAL(selectionChanged()), this, SLOT(apply()));
QObject::connect(Application::getViewer("Coronal Viewer"), SIGNAL(selectionChanged()), this, SLOT(apply()));
QObject::connect(Application::getViewer("Sagittal Viewer"), SIGNAL(selectionChanged()), this, SLOT(apply()));
isConnected = true;
}
return informationFrame;
}
// --------------- apply -------------------
Action::ApplyStatus ImagePicking::apply() {
if (informationFrame != nullptr) {
// set waiting cursor (not really needed here as the action is very fast, but after all this is a demo)
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
}
// get the last selected image component
ImageComponent* imageComponent = dynamic_cast<ImageComponent*>(getTargets().last());
// NOTE it is not needed to check for NULL pointer after this dynamic_cast: this action
// has declared to be able to process ImageComponent (see the setComponent(..) in the constructor),
// therefore it is only called using getTargets() that are compatible with ImageComponent
// get the last picked pixel index
int i, j, k;
imageComponent->getLastPixelPicked(&i, &j, &k);
// check validity
if (i != -1 && j != -1 && k != -1) {
// retrieve information
double pixelValue;
pixelValue = imageComponent->getImageData()->GetScalarComponentAsDouble(i, j, k, 0);
// NOTE if this was a colored image, this would be the red value (the last parameter
// of GetScalarComponentAsDouble is the index of the color component)
// update the information label
if (informationFrame != nullptr) {
informationLabel->setText("<b>Selected Component:</b> " + imageComponent->getName() + "<br/>"
+ "<b>Pixel coordinates:</b> (" + QString("%1").arg(i, 3) + ","
+ QString("%1").arg(j, 3) + "," + QString("%1").arg(k, 3) + ")<br/>"
+ "<b>Pixel value:</b> " + QString("%1").arg(pixelValue, 5)
);
}
else {
// or just print it out if there is no widget
CAMITK_INFO(tr("Selected Component: \"%1\"\n"
"- Pixel coordinates: (%2,%3,%4)\n"
"- Pixel value: %5").arg(imageComponent->getName(), QString::number(i), QString::number(j), QString::number(k), QString::number(pixelValue)))
}
}
if (informationFrame != nullptr) {
if (informationFrame->isVisible()) {
// restore the normal cursor
QApplication::restoreOverrideCursor();
}
else {
// disconnect
CAMITK_TRACE("Disconnecting viewers signals.")
if (Application::getViewer("Axial Viewer") != nullptr) {
//-- disconnect the automatic run of the action every time a picking is done in the axial/sagittal or coronal planes
QObject::disconnect(Application::getViewer("Axial Viewer"), SIGNAL(selectionChanged()), this, SLOT(apply()));
QObject::disconnect(Application::getViewer("Coronal Viewer"), SIGNAL(selectionChanged()), this, SLOT(apply()));
QObject::disconnect(Application::getViewer("Sagittal Viewer"), SIGNAL(selectionChanged()), this, SLOT(apply()));
isConnected = false;
}
}
}
return SUCCESS;
}
|