Subversion Repositories seema-scanner

Rev

Rev 29 | Rev 32 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 jakw 1
#include "SMScanner.h"
2
#include "ui_SMScanner.h"
3
 
4 jakw 4
#include <QMetaObject>
5
 
27 jakw 6
SMScanner::SMScanner(QWidget *parent) :QMainWindow(parent), ui(new Ui::SMScanner),
7
                                        calibrationReviewMode(false), captureReviewMode(false){
1 jakw 8
    ui->setupUi(this);
4 jakw 9
 
27 jakw 10
    // Register metatypes
11
    qRegisterMetaType<cv::Mat>("cv::Mat");
12
    qRegisterMetaType< std::vector<cv::Mat> >("std::vector<cv::Mat>");
30 jakw 13
    qRegisterMetaType< std::vector<float> >("std::vector<float>");
27 jakw 14
    qRegisterMetaType<SMCalibrationSet>("SMCalibrationSet");
15
    qRegisterMetaType<SMCalibrationParameters>("SMCalibrationParameters");
16
    qRegisterMetaTypeStreamOperators<SMCalibrationParameters>("SMCalibrationParameters");
17
    qRegisterMetaType< std::vector<SMCalibrationSet> >("std::vector<SMCalibrationSet>");
18
    qRegisterMetaType<SMFrameSequence>("SMFrameSequence");
19
 
4 jakw 20
    // Restore geometry
21
    this->restoreGeometry(settings.value("geometry/mainwindow").toByteArray());
22
    this->restoreState(settings.value("state/mainwindow").toByteArray());
23
 
24
    // Set up threads
25
    captureWorker = new SMCaptureWorker;
26
    captureWorkerThread = new QThread(this);
27
    captureWorkerThread->setObjectName("captureWorkerThread");
28
    captureWorker->moveToThread(captureWorkerThread);
29
    captureWorkerThread->start();
30
 
31
    // Connections
23 jakw 32
    connect(captureWorker, SIGNAL(newFrame(unsigned int, cv::Mat)), this, SLOT(onReceiveFrame(unsigned int, cv::Mat)));
27 jakw 33
    connect(captureWorker, SIGNAL(newCalibrationSet(SMCalibrationSet)), this, SLOT(onReceiveCalibrationSet(SMCalibrationSet)));
34
    connect(captureWorker, SIGNAL(newFrameSequence(SMFrameSequence)), this, SLOT(onReceiveFrameSequence(SMFrameSequence)));
30 jakw 35
    connect(captureWorker, SIGNAL(rotatedTo(float)), this, SLOT(onReceiveRotatedTo(float)));
4 jakw 36
 
37
    // Start capturing
38
    QMetaObject::invokeMethod(captureWorker, "setup");
39
    QMetaObject::invokeMethod(captureWorker, "doWork");
40
 
1 jakw 41
}
42
 
23 jakw 43
void SMScanner::onReceiveFrame(unsigned int camId, cv::Mat frame){
4 jakw 44
 
23 jakw 45
    if(camId == 0){
25 jakw 46
        if(!calibrationReviewMode)
47
            ui->calibrationCamera0Widget->showImageCV(frame);
27 jakw 48
        if(!captureReviewMode)
49
            ui->captureCamera0Widget->showImageCV(frame);
23 jakw 50
    } else if(camId == 1){
25 jakw 51
        if(!calibrationReviewMode)
52
            ui->calibrationCamera1Widget->showImageCV(frame);
27 jakw 53
        if(!captureReviewMode)
54
            ui->captureCamera1Widget->showImageCV(frame);
23 jakw 55
    }
56
}
4 jakw 57
 
23 jakw 58
void SMScanner::on_actionPreferences_triggered(){
4 jakw 59
 
60
    preferenceDialog.show();
61
}
62
 
63
void SMScanner::closeEvent(QCloseEvent *event){
64
 
23 jakw 65
    // Stop capturing thread
66
    connect(captureWorker, SIGNAL(finished()), captureWorker, SLOT(deleteLater()));
67
    connect(captureWorker, SIGNAL(finished()), captureWorkerThread, SLOT(quit()));
68
    QMetaObject::invokeMethod(captureWorker, "stopWork");
69
    captureWorkerThread->quit();
70
    captureWorkerThread->wait();
71
 
4 jakw 72
    // Save window geometry
73
    settings.setValue("geometry/mainwindow", this->saveGeometry());
74
    settings.setValue("state/mainwindow", this->saveState());
75
 
76
    event->accept();
77
 
78
}
79
 
2 jakw 80
SMScanner::~SMScanner(){
1 jakw 81
    delete ui;
82
}
4 jakw 83
 
23 jakw 84
void SMScanner::on_singleCalibrationButton_clicked(){
85
 
25 jakw 86
    // If in review mode, go back to aquisition mode
87
    if(calibrationReviewMode){
26 jakw 88
        ui->calibrationListWidget->clearSelection();
25 jakw 89
        ui->singleCalibrationButton->setText("Single Aquisition");
90
        ui->batchCalibrationButton->setText("Batch Aquisition");
91
        calibrationReviewMode = false;
92
        return;
93
    }
94
 
27 jakw 95
    QMetaObject::invokeMethod(captureWorker, "acquireCalibrationSet", Q_ARG(float, -1.0));
23 jakw 96
 
97
}
98
 
30 jakw 99
 
100
void SMScanner::on_batchCalibrationButton_clicked(){
101
 
102
    // If in review mode, go back to aquisition mode
103
    if(calibrationReviewMode){
104
        ui->calibrationListWidget->clearSelection();
105
        ui->singleCalibrationButton->setText("Single Aquisition");
106
        ui->batchCalibrationButton->setText("Batch Aquisition");
107
        calibrationReviewMode = false;
108
        return;
109
    }
110
 
111
    // Construct vector of angles
112
    int angleStart = ui->calibrationBatchStartSpinBox->value();
113
    int angleEnd = ui->calibrationBatchEndSpinBox->value();
114
    int angleStep = ui->calibrationBatchStepSpinBox->value();
115
 
116
    if(angleStart > angleEnd)
117
        angleEnd += 360;
118
 
119
    std::vector<float> angles;
120
    for(int i=angleStart; i<=angleEnd; i+=angleStep)
121
        angles.push_back(i % 360);
122
 
123
    QMetaObject::invokeMethod(captureWorker, "acquireCalibrationSets", Q_ARG(std::vector<float>, angles));
124
 
125
    std::cout << "Aquiring sets at ";
126
    for(int i=0; i<angles.size(); i++)
127
        std::cout << angles[i] << " ";
128
    std::cout << " degrees" <<std::endl;
129
}
130
 
131
 
23 jakw 132
void SMScanner::on_calibrationRotationDial_sliderReleased(){
27 jakw 133
 
23 jakw 134
    float angle = ui->calibrationRotationDial->value();
135
    std::cout << "Rotation stage target: " << angle << std::endl;
136
    QMetaObject::invokeMethod(captureWorker, "rotateTo", Q_ARG(float, angle));
27 jakw 137
 
138
    ui->captureRotationDial->setValue(ui->calibrationRotationDial->value());
23 jakw 139
}
24 jakw 140
 
27 jakw 141
void SMScanner::onReceiveCalibrationSet(SMCalibrationSet calibrationSet){
23 jakw 142
    calibrationData.push_back(calibrationSet);
25 jakw 143
 
144
    // Add identifier to list
29 jakw 145
    QListWidgetItem* item = new QListWidgetItem(QString("Calibration Set %1 -- %2 deg").arg(ui->calibrationListWidget->count()).arg(calibrationSet.rotationAngle), ui->calibrationListWidget);
25 jakw 146
    item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
147
    item->setCheckState(Qt::Checked);
148
    ui->calibrationListWidget->addItem(item);
149
 
150
    // Set enabled checkmark
151
    if(calibrationData.size() >= 2)
152
        ui->calibrateButton->setEnabled(true);
23 jakw 153
}
25 jakw 154
 
27 jakw 155
void SMScanner::on_calibrateButton_clicked(){
25 jakw 156
 
29 jakw 157
    // disable ui elements
158
    ui->calibrateButton->setEnabled(false);
159
    ui->calibrationFrame->setEnabled(false);
27 jakw 160
 
161
    // set checked flags
162
    for(int i=0; i<calibrationData.size(); i++){
163
        calibrationData[i].checked = (ui->calibrationListWidget->item(i)->checkState() == Qt::Checked);
164
    }
165
 
166
//    SMCalibrationWorker calibrationWorker;
167
//    calibrationWorker.performCalibration(calibrationData);
168
 
169
    // Set up calibration thread
170
    calibrationWorker = new SMCalibrationWorker;
171
    calibrationWorkerThread = new QThread(this);
172
    calibrationWorkerThread->setObjectName("calibrationWorkerThread");
173
    calibrationWorker->moveToThread(captureWorkerThread);
174
    calibrationWorkerThread->start();
175
 
176
    // Connections
28 jakw 177
    connect(calibrationWorker, SIGNAL(newSetProcessed(int)), this, SLOT(onCalibrationSetProcessed(int)));
29 jakw 178
    connect(calibrationWorker, SIGNAL(newFrameResult(int,int,bool,cv::Mat)), this, SLOT(onCalibrationFrameResult(int,int,bool,cv::Mat)));
27 jakw 179
    connect(calibrationWorker, SIGNAL(done()), this, SLOT(onCalibrationDone()));
180
    connect(calibrationWorker, SIGNAL(done()), calibrationWorkerThread, SLOT(quit()));
181
    connect(calibrationWorker, SIGNAL(done()), calibrationWorker, SLOT(deleteLater()));
182
 
183
    // Start capturing
184
    QMetaObject::invokeMethod(calibrationWorker, "performCalibration", Q_ARG(std::vector<SMCalibrationSet>, calibrationData));
185
 
186
}
187
 
30 jakw 188
 
189
 
27 jakw 190
void SMScanner::onCalibrationSetProcessed(int idx){
191
 
192
    ui->calibrationListWidget->setCurrentRow(idx);
193
}
194
 
195
void SMScanner::onCalibrationDone(){
196
 
197
    std::cout << "Calibration done!" << std::endl;
29 jakw 198
    ui->calibrateButton->setEnabled(true);
199
    ui->calibrationFrame->setEnabled(true);
27 jakw 200
 
201
}
202
 
203
void SMScanner::on_calibrationListWidget_itemSelectionChanged(){
204
 
205
    // if selection is just cleared
206
    if(ui->calibrationListWidget->selectedItems().empty())
207
        return;
208
 
209
    int currentRow = ui->calibrationListWidget->currentRow();
210
 
25 jakw 211
    calibrationReviewMode = true;
212
    ui->singleCalibrationButton->setText("Live View");
213
    ui->batchCalibrationButton->setText("Live View");
214
 
215
    if(!calibrationData[currentRow].frame0Result.empty())
216
        ui->calibrationCamera0Widget->showImageCV(calibrationData[currentRow].frame0Result);
217
    else
218
        ui->calibrationCamera0Widget->showImageCV(calibrationData[currentRow].frame0);
219
 
220
    if(!calibrationData[currentRow].frame1Result.empty())
221
        ui->calibrationCamera1Widget->showImageCV(calibrationData[currentRow].frame1Result);
222
    else
223
        ui->calibrationCamera1Widget->showImageCV(calibrationData[currentRow].frame1);
27 jakw 224
 
225
//     std::cout << "on_calibrationListWidget_itemSelectionChanged" << std::endl;
25 jakw 226
}
227
 
29 jakw 228
void SMScanner::onCalibrationFrameResult(int idx, int camID, bool success, cv::Mat result){
25 jakw 229
 
29 jakw 230
//    std::cout << "onCalibrationFrameResult " << idx << camID << std::endl;
27 jakw 231
 
29 jakw 232
    if(!success)
233
        ui->calibrationListWidget->item(idx)->setCheckState(Qt::Unchecked);
234
    else {
235
        if(camID == 0)
236
            calibrationData[idx].frame0Result = result;
237
        else if(camID == 1)
238
            calibrationData[idx].frame1Result = result;
239
    }
27 jakw 240
 
241
}
242
 
243
void SMScanner::on_singleCaptureButton_clicked(){
244
 
245
    // If in review mode, go back to aquisition mode
246
    if(captureReviewMode){
247
        ui->captureTreeWidget->clearSelection();
248
        ui->singleCaptureButton->setText("Single Aquisition");
249
        ui->batchCaptureButton->setText("Batch Aquisition");
250
        captureReviewMode = false;
251
        return;
25 jakw 252
    }
253
 
27 jakw 254
    QMetaObject::invokeMethod(captureWorker, "acquireFrameSequence", Q_ARG(float, -1.0));
25 jakw 255
 
256
}
26 jakw 257
 
27 jakw 258
 
30 jakw 259
void SMScanner::on_batchCaptureButton_clicked(){
260
 
261
    // If in review mode, go back to aquisition mode
262
    if(captureReviewMode){
263
        ui->captureTreeWidget->clearSelection();
264
        ui->singleCaptureButton->setText("Single Aquisition");
265
        ui->batchCaptureButton->setText("Batch Aquisition");
266
        captureReviewMode = false;
267
        return;
268
    }
269
 
270
    // Construct vector of angles
271
    int angleStart = ui->captureBatchStartSpinBox->value();
272
    int angleEnd = ui->captureBatchEndSpinBox->value();
273
    int angleStep = ui->captureBatchStepSpinBox->value();
274
 
275
    if(angleStart > angleEnd)
276
        angleEnd += 360;
277
 
278
    std::vector<float> angles;
279
    for(int i=angleStart; i<=angleEnd; i+=angleStep)
280
        angles.push_back(i % 360);
281
 
282
    std::cout << "Aquiring sequences at ";
283
    for(int i=0; i<angles.size(); i++)
284
        std::cout << angles[i] << " ";
285
    std::cout << " degrees" <<std::endl;
286
 
287
    QMetaObject::invokeMethod(captureWorker, "acquireFrameSequences", Q_ARG(std::vector<float>, angles));
288
}
289
 
27 jakw 290
void SMScanner::on_captureRotationDial_sliderReleased(){
291
 
292
    float angle = ui->captureRotationDial->value();
293
    std::cout << "Rotation stage target: " << angle << std::endl;
294
    QMetaObject::invokeMethod(captureWorker, "rotateTo", Q_ARG(float, angle));
295
 
296
    ui->calibrationRotationDial->setValue(ui->captureRotationDial->value());
26 jakw 297
}
27 jakw 298
 
299
void SMScanner::onReceiveFrameSequence(SMFrameSequence frameSequence){
300
 
301
    captureData.push_back(frameSequence);
302
 
303
    int idx = captureData.size()-1;
304
 
305
    // Add identifier to list
306
    QTreeWidgetItem* item = new QTreeWidgetItem(ui->captureTreeWidget);
307
    item->setText(0, QString("Frame Sequence %1 -- %2 deg").arg(idx).arg(frameSequence.rotationAngle));
308
    item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
309
    item->setData(0, Qt::UserRole, QPoint(idx, -1));
310
    item->setCheckState(0, Qt::Checked);
311
    //ui->captureTreeWidget->addItem(item);
312
 
313
    for(int i=0; i<frameSequence.frames0.size(); i++){
314
        QTreeWidgetItem* subItem = new QTreeWidgetItem(item);
315
        subItem->setText(0, QString("frames %1").arg(i));
316
        subItem->setData(0, Qt::UserRole, QPoint(idx, i));
317
    }
318
}
319
 
320
void SMScanner::on_captureTreeWidget_itemSelectionChanged(){
321
 
322
    // if selection is just cleared
323
    if(ui->captureTreeWidget->selectedItems().empty())
324
        return;
325
 
326
    QTreeWidgetItem *item = ui->captureTreeWidget->currentItem();
327
 
328
    captureReviewMode = true;
329
 
330
    ui->singleCaptureButton->setText("Live View");
331
    ui->batchCaptureButton->setText("Live View");
332
 
333
    QPoint idx = item->data(0, Qt::UserRole).toPoint();
334
 
335
    if(idx.y() != -1){
336
        ui->captureCamera0Widget->showImageCV(captureData[idx.x()].frames0[idx.y()]);
337
        ui->captureCamera1Widget->showImageCV(captureData[idx.x()].frames1[idx.y()]);
338
    }
339
 
340
//     std::cout << "on_captureTreeWidget_itemSelectionChanged" << std::endl;
341
}
30 jakw 342
 
343
 
344
void SMScanner::onReceiveRotatedTo(float angle){
345
 
346
    // update ui with new position
347
    ui->calibrationRotationDial->setValue(angle);
348
    ui->captureRotationDial->setValue(angle);
349
 
350
}