diff --git a/src/AddObjectDialog.cpp b/src/AddObjectDialog.cpp index 22d31a25..f8073899 100644 --- a/src/AddObjectDialog.cpp +++ b/src/AddObjectDialog.cpp @@ -142,7 +142,7 @@ void AddObjectDialog::setState(int state) else if(state == kSelectFeatures) { disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - camera_->stop(); + camera_->pause(); ui_->pushButton_cancel->setEnabled(true); ui_->pushButton_back->setEnabled(true); @@ -169,7 +169,7 @@ void AddObjectDialog::setState(int state) else if(state == kVerifySelection) { disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); - camera_->stop(); + camera_->pause(); ui_->pushButton_cancel->setEnabled(true); ui_->pushButton_back->setEnabled(true); diff --git a/src/Camera.cpp b/src/Camera.cpp index 74d0ae0f..bb20d4f3 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -6,6 +6,7 @@ #include #include #include "Settings.h" +#include Camera::Camera(QObject * parent) : QObject(parent), @@ -30,6 +31,11 @@ void Camera::stop() } } +void Camera::pause() +{ + stopTimer(); +} + void Camera::takeImage() { if(capture_) @@ -73,11 +79,23 @@ bool Camera::start() { if(!capture_) { - capture_ = cvCaptureFromCAM(Settings::getCamera_deviceId()); - if(capture_) + QString videoFile = Settings::getCamera_videoFilePath(); + if(QFile::exists(videoFile)) { - cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_WIDTH, double(Settings::getCamera_imageWidth())); - cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_HEIGHT, double(Settings::getCamera_imageHeight())); + capture_ = cvCaptureFromAVI(videoFile.toStdString().c_str()); + if(!capture_) + { + printf("WARNING: Cannot open file \"%s\". If you want to disable loading automatically this video file, clear the Camera/videoFilePath parameter. By default, webcam will be used instead of the file.\n", videoFile.toStdString().c_str()); + } + } + if(!capture_) + { + capture_ = cvCaptureFromCAM(Settings::getCamera_deviceId()); + if(capture_ && Settings::getCamera_imageWidth() && Settings::getCamera_imageHeight()) + { + cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_WIDTH, double(Settings::getCamera_imageWidth())); + cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_HEIGHT, double(Settings::getCamera_imageHeight())); + } } } if(!capture_) diff --git a/src/Camera.h b/src/Camera.h index ecb8edb3..299a575f 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -19,6 +19,8 @@ public: virtual void stop(); virtual bool isRunning() {return cameraTimer_.isActive();} + void pause(); + signals: void imageReceived(const cv::Mat & image); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index c1de1ed4..503f8ff0 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -71,6 +71,7 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) : connect(ui_->pushButton_updateObjects, SIGNAL(clicked()), this, SLOT(updateObjects())); ui_->actionStop_camera->setEnabled(false); + ui_->actionPause_camera->setEnabled(false); ui_->actionSave_objects->setEnabled(false); // Actions @@ -79,12 +80,20 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) : connect(ui_->actionLoad_scene_from_file, SIGNAL(triggered()), this, SLOT(loadSceneFromFile())); connect(ui_->actionStart_camera, SIGNAL(triggered()), this, SLOT(startProcessing())); connect(ui_->actionStop_camera, SIGNAL(triggered()), this, SLOT(stopProcessing())); + connect(ui_->actionPause_camera, SIGNAL(triggered()), this, SLOT(pauseProcessing())); 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_->actionAbout, SIGNAL(triggered()), aboutDialog_ , SLOT(exec())); connect(ui_->actionRestore_all_default_settings, SIGNAL(triggered()), ui_->toolBox, SLOT(resetAllPages())); + 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()); + if(Settings::getGeneral_autoStartCamera()) { // Set 1 msec to see state on the status bar. @@ -237,6 +246,21 @@ 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()) + { + Settings::setCamera_videoFilePath(fileName); + ui_->toolBox->updateParameter(Settings::kCamera_videoFilePath()); + if(camera_->isRunning()) + { + this->stopProcessing(); + this->startProcessing(); + } + } +} + void MainWindow::showObject(ObjWidget * obj) { if(obj) @@ -257,6 +281,7 @@ void MainWindow::showObject(ObjWidget * obj) id = obj->id()+1; Settings::setGeneral_nextObjID(id); } + ui_->toolBox->updateParameter(Settings::kGeneral_nextObjID()); QLabel * title = new QLabel(QString("%1 (%2)").arg(obj->id()).arg(QString::number(obj->keypoints().size())), this); QLabel * detectorDescriptorType = new QLabel(QString("%1/%2").arg(obj->detectorType()).arg(obj->descriptorType()), this); @@ -346,13 +371,27 @@ void MainWindow::updateData() { if(dim >= 0 && objects_.at(i)->descriptors().cols != dim) { - QMessageBox::critical(this, tr("Error"), tr("Descriptors of the objects are not all the same size!\nObjects opened must have all the same size (and from the same descriptor extractor).")); + if(this->isVisible()) + { + QMessageBox::critical(this, tr("Error"), tr("Descriptors of the objects are not all the same size!\nObjects opened must have all the same size (and from the same descriptor extractor).")); + } + else + { + printf("ERROR: Descriptors of the objects are not all the same size! Objects opened must have all the same size (and from the same descriptor extractor)."); + } return; } dim = objects_.at(i)->descriptors().cols; if(type >= 0 && objects_.at(i)->descriptors().type() != type) { - QMessageBox::critical(this, tr("Error"), tr("Descriptors of the objects are not all the same type!\nObjects opened must have been processed by the same descriptor extractor.")); + if(this->isVisible()) + { + QMessageBox::critical(this, tr("Error"), tr("Descriptors of the objects are not all the same type!\nObjects opened must have been processed by the same descriptor extractor.")); + } + else + { + printf("ERROR: Descriptors of the objects are not all the same type! Objects opened must have been processed by the same descriptor extractor."); + } return; } type = objects_.at(i)->descriptors().type(); @@ -383,6 +422,7 @@ void MainWindow::startProcessing() { connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); ui_->actionStop_camera->setEnabled(true); + ui_->actionPause_camera->setEnabled(true); ui_->actionStart_camera->setEnabled(false); ui_->actionLoad_scene_from_file->setEnabled(false); ui_->label_timeRefreshRate->setVisible(true); @@ -391,7 +431,14 @@ void MainWindow::startProcessing() else { this->statusBar()->clearMessage(); - QMessageBox::critical(this, tr("Camera error"), tr("Camera initialization failed! (with device %1)").arg(Settings::getCamera_deviceId())); + if(this->isVisible()) + { + QMessageBox::critical(this, tr("Camera error"), tr("Camera initialization failed! (with device %1)").arg(Settings::getCamera_deviceId())); + } + else + { + printf("ERROR: Camera initialization failed! (with device %d)", Settings::getCamera_deviceId()); + } } } @@ -403,10 +450,26 @@ void MainWindow::stopProcessing() camera_->stop(); } ui_->actionStop_camera->setEnabled(false); + ui_->actionPause_camera->setEnabled(false); ui_->actionStart_camera->setEnabled(true); ui_->actionLoad_scene_from_file->setEnabled(true); } +void MainWindow::pauseProcessing() +{ + ui_->actionStop_camera->setEnabled(true); + ui_->actionPause_camera->setEnabled(true); + ui_->actionStart_camera->setEnabled(false); + if(camera_->isRunning()) + { + camera_->pause(); + } + else + { + camera_->start(); + } +} + void MainWindow::update(const cv::Mat & image) { // reset objects color @@ -707,4 +770,7 @@ void MainWindow::notifyParametersChanged() this->update(image); 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()); } diff --git a/src/MainWindow.h b/src/MainWindow.h index e0ae63b0..c30b0d28 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -40,6 +40,7 @@ protected: public slots: void startProcessing(); void stopProcessing(); + void pauseProcessing(); private slots: void loadObjects(); @@ -47,6 +48,7 @@ private slots: void addObject(); void addObjectsFromFiles(); void loadSceneFromFile(); + void setupCameraFromVideoFile(); void removeObject(ObjWidget * object); void update(const cv::Mat & image); void updateObjects(); diff --git a/src/ObjWidget.cpp b/src/ObjWidget.cpp index d8d00413..7c305ec6 100644 --- a/src/ObjWidget.cpp +++ b/src/ObjWidget.cpp @@ -403,6 +403,12 @@ void ObjWidget::load(QDataStream & streamPtr) descriptors = cv::Mat(rows, cols, type, data.data()).clone(); streamPtr >> image_; this->setData(kpts, descriptors, 0, detectorType, descriptorType); + if(iplImage_) + { + cvReleaseImage(&iplImage_); + iplImage_ = 0; + } + iplImage_ = QImage2Ipl(image_.toImage()); //this->setMinimumSize(image_.size()); } diff --git a/src/ParametersToolBox.cpp b/src/ParametersToolBox.cpp index e89cadfb..07c76645 100644 --- a/src/ParametersToolBox.cpp +++ b/src/ParametersToolBox.cpp @@ -123,6 +123,36 @@ void ParametersToolBox::setupUi() } } +void ParametersToolBox::updateParameter(const QString & key) +{ + QWidget * widget = this->findChild(key); + QString type = Settings::getParametersType().value(key); + if(type.compare("QString") == 0) + { + ((QLineEdit*)widget)->setText(Settings::getParameter(key).toString()); + } + else if(type.compare("int") == 0) + { + ((QSpinBox*)widget)->setValue(Settings::getParameter(key).toInt()); + } + else if(type.compare("uint") == 0) + { + ((QSpinBox*)widget)->setValue(Settings::getParameter(key).toInt()); + } + else if(type.compare("double") == 0) + { + ((QDoubleSpinBox*)widget)->setValue(Settings::getParameter(key).toDouble()); + } + else if(type.compare("float") == 0) + { + ((QDoubleSpinBox*)widget)->setValue(Settings::getParameter(key).toDouble()); + } + else if(type.compare("bool") == 0) + { + ((QCheckBox*)widget)->setChecked(Settings::getParameter(key).toBool()); + } +} + void ParametersToolBox::addParameter(QVBoxLayout * layout, const QString & key, const QVariant & value) @@ -216,11 +246,11 @@ void ParametersToolBox::addParameter(QVBoxLayout * layout, if(def>0) { - widget->setMaximum(def*10); + widget->setMaximum(def*1000000); } else if(def<0) { - widget->setMinimum(def*10); + widget->setMinimum(def*1000000); widget->setMaximum(0); } widget->setValue(value); @@ -253,6 +283,7 @@ void ParametersToolBox::changeParameter(const QString & value) if(sender()) { Settings::setParameter(sender()->objectName(), value); + emit parametersChanged(); } } void ParametersToolBox::changeParameter() diff --git a/src/ParametersToolBox.h b/src/ParametersToolBox.h index 3e30405e..2713975d 100644 --- a/src/ParametersToolBox.h +++ b/src/ParametersToolBox.h @@ -20,6 +20,7 @@ public: void setupUi(); QWidget * getParameterWidget(const QString & key); + void updateParameter(const QString & key); private: void addParameter(QVBoxLayout * layout, const QString & key, const QVariant & value); diff --git a/src/Settings.h b/src/Settings.h index 762d4190..264f58c2 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -56,6 +56,7 @@ class Settings PARAMETER(Camera, imageWidth, int, 640); PARAMETER(Camera, imageHeight, int, 480); PARAMETER(Camera, imageRate, int, 2); // Hz + PARAMETER(Camera, videoFilePath, QString, ""); //List format : [Index:item0;item1;item3;...] PARAMETER(Detector, Type, QString, "7:Dense;Fast;GoodFeaturesToTrack;Mser;Orb;Sift;Star;Surf"); diff --git a/src/qtipl.cpp b/src/qtipl.cpp index aa3749aa..6f0b65f9 100644 --- a/src/qtipl.cpp +++ b/src/qtipl.cpp @@ -15,10 +15,10 @@ QImage Ipl2QImage(const IplImage *newImage) int y; char* data = newImage->imageData; - qtemp= QImage(newImage->width, newImage->height,QImage::Format_RGB32 ); - for( y = 0; y < newImage->height; y++, data +=newImage->widthStep ) + qtemp= QImage(newImage->width, newImage->height,QImage::Format_RGB32); + for( y = 0; y < newImage->height; ++y, data +=newImage->widthStep ) { - for( x = 0; x < newImage->width; x++) + for( x = 0; x < newImage->width; ++x) { uint *p = (uint*)qtemp.scanLine (y) + x; *p = qRgb(data[x * newImage->nChannels+2], data[x * newImage->nChannels+1],data[x * newImage->nChannels]); @@ -31,3 +31,33 @@ QImage Ipl2QImage(const IplImage *newImage) } return qtemp; } + +IplImage * QImage2Ipl(const QImage & image) +{ + IplImage * iplTmp = 0; + if(!image.isNull() && image.depth() == 32 && image.format() == QImage::Format_RGB32) + { + int x; + int y; + + // assume RGB (3 channels) + int channels = 3; + iplTmp = cvCreateImage(cvSize(image.width(), image.height()), IPL_DEPTH_8U, channels); + char* data = iplTmp->imageData; + for( y = 0; y < image.height(); ++y, data+=iplTmp->widthStep) + { + for( x = 0; x < image.width(); ++x) + { + QRgb rgb = image.pixel(x, y); + data[x * channels+2] = qRed(rgb); //r + data[x * channels+1] = qGreen(rgb); //g + data[x * channels] = qBlue(rgb); //b + } + } + } + else + { + printf("failed to convert image : depth=%d(!=32) format=%d(!=%d)\n", image.depth(), image.format(), QImage::Format_RGB32); + } + return iplTmp; +} diff --git a/src/qtipl.h b/src/qtipl.h index 0cd28f10..a05a17f4 100644 --- a/src/qtipl.h +++ b/src/qtipl.h @@ -8,6 +8,10 @@ #include #include +// IplImage to QImage QImage Ipl2QImage(const IplImage *newImage); +// QImage to IplImage +IplImage * QImage2Ipl(const QImage & image); + #endif diff --git a/src/ui/mainWindow.ui b/src/ui/mainWindow.ui index f97582eb..cfeeee8c 100644 --- a/src/ui/mainWindow.ui +++ b/src/ui/mainWindow.ui @@ -153,8 +153,12 @@ + + + + @@ -495,6 +499,21 @@ Load scene from file... + + + Pause camera + + + + + Setup camera from video file... + + + + + Setup camera from video file... + +