Subversion Repositories seema-scanner

Rev

Rev 199 | Rev 208 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 199 Rev 207
Line 249... Line 249...
249
    connect(calibrationWorker, SIGNAL(done()), ui->pointCloudWidget, SLOT(updateCalibrationParameters()));
249
    connect(calibrationWorker, SIGNAL(done()), ui->pointCloudWidget, SLOT(updateCalibrationParameters()));
250
    connect(calibrationWorker, SIGNAL(done()), calibrationWorkerThread, SLOT(quit()));
250
    connect(calibrationWorker, SIGNAL(done()), calibrationWorkerThread, SLOT(quit()));
251
    connect(calibrationWorker, SIGNAL(done()), calibrationWorker, SLOT(deleteLater()));
251
    connect(calibrationWorker, SIGNAL(done()), calibrationWorker, SLOT(deleteLater()));
252
 
252
 
253
    // Start calibration
253
    // Start calibration
254
    QMetaObject::invokeMethod(calibrationWorker, "performCalibration", Q_ARG(std::vector<SMCalibrationSet>, calibrationData));
254
    QMetaObject::invokeMethod(calibrationWorker, "performCameraCalibration", Q_ARG(std::vector<SMCalibrationSet>, calibrationData));
255
 
255
 
256
}
256
}
257
 
257
 
258
 
258
 
259
 
259
 
Line 277... Line 277...
277
 
277
 
278
    // if selection is just cleared
278
    // if selection is just cleared
279
    if(ui->calibrationListWidget->selectedItems().empty())
279
    if(ui->calibrationListWidget->selectedItems().empty())
280
        return;
280
        return;
281
 
281
 
-
 
282
    // clamp to available range
282
    int currentRow = ui->calibrationListWidget->currentRow();
283
    assert(ui->calibrationListWidget->currentRow() >= 0
-
 
284
           && ui->calibrationListWidget->currentRow() < calibrationData.size());
-
 
285
    int currentRow = std::min(int(calibrationData.size())-1,
-
 
286
                              std::max(0, ui->calibrationListWidget->currentRow()));
283
 
287
 
284
    calibrationReviewMode = true;
288
    calibrationReviewMode = true;
285
    ui->singleCalibrationButton->setText("Live View");
289
    ui->singleCalibrationButton->setText("Live View");
286
    ui->batchCalibrationButton->setText("Live View");
290
    ui->batchCalibrationButton->setText("Live View");
287
 
291
 
Line 379... Line 383...
379
 
383
 
380
    QMetaObject::invokeMethod(captureWorker, "acquireFrameSequences", Q_ARG(std::vector<float>, angles));
384
    QMetaObject::invokeMethod(captureWorker, "acquireFrameSequences", Q_ARG(std::vector<float>, angles));
381
}
385
}
382
 
386
 
383
void SMScanner::onReceiveFrameSequence(SMFrameSequence frameSequence){
387
void SMScanner::onReceiveFrameSequence(SMFrameSequence frameSequence){
384
 
-
 
385
    int id = lastCaptureId + 1;
-
 
386
    lastCaptureId += 1;
-
 
387
 
-
 
388
    frameSequence.id = id;
388
    frameSequence.id = ++lastCaptureId;
389
 
-
 
390
    captureData.push_back(frameSequence);
389
    captureData.push_back(frameSequence);
391
 
390
 
392
    // Add identifier to list
391
    // Add identifier to list
393
    QTreeWidgetItem* item = new QTreeWidgetItem(ui->captureTreeWidget);
392
    QTreeWidgetItem* item = new QTreeWidgetItem(ui->captureTreeWidget);
394
    item->setText(0, QString("Frame Sequence %1 -- %2 deg").arg(id).arg(frameSequence.rotationAngle));
393
    item->setText(0, QString("Frame Sequence %1 -- %2 deg").arg(frameSequence.id).arg(frameSequence.rotationAngle));
395
    //item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
394
    //item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
396
    item->setData(0, Qt::UserRole, QPoint(captureData.size()-1, -1));
395
    item->setData(0, Qt::UserRole, QPoint(captureData.size()-1, -1));
397
    //item->setCheckState(0, Qt::Checked);
396
    //item->setCheckState(0, Qt::Checked);
398
    //ui->captureTreeWidget->addItem(item);
397
    //ui->captureTreeWidget->addItem(item);
399
 
398
 
400
    for(unsigned int i=0; i<frameSequence.frames0.size(); i++){
399
    for(unsigned int i=0; i<frameSequence.frames0.size(); i++){
401
        QTreeWidgetItem* subItem = new QTreeWidgetItem(item);
400
        QTreeWidgetItem* subItem = new QTreeWidgetItem(item);
402
        subItem->setText(0, QString("frames %1").arg(i));
401
        subItem->setText(0, QString("frames %1").arg(i));
403
        subItem->setData(0, Qt::UserRole, QPoint(id, i));
402
        subItem->setData(0, Qt::UserRole, QPoint(frameSequence.id, i));
404
    }
403
    }
405
 
404
 
406
    ui->reconstructButton->setEnabled(true);
405
    ui->reconstructButton->setEnabled(true);
407
}
406
}
408
 
407
 
Line 419... Line 418...
419
    ui->singleCaptureButton->setText("Live View");
418
    ui->singleCaptureButton->setText("Live View");
420
    ui->batchCaptureButton->setText("Live View");
419
    ui->batchCaptureButton->setText("Live View");
421
 
420
 
422
    QPoint idx = item->data(0, Qt::UserRole).toPoint();
421
    QPoint idx = item->data(0, Qt::UserRole).toPoint();
423
 
422
 
424
    if(idx.y() != -1){
423
    if( idx.y() != -1 && idx.x()>=0 && idx.x()<captureData.size()
-
 
424
            && idx.y()<captureData[idx.x()].frames0.size()
-
 
425
            && idx.y()<captureData[idx.x()].frames1.size() ){
-
 
426
        // TODO idx.x() can & WILL be out of bounds
425
        ui->captureCamera0Widget->showImageCV(captureData[idx.x()].frames0[idx.y()]);
427
        ui->captureCamera0Widget->showImageCV(captureData[idx.x()].frames0[idx.y()]);
426
        ui->captureCamera1Widget->showImageCV(captureData[idx.x()].frames1[idx.y()]);
428
        ui->captureCamera1Widget->showImageCV(captureData[idx.x()].frames1[idx.y()]);
427
    }
429
    }
428
 
-
 
429
//     std::cout << "on_captureTreeWidget_itemSelectionChanged" << std::endl;
430
//     std::cout << "on_captureTreeWidget_itemSelectionChanged" << std::endl;
430
}
431
}
431
 
432
 
432
 
433
 
433
void SMScanner::onReceiveRotatedTo(float angle){
434
void SMScanner::onReceiveRotatedTo(float angle){
Line 573... Line 574...
573
    connect(reconstructionWorker, SIGNAL(done()), reconstructionWorker, SLOT(deleteLater()));
574
    connect(reconstructionWorker, SIGNAL(done()), reconstructionWorker, SLOT(deleteLater()));
574
 
575
 
575
    // Start reconstructing
576
    // Start reconstructing
576
    QMetaObject::invokeMethod(reconstructionWorker, "setup");
577
    QMetaObject::invokeMethod(reconstructionWorker, "setup");
577
 
578
 
-
 
579
    // TODO is a reference working here??
-
 
580
    QMetaObject::invokeMethod(reconstructionWorker, "reconstructPointClouds", Q_ARG(std::vector<SMFrameSequence>, captureData));
578
    for(unsigned int i=0; i<captureData.size(); i++){
581
    for(unsigned int i=0; i<captureData.size(); i++){
579
        if(!captureData[i].reconstructed){ // & (ui->captureTreeWidget->topLevelItem(i)->checkState(0) == Qt::Checked))
582
        if(!captureData[i].reconstructed){ // & (ui->captureTreeWidget->topLevelItem(i)->checkState(0) == Qt::Checked))
580
            captureData[i].reconstructed = true;
583
            captureData[i].reconstructed = true;
581
            QMetaObject::invokeMethod(reconstructionWorker, "reconstructPointCloud", Q_ARG(SMFrameSequence, captureData[i]));
584
            // now done before QMetaObject::invokeMethod(reconstructionWorker, "reconstructPointCloud", Q_ARG(SMFrameSequence, captureData[i]));
582
        }
585
        }
583
    }
586
    }
584
 
-
 
585
}
587
}
586
 
588
 
587
void SMScanner::onReceivePointCloud(SMPointCloud smCloud){
589
void SMScanner::onReceivePointCloud(SMPointCloud smCloud){
588
 
-
 
589
    int id = smCloud.id;
-
 
590
 
-
 
591
//    for(int i=0; i<captureData.size(); i++){
590
//    for(int i=0; i<captureData.size(); i++){
592
//        if(captureData[i].id == id)
591
//        if(captureData[i].id == id)
593
//            captureData[i].reconstructed = true;
592
//            captureData[i].reconstructed = true;
594
//    }
593
//    }
595
 
594
 
596
    pointCloudData.push_back(smCloud);
595
    //pointCloudData.push_back(smCloud);
-
 
596
    if(pointCloudData.size()<=smCloud.id) pointCloudData.resize(smCloud.id+1);
-
 
597
    pointCloudData[smCloud.id] = smCloud;
597
 
598
 
598
    // Add identifier to list
599
    // Add identifier to list
599
    QListWidgetItem* item = new QListWidgetItem(QString("Point Cloud %1 -- %2 deg").arg(id).arg(smCloud.rotationAngle));
600
    QListWidgetItem* item = new QListWidgetItem(QString("Point Cloud %1 -- %2 deg").arg(smCloud.id).arg(smCloud.rotationAngle));
600
    item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
601
    item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
601
    item->setData(Qt::UserRole, QVariant(id));
602
    item->setData(Qt::UserRole, QVariant(smCloud.id));
602
    item->setCheckState(Qt::Checked);
603
    item->setCheckState(Qt::Checked);
603
 
604
 
604
    ui->pointCloudsListWidget->addItem(item);
605
    ui->pointCloudsListWidget->addItem(item);
605
ui->pointCloudWidget->addPointCloud(smCloud, id);
606
    ui->pointCloudWidget->addPointCloud(smCloud, smCloud.id);
606
}
607
}
607
 
608
 
608
 
-
 
609
 
-
 
610
void SMScanner::on_actionExport_Point_Clouds_triggered(){
609
void SMScanner::on_actionExport_Point_Clouds_triggered(){
611
 
610
 
612
    QString directory = QFileDialog::getExistingDirectory(this, "Export Point Clouds", QString());
611
    QString directory = QFileDialog::getExistingDirectory(this, "Export Point Clouds", QString());
613
 
612
 
614
//    //  Non native file dialog
613
//    //  Non native file dialog
Line 625... Line 624...
625
 
624
 
626
    // save point clouds in ply format
625
    // save point clouds in ply format
627
    for(unsigned int i=0; i<pointCloudData.size(); i++){
626
    for(unsigned int i=0; i<pointCloudData.size(); i++){
628
 
627
 
629
        progressDialog.setValue(100.0*i/pointCloudData.size());
628
        progressDialog.setValue(100.0*i/pointCloudData.size());
630
 
-
 
-
 
629
    if(pointCloudData[i].id != -1){
631
        QString fileName = QString("%1/pointcloud_%2.ply").arg(directory).arg(i);
630
        QString fileName = QString("%1/pointcloud_%2.ply").arg(directory).arg(i);
632
        pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pointCloudPCL(pointCloudData[i].pointCloud);
631
        pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr pointCloudPCL(pointCloudData[i].pointCloud);
633
        //pcl::io::savePLYFileBinary(fileName.toStdString(), *pointCloudPCL);
632
        //pcl::io::savePLYFileBinary(fileName.toStdString(), *pointCloudPCL);
634
        pcl::PLYWriter w;
633
        pcl::PLYWriter w;
635
        // Write to ply in binary without camera
634
        // Write to ply in binary without camera
636
        w.write<pcl::PointXYZRGBNormal> (fileName.toStdString(), *pointCloudPCL, true, false);
635
        w.write<pcl::PointXYZRGBNormal> (fileName.toStdString(), *pointCloudPCL, true, false);
637
 
636
    }
638
        QCoreApplication::processEvents();
637
        QCoreApplication::processEvents();
639
        if(progressDialog.wasCanceled())
638
        if(progressDialog.wasCanceled())
640
            return;
639
            return;
641
    }
640
    }
642
 
641
 
643
    // save meshlab aln project file
642
    // save meshlab aln project file
644
    std::ofstream s(QString("%1/alignment.aln").arg(directory).toLocal8Bit());
643
    std::ofstream s(QString("%1/alignment.aln").arg(directory).toLocal8Bit());
645
    s << pointCloudData.size() << std::endl;
644
    s << pointCloudData.size() << std::endl;
646
    for(unsigned int i=0; i<pointCloudData.size(); i++){
645
    for(unsigned int i=0; i<pointCloudData.size(); i++){
-
 
646
        if(pointCloudData[i].id != -1){
647
        QString fileName = QString("pointcloud_%1.ply").arg(i);
647
        QString fileName = QString("pointcloud_%1.ply").arg(pointCloudData[i].id);
648
        s << fileName.toStdString() << std::endl << "#" << std::endl;
648
        s << fileName.toStdString() << std::endl << "#" << std::endl;
649
        cv::Mat Tr = cv::Mat::eye(4, 4, CV_32F);
649
        cv::Mat Tr = cv::Mat::eye(4, 4, CV_32F);
650
        cv::Mat(pointCloudData[i].R.t()).copyTo(Tr.colRange(0, 3).rowRange(0, 3));
650
        cv::Mat(pointCloudData[i].R.t()).copyTo(Tr.colRange(0, 3).rowRange(0, 3));
651
        cv::Mat(-pointCloudData[i].R.t()*pointCloudData[i].T).copyTo(Tr.col(3).rowRange(0, 3));
651
        cv::Mat(-pointCloudData[i].R.t()*pointCloudData[i].T).copyTo(Tr.col(3).rowRange(0, 3));
652
        for(int j=0; j<Tr.rows; j++){
652
        for(int j=0; j<Tr.rows; j++){
653
            for(int k=0; k<Tr.cols; k++){
653
            for(int k=0; k<Tr.cols; k++){
654
                s << Tr.at<float>(j,k) << " ";
654
                s << Tr.at<float>(j,k) << " ";
655
            }
655
            }
656
            s << std::endl;
656
            s << std::endl;
657
        }
657
        }
-
 
658
        }
658
    }
659
    }
659
    s << "0" << std::flush;
660
    s << "0" << std::flush;
660
    s.close();
661
    s.close();
661
}
662
}
662
 
663
 
663
void SMScanner::on_pointCloudsListWidget_itemChanged(QListWidgetItem *item){
664
void SMScanner::on_pointCloudsListWidget_itemChanged(QListWidgetItem *item){
664
 
665
 
665
    int id = item->data(Qt::UserRole).toInt();
666
    int id = item->data(Qt::UserRole).toInt();
666
 
-
 
-
 
667
    assert(pointCloudData.size()>id);
667
    if(item->checkState() == Qt::Checked)
668
    if(item->checkState() == Qt::Checked){
-
 
669
        id = std::min(int(pointCloudData.size())-1,std::max(0,id));// clamp range
668
        ui->pointCloudWidget->addPointCloud(pointCloudData[id], id);
670
        ui->pointCloudWidget->addPointCloud(pointCloudData[id], id);
-
 
671
    }
669
    else
672
    else
670
        ui->pointCloudWidget->removePointCloud(id);
673
        ui->pointCloudWidget->removePointCloud(id);
671
 
674
 
672
}
675
}
673
 
676
 
Line 689... Line 692...
689
    int res = QMessageBox::question(this, "Clear Captured Sequences", "Clear all captured data?", QMessageBox::Ok, QMessageBox::Cancel);
692
    int res = QMessageBox::question(this, "Clear Captured Sequences", "Clear all captured data?", QMessageBox::Ok, QMessageBox::Cancel);
690
 
693
 
691
    if(res == QMessageBox::Ok){
694
    if(res == QMessageBox::Ok){
692
        captureData.clear();
695
        captureData.clear();
693
        ui->captureTreeWidget->clear();
696
        ui->captureTreeWidget->clear();
-
 
697
        lastCaptureId=-1;
694
    }
698
    }
695
}
699
}
696
 
700
 
697
 
701
 
698
 
702
 
Line 786... Line 790...
786
        return;
790
        return;
787
    }
791
    }
788
 
792
 
789
    captureData.clear();
793
    captureData.clear();
790
    ui->captureTreeWidget->clear();
794
    ui->captureTreeWidget->clear();
-
 
795
    lastCaptureId=-1;
791
 
796
 
792
    QProgressDialog progressDialog("Importing Sequences...", "Cancel", 0, 100, this);
797
    QProgressDialog progressDialog("Importing Sequences...", "Cancel", 0, 100, this);
793
    progressDialog.setWindowModality(Qt::WindowModal);
798
    progressDialog.setWindowModality(Qt::WindowModal);
794
    progressDialog.setMinimumDuration(1000);
799
    progressDialog.setMinimumDuration(1000);
795
 
800