diff --git a/src/AddObjectDialog.cpp b/src/AddObjectDialog.cpp index f8073899..303729de 100644 --- a/src/AddObjectDialog.cpp +++ b/src/AddObjectDialog.cpp @@ -19,10 +19,10 @@ #include #include -AddObjectDialog::AddObjectDialog(Camera * camera, QList * objects, bool mirrorView, QWidget * parent, Qt::WindowFlags f) : +AddObjectDialog::AddObjectDialog(Camera * camera, const IplImage * image, bool mirrorView, QWidget * parent, Qt::WindowFlags f) : QDialog(parent, f), camera_(camera), - objects_(objects), + object_(0), cvImage_(0) { ui_ = new Ui_addObjectDialog(); @@ -38,7 +38,16 @@ AddObjectDialog::AddObjectDialog(Camera * camera, QList * objects, b connect(ui_->cameraView, SIGNAL(roiChanged(const QRect &)), this, SLOT(updateNextButton(const QRect &))); ui_->cameraView->setMirrorView(mirrorView); - this->setState(kTakePicture); + if((camera_ && camera_->isRunning()) || !image) + { + this->setState(kTakePicture); + } + else if(image) + { + cv::Mat img(image); + update(img); + this->setState(kSelectFeatures); + } } AddObjectDialog::~AddObjectDialog() @@ -47,12 +56,19 @@ AddObjectDialog::~AddObjectDialog() { cvReleaseImage(&cvImage_); } + if(object_) + { + delete object_; + } delete ui_; } void AddObjectDialog::closeEvent(QCloseEvent* event) { - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); + if(camera_) + { + disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); + } QDialog::closeEvent(event); } @@ -141,11 +157,14 @@ void AddObjectDialog::setState(int state) } else if(state == kSelectFeatures) { - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - camera_->pause(); + if(camera_) + { + disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); + camera_->pause(); + } ui_->pushButton_cancel->setEnabled(true); - ui_->pushButton_back->setEnabled(true); + ui_->pushButton_back->setEnabled(camera_); ui_->pushButton_next->setEnabled(false); ui_->pushButton_takePicture->setEnabled(false); ui_->pushButton_next->setText(tr("Next")); @@ -168,8 +187,11 @@ void AddObjectDialog::setState(int state) } else if(state == kVerifySelection) { - disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - camera_->pause(); + if(camera_) + { + disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); + camera_->pause(); + } ui_->pushButton_cancel->setEnabled(true); ui_->pushButton_back->setEnabled(true); @@ -262,7 +284,12 @@ void AddObjectDialog::setState(int state) } } - objects_->append(new ObjWidget(0, keypoints, descriptors, ui_->objectView->iplImage(), Settings::currentDetectorType(), Settings::currentDescriptorType())); + if(object_) + { + delete object_; + object_ = 0; + } + object_ = new ObjWidget(0, keypoints, descriptors, ui_->objectView->iplImage(), Settings::currentDetectorType(), Settings::currentDescriptorType()); this->accept(); } diff --git a/src/AddObjectDialog.h b/src/AddObjectDialog.h index 1712327c..7b9b371e 100644 --- a/src/AddObjectDialog.h +++ b/src/AddObjectDialog.h @@ -20,9 +20,12 @@ class AddObjectDialog : public QDialog { Q_OBJECT public: - AddObjectDialog(Camera * camera, QList * objects, bool mirrorView, QWidget * parent = 0, Qt::WindowFlags f = 0); + AddObjectDialog(Camera * camera, const IplImage * image, bool mirrorView, QWidget * parent = 0, Qt::WindowFlags f = 0); virtual ~AddObjectDialog(); + // ownership transferred to caller + ObjWidget * retrieveObject() {ObjWidget * obj = object_; object_=0; return obj;} + private slots: void update(const cv::Mat &); void next(); @@ -42,7 +45,7 @@ private: private: Ui_addObjectDialog * ui_; Camera * camera_; - QList * objects_; + ObjWidget * object_; IplImage * cvImage_; enum State{kTakePicture, kSelectFeatures, kVerifySelection, kClosing}; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 1397e066..50c74f86 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -66,6 +66,7 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) : connect(ui_->toolBox, SIGNAL(parametersChanged()), this, SLOT(notifyParametersChanged())); ui_->imageView_source->setGraphicsViewMode(false); + ui_->imageView_source->setTextLabel(tr("Press \"space\" to start camera...")); //reset button connect(ui_->pushButton_restoreDefaults, SIGNAL(clicked()), ui_->toolBox, SLOT(resetCurrentPage())); @@ -77,7 +78,7 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) : ui_->actionSave_objects->setEnabled(false); // Actions - connect(ui_->actionAdd_object, SIGNAL(triggered()), this, SLOT(addObject())); + connect(ui_->actionAdd_object_from_scene, SIGNAL(triggered()), this, SLOT(addObjectFromScene())); connect(ui_->actionAdd_objects_from_files, SIGNAL(triggered()), this, SLOT(addObjectsFromFiles())); connect(ui_->actionLoad_scene_from_file, SIGNAL(triggered()), this, SLOT(loadSceneFromFile())); connect(ui_->actionStart_camera, SIGNAL(triggered()), this, SLOT(startProcessing())); @@ -86,16 +87,16 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) : connect(ui_->actionExit, SIGNAL(triggered()), this, SLOT(close())); connect(ui_->actionSave_objects, SIGNAL(triggered()), this, SLOT(saveObjects())); connect(ui_->actionLoad_objects, SIGNAL(triggered()), this, SLOT(loadObjects())); - connect(ui_->actionSetup_camera_from_video_file, SIGNAL(triggered()), this, SLOT(setupCameraFromVideoFile())); - connect(ui_->actionSetup_camera_from_video_file_2, SIGNAL(triggered()), this, SLOT(setupCameraFromVideoFile())); + connect(ui_->actionCamera_from_video_file, SIGNAL(triggered()), this, SLOT(setupCameraFromVideoFile())); connect(ui_->actionAbout, SIGNAL(triggered()), aboutDialog_ , SLOT(exec())); connect(ui_->actionRestore_all_default_settings, SIGNAL(triggered()), ui_->toolBox, SLOT(resetAllPages())); connect(ui_->actionRemove_all_objects, SIGNAL(triggered()), this, SLOT(removeAllObjects())); - ui_->actionSetup_camera_from_video_file->setCheckable(true); - ui_->actionSetup_camera_from_video_file_2->setCheckable(true); - ui_->actionSetup_camera_from_video_file->setChecked(!Settings::getCamera_videoFilePath().isEmpty()); - ui_->actionSetup_camera_from_video_file_2->setChecked(!Settings::getCamera_videoFilePath().isEmpty()); + ui_->actionStart_camera->setShortcut(Qt::Key_Space); + ui_->actionPause_camera->setShortcut(Qt::Key_Space); + + ui_->actionCamera_from_video_file->setCheckable(true); + ui_->actionCamera_from_video_file->setChecked(!Settings::getCamera_videoFilePath().isEmpty()); if(Settings::getGeneral_autoStartCamera()) { @@ -155,8 +156,7 @@ void MainWindow::loadObjects(const QString & dirPath) QDir dir(dirPath); if(dir.exists()) { - QStringList filters; - filters << "*.png" << "*.jpg" << "*.bmp" << "*.tiff"; + QStringList filters = Settings::getGeneral_imageFormats().split(' '); QFileInfoList list = dir.entryInfoList(filters, QDir::Files, QDir::Name); for(int i=0; ideleteLater(); this->updateData(); + if(!camera_->isRunning() && ui_->imageView_source->iplImage()) + { + cv::Mat image(ui_->imageView_source->iplImage(), true); + this->update(image); + } } } void MainWindow::removeAllObjects() { - QList obj = objects_; - for(int i=0; iupdateData(); + if(!camera_->isRunning() && ui_->imageView_source->iplImage()) + { + cv::Mat image(ui_->imageView_source->iplImage(), true); + this->update(image); } } -void MainWindow::addObject() +void MainWindow::addObjectFromScene() { disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - AddObjectDialog dialog(camera_, &objects_, ui_->imageView_source->isMirrorView(), this); - if(dialog.exec() == QDialog::Accepted) + AddObjectDialog * dialog; + bool resumeCamera = camera_->isRunning(); + if(!ui_->actionStart_camera->isEnabled() || !ui_->imageView_source->iplImage()) { - showObject(objects_.last()); - updateData(); - objectsModified_ = true; + dialog = new AddObjectDialog(camera_, ui_->imageView_source->iplImage(), ui_->imageView_source->isMirrorView(), this); } - this->startProcessing(); + else + { + dialog = new AddObjectDialog(0, ui_->imageView_source->iplImage(), ui_->imageView_source->isMirrorView(), this); + } + if(dialog->exec() == QDialog::Accepted) + { + ObjWidget * obj = dialog->retrieveObject(); + if(obj) + { + objects_.push_back(obj); + showObject(objects_.last()); + updateData(); + objectsModified_ = true; + } + } + if(resumeCamera || !ui_->imageView_source->iplImage()) + { + this->startProcessing(); + } + else + { + connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); + cv::Mat image(ui_->imageView_source->iplImage(), true); + this->update(image); + } + delete dialog; } void MainWindow::addObjectsFromFiles() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Add objects..."), Settings::workingDirectory(), tr("Image Files (*.png *.jpg *.bmp *.tiff)")); + QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Add objects..."), Settings::workingDirectory(), tr("Image Files (%1)").arg(Settings::getGeneral_imageFormats())); if(fileNames.size()) { for(int i=0; iid() == id) @@ -295,7 +329,7 @@ void MainWindow::addObjectFromFile(const QString & filePath) void MainWindow::loadSceneFromFile() { - QString fileName = QFileDialog::getOpenFileName(this, tr("Load scene..."), Settings::workingDirectory(), tr("Image Files (*.png *.jpg *.bmp *.tiff)")); + QString fileName = QFileDialog::getOpenFileName(this, tr("Load scene..."), Settings::workingDirectory(), tr("Image Files (%1)").arg(Settings::getGeneral_imageFormats())); if(!fileName.isEmpty()) { IplImage * img = cvLoadImage(fileName.toStdString().c_str()); @@ -311,17 +345,26 @@ void MainWindow::loadSceneFromFile() void MainWindow::setupCameraFromVideoFile() { - QString fileName = QFileDialog::getOpenFileName(this, tr("Setup camera from video file..."), Settings::workingDirectory(), tr("Video Files (*.avi *.m4v)")); - if(!fileName.isEmpty()) + if(!ui_->actionCamera_from_video_file->isChecked()) { - Settings::setCamera_videoFilePath(fileName); + Settings::setCamera_videoFilePath(""); ui_->toolBox->updateParameter(Settings::kCamera_videoFilePath()); - if(camera_->isRunning()) + } + else + { + QString fileName = QFileDialog::getOpenFileName(this, tr("Setup camera from video file..."), Settings::workingDirectory(), tr("Video Files (%1)").arg(Settings::getGeneral_videoFormats())); + if(!fileName.isEmpty()) { - this->stopProcessing(); - this->startProcessing(); + Settings::setCamera_videoFilePath(fileName); + ui_->toolBox->updateParameter(Settings::kCamera_videoFilePath()); + if(camera_->isRunning()) + { + this->stopProcessing(); + this->startProcessing(); + } } } + ui_->actionCamera_from_video_file->setChecked(!Settings::getCamera_videoFilePath().isEmpty()); } void MainWindow::showObject(ObjWidget * obj) @@ -405,8 +448,11 @@ void MainWindow::updateObjects() detectorDescriptorType->setText(QString("%1/%2").arg(objects_.at(i)->detectorType()).arg(objects_.at(i)->descriptorType())); } updateData(); - notifyParametersChanged(); // this will update the scene if camera is stopped - + } + if(!camera_->isRunning() && ui_->imageView_source->iplImage()) + { + cv::Mat image(ui_->imageView_source->iplImage(), true); + this->update(image); } this->statusBar()->clearMessage(); } @@ -478,7 +524,11 @@ void MainWindow::updateData() void MainWindow::startProcessing() { - this->statusBar()->showMessage(tr("Starting camera...")); + bool updateStatusMessage = this->statusBar()->currentMessage().isEmpty(); + if(updateStatusMessage) + { + this->statusBar()->showMessage(tr("Starting camera...")); + } if(camera_->start()) { connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); @@ -487,11 +537,17 @@ void MainWindow::startProcessing() ui_->actionStart_camera->setEnabled(false); ui_->actionLoad_scene_from_file->setEnabled(false); ui_->label_timeRefreshRate->setVisible(true); - this->statusBar()->showMessage(tr("Camera started."), 2000); + if(updateStatusMessage) + { + this->statusBar()->showMessage(tr("Camera started."), 2000); + } } else { - this->statusBar()->clearMessage(); + if(updateStatusMessage) + { + this->statusBar()->clearMessage(); + } if(this->isVisible()) { QMessageBox::critical(this, tr("Camera error"), tr("Camera initialization failed! (with device %1)").arg(Settings::getCamera_deviceId())); @@ -628,7 +684,8 @@ void MainWindow::update(const cv::Mat & image) float maxMatchedDistance = -1.0f; for(int i=0; istatusBar()->showMessage(tr("A parameter has changed... \"Update objects\" may be required.")); @@ -832,6 +890,5 @@ void MainWindow::notifyParametersChanged() ui_->label_timeRefreshRate->setVisible(false); } - ui_->actionSetup_camera_from_video_file->setChecked(!Settings::getCamera_videoFilePath().isEmpty()); - ui_->actionSetup_camera_from_video_file_2->setChecked(!Settings::getCamera_videoFilePath().isEmpty()); + ui_->actionCamera_from_video_file->setChecked(!Settings::getCamera_videoFilePath().isEmpty()); } diff --git a/src/MainWindow.h b/src/MainWindow.h index 180a3667..b0b0e5d9 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -45,7 +45,7 @@ public slots: private slots: void loadObjects(); bool saveObjects(); - void addObject(); + void addObjectFromScene(); void addObjectsFromFiles(); void loadSceneFromFile(); void setupCameraFromVideoFile(); diff --git a/src/ObjWidget.cpp b/src/ObjWidget.cpp index 7c305ec6..c3eba4a2 100644 --- a/src/ObjWidget.cpp +++ b/src/ObjWidget.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -72,8 +73,12 @@ void ObjWidget::setupUi() graphicsView_->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); graphicsView_->setScene(new QGraphicsScene(graphicsView_)); + label_ = new QLabel(); + label_->setAlignment(Qt::AlignCenter); + this->setLayout(new QVBoxLayout(this)); this->layout()->addWidget(graphicsView_); + this->layout()->addWidget(label_); this->layout()->setContentsMargins(0,0,0,0); _menu = new QMenu(tr(""), this); @@ -232,6 +237,11 @@ void ObjWidget::setAlpha(int alpha) } } +void ObjWidget::setTextLabel(const QString & text) +{ + label_->setText(text); +} + void ObjWidget::setData(const std::vector & keypoints, const cv::Mat & descriptors, const IplImage * image, @@ -247,6 +257,7 @@ void ObjWidget::setData(const std::vector & keypoints, graphicsViewInitialized_ = false; detectorType_ = detectorType; descriptorType_ = descriptorType; + mouseCurrentPos_ = mousePressedPos_; // this will reset roi selection if(iplImage_) { cvReleaseImage(&iplImage_); @@ -270,6 +281,7 @@ void ObjWidget::setData(const std::vector & keypoints, { this->setupGraphicsView(); } + label_->setVisible(!image); } void ObjWidget::resetKptsColor() diff --git a/src/ObjWidget.h b/src/ObjWidget.h index d3894d1b..952d07fd 100644 --- a/src/ObjWidget.h +++ b/src/ObjWidget.h @@ -16,6 +16,7 @@ class QGraphicsView; class QGraphicsScene; class QGraphicsRectItem; class QGraphicsItem; +class QLabel; class ObjWidget : public QWidget { @@ -38,6 +39,7 @@ public: const IplImage * image, const QString & detectorType, const QString & descriptorType); + void setTextLabel(const QString & text); void resetKptsColor(); void setKptColor(int index, const QColor & color); void setGraphicsViewMode(bool on); @@ -104,6 +106,7 @@ private: QList rectItems_; bool graphicsViewInitialized_; int alpha_; + QLabel * label_; // menu stuff QString _savedFileName; diff --git a/src/ParametersToolBox.cpp b/src/ParametersToolBox.cpp index 07c76645..53cedc17 100644 --- a/src/ParametersToolBox.cpp +++ b/src/ParametersToolBox.cpp @@ -27,71 +27,61 @@ QWidget * ParametersToolBox::getParameterWidget(const QString & key) return this->findChild(key); } -void ParametersToolBox::resetCurrentPage() +void ParametersToolBox::resetPage(int index) { - const QObjectList & children = this->widget(this->currentIndex())->children(); + const QObjectList & children = this->widget(index)->children(); for(int j=0; jobjectName(); - QVariant value = Settings::getDefaultParameters().value(key, QVariant()); - if(value.isValid()) + // ignore only the nextObjID setting, to avoid problem with saved objects + if(key.compare(Settings::kGeneral_nextObjID()) != 0) { - if(qobject_cast(children.at(j))) + QVariant value = Settings::getDefaultParameters().value(key, QVariant()); + if(value.isValid()) { - ((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt()); + if(qobject_cast(children.at(j))) + { + ((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt()); + } + else if(qobject_cast(children.at(j))) + { + ((QSpinBox*)children.at(j))->setValue(value.toInt()); + } + else if(qobject_cast(children.at(j))) + { + ((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble()); + } + else if(qobject_cast(children.at(j))) + { + ((QCheckBox*)children.at(j))->setChecked(value.toBool()); + } + else if(qobject_cast(children.at(j))) + { + ((QLineEdit*)children.at(j))->setText(value.toString()); + } + Settings::setParameter(key, value); } - else if(qobject_cast(children.at(j))) - { - ((QSpinBox*)children.at(j))->setValue(value.toInt()); - } - else if(qobject_cast(children.at(j))) - { - ((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble()); - } - else if(qobject_cast(children.at(j))) - { - ((QCheckBox*)children.at(j))->setChecked(value.toBool()); - } - Settings::setParameter(key, value); } } } +void ParametersToolBox::resetCurrentPage() +{ + this->blockSignals(true); + this->resetPage(this->currentIndex()); + this->blockSignals(false); + emit parametersChanged(); +} + void ParametersToolBox::resetAllPages() { + this->blockSignals(true); for(int i=0; i< this->count(); ++i) { - const QObjectList & children = this->widget(i)->children(); - for(int j=0; jobjectName(); - // ignore only the nextObjID setting, to avoid problem with saved objects - if(key.compare(Settings::kGeneral_nextObjID()) != 0) - { - QVariant value = Settings::getDefaultParameters().value(key, QVariant()); - if(value.isValid()) - { - if(qobject_cast(children.at(j))) - { - ((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt()); - } - else if(qobject_cast(children.at(j))) - { - ((QSpinBox*)children.at(j))->setValue(value.toInt()); - } - else if(qobject_cast(children.at(j))) - { - ((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble()); - } - else if(qobject_cast(children.at(j))) - { - ((QCheckBox*)children.at(j))->setChecked(value.toBool()); - } - Settings::setParameter(key, value); - } - } - } + this->resetPage(i); } + this->blockSignals(false); + emit parametersChanged(); } void ParametersToolBox::setupUi() @@ -202,7 +192,7 @@ void ParametersToolBox::addParameter(QVBoxLayout * layout, { QLineEdit * widget = new QLineEdit(value, this); widget->setObjectName(key); - connect(widget, SIGNAL(textChanged(const QString &)), this, SLOT(changeParameter(const QString &))); + connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter())); addParameter(layout, key.split('/').last(), widget); } } @@ -292,6 +282,7 @@ void ParametersToolBox::changeParameter() { QDoubleSpinBox * doubleSpinBox = qobject_cast(sender()); QSpinBox * spinBox = qobject_cast(sender()); + QLineEdit * lineEdit = qobject_cast(sender()); if(doubleSpinBox) { Settings::setParameter(sender()->objectName(), doubleSpinBox->value()); @@ -300,6 +291,10 @@ void ParametersToolBox::changeParameter() { Settings::setParameter(sender()->objectName(), spinBox->value()); } + else if(lineEdit) + { + Settings::setParameter(sender()->objectName(), lineEdit->text()); + } emit parametersChanged(); } } diff --git a/src/ParametersToolBox.h b/src/ParametersToolBox.h index 2713975d..bf0b97da 100644 --- a/src/ParametersToolBox.h +++ b/src/ParametersToolBox.h @@ -39,6 +39,9 @@ private slots: void changeParameter(const int & value); void resetCurrentPage(); void resetAllPages(); + +private: + void resetPage(int index); }; #endif /* PARAMETERSTOOLBOX_H_ */ diff --git a/src/Settings.h b/src/Settings.h index 264f58c2..43c58956 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -53,8 +53,8 @@ typedef unsigned int uint; class Settings { PARAMETER(Camera, deviceId, int, 0); - PARAMETER(Camera, imageWidth, int, 640); - PARAMETER(Camera, imageHeight, int, 480); + PARAMETER(Camera, imageWidth, int, 0); + PARAMETER(Camera, imageHeight, int, 0); PARAMETER(Camera, imageRate, int, 2); // Hz PARAMETER(Camera, videoFilePath, QString, ""); @@ -127,6 +127,8 @@ class Settings PARAMETER(General, autoStartCamera, bool, false); PARAMETER(General, nextObjID, uint, 1); + PARAMETER(General, imageFormats, QString, "*.png *.jpg *.bmp *.tiff") + PARAMETER(General, videoFormats, QString, "*.avi *.m4v") PARAMETER(Homography, homographyComputed, bool, true); PARAMETER(Homography, ransacReprojThr, double, 1.0); diff --git a/src/ui/mainWindow.ui b/src/ui/mainWindow.ui index b5542f71..6f7a4a78 100644 --- a/src/ui/mainWindow.ui +++ b/src/ui/mainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 871 - 533 + 1104 + 497 @@ -130,7 +130,7 @@ 0 0 - 871 + 1104 22 @@ -147,7 +147,7 @@ Edit - + @@ -156,8 +156,7 @@ - - + @@ -208,7 +207,7 @@ 0 0 276 - 393 + 357 @@ -417,7 +416,7 @@ 0 0 274 - 425 + 389 @@ -456,9 +455,9 @@ Exit - + - Add object... + Add object from scene... @@ -506,14 +505,9 @@ Pause camera - + - Setup camera from video file... - - - - - Setup camera from video file... + Camera from video file...