File: ImagePicking.cpp

package info (click to toggle)
camitk 5.2.0-5
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 358,388 kB
  • sloc: cpp: 86,984; xml: 1,295; sh: 1,280; ansic: 142; makefile: 112; perl: 84; sed: 20
file content (146 lines) | stat: -rw-r--r-- 6,324 bytes parent folder | download
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;
}