gui.cpp
4 KB
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
147
148
149
150
151
152
153
154
155
156
157
158
#include <QApplication>
#include <QLabel>
#include <opencv2/imgproc/imgproc.hpp>
#include <openbr_plugin.h>
using namespace cv;
namespace br
{
QImage toQImage(const Mat &mat)
{
// Convert to 8U depth
Mat mat8u;
if (mat.depth() != CV_8U) {
double globalMin = std::numeric_limits<double>::max();
double globalMax = -std::numeric_limits<double>::max();
std::vector<Mat> mv;
split(mat, mv);
for (size_t i=0; i<mv.size(); i++) {
double min, max;
minMaxLoc(mv[i], &min, &max);
globalMin = std::min(globalMin, min);
globalMax = std::max(globalMax, max);
}
assert(globalMax >= globalMin);
double range = globalMax - globalMin;
if (range != 0) {
double scale = 255 / range;
convertScaleAbs(mat, mat8u, scale, -(globalMin * scale));
} else {
// Monochromatic
mat8u = Mat(mat.size(), CV_8UC1, Scalar((globalMin+globalMax)/2));
}
} else {
mat8u = mat;
}
// Convert to 3 channels
Mat mat8uc3;
if (mat8u.channels() == 4) cvtColor(mat8u, mat8uc3, CV_BGRA2RGB);
else if (mat8u.channels() == 3) cvtColor(mat8u, mat8uc3, CV_BGR2RGB);
else if (mat8u.channels() == 1) cvtColor(mat8u, mat8uc3, CV_GRAY2RGB);
return QImage(mat8uc3.data, mat8uc3.cols, mat8uc3.rows, 3*mat8uc3.cols, QImage::Format_RGB888).copy();
}
// Provides slots for manipulating a QLabel, but does not inherit from QWidget.
// Therefore, it can be moved to the main thread if not created there initially
// since god forbid you create a QWidget subclass in not the main thread.
class GUIProxy : public QObject
{
Q_OBJECT
QLabel * window;
public:
GUIProxy()
{
window =NULL;
}
public slots:
void showImage(QPixmap pixmap)
{
window->show();
window->setPixmap(pixmap);
window->setFixedSize(pixmap.size());
window->update();
}
void createWindow()
{
delete window;
window = NULL;
window = new QLabel();
}
};
/*!
* \ingroup transforms
* \brief Displays templates in a GUI pop-up window using QT.
* \author Charles Otto \cite caotto
* Unlike ShowTransform, this can be used with parallelism enabled, although it
* is considered TimeVarying.
*/
class Show2Transform : public TimeVaryingTransform
{
Q_OBJECT
public:
Show2Transform() : TimeVaryingTransform(false, false)
{
// Create our GUI proxy
gui = new GUIProxy();
// Move it to the main thread, this means signals we send to it will
// be run in the main thread, which is hopefully in an event loop
gui->moveToThread(QApplication::instance()->thread());
// Connect our signals to the proxy's slots
connect(this, SIGNAL(needWindow()), gui, SLOT(createWindow()), Qt::BlockingQueuedConnection);
connect(this, SIGNAL(updateImage(QPixmap)), gui, SLOT(showImage(QPixmap)));
}
~Show2Transform()
{
delete gui;
}
void train(const TemplateList &data) { (void) data; }
void project(const TemplateList &src, TemplateList &dst) const
{
Transform * non_const = (Show2Transform *) this;
non_const->projectUpdate(src,dst);
}
void projectUpdate(const TemplateList &src, TemplateList &dst)
{
dst = src;
if (src.empty())
return;
foreach (const Template & t, src) {
foreach(const cv::Mat & m, t) {
QImage qImageBuffer = toQImage(m);
displayBuffer.convertFromImage(qImageBuffer);
emit updateImage(displayBuffer);
}
}
}
void finalize(TemplateList & output)
{
(void) output;
// todo: hide ui?
}
void init()
{
emit needWindow();
}
protected:
GUIProxy * gui;
QPixmap displayBuffer;
signals:
void needWindow();
void updateImage(QPixmap input);
};
BR_REGISTER(Transform, Show2Transform)
} // namespace br
#include "gui.moc"