New feature: we can setup the camera to use a video file intead of the webcam.

Fixed a crash when user did "Update Objects" with loaded objects.

git-svn-id: http://find-object.googlecode.com/svn/trunk/find_object@76 620bd6b2-0a58-f614-fd9a-1bd335dccda9
This commit is contained in:
matlabbe 2012-01-30 03:16:30 +00:00
parent 465e2d846e
commit 0e3b934316
12 changed files with 194 additions and 14 deletions

View File

@ -142,7 +142,7 @@ void AddObjectDialog::setState(int state)
else if(state == kSelectFeatures) else if(state == kSelectFeatures)
{ {
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
camera_->stop(); camera_->pause();
ui_->pushButton_cancel->setEnabled(true); ui_->pushButton_cancel->setEnabled(true);
ui_->pushButton_back->setEnabled(true); ui_->pushButton_back->setEnabled(true);
@ -169,7 +169,7 @@ void AddObjectDialog::setState(int state)
else if(state == kVerifySelection) else if(state == kVerifySelection)
{ {
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &))); disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
camera_->stop(); camera_->pause();
ui_->pushButton_cancel->setEnabled(true); ui_->pushButton_cancel->setEnabled(true);
ui_->pushButton_back->setEnabled(true); ui_->pushButton_back->setEnabled(true);

View File

@ -6,6 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include <opencv2/imgproc/imgproc_c.h> #include <opencv2/imgproc/imgproc_c.h>
#include "Settings.h" #include "Settings.h"
#include <QtCore/QFile>
Camera::Camera(QObject * parent) : Camera::Camera(QObject * parent) :
QObject(parent), QObject(parent),
@ -30,6 +31,11 @@ void Camera::stop()
} }
} }
void Camera::pause()
{
stopTimer();
}
void Camera::takeImage() void Camera::takeImage()
{ {
if(capture_) if(capture_)
@ -71,15 +77,27 @@ void Camera::takeImage()
bool Camera::start() bool Camera::start()
{ {
if(!capture_)
{
QString videoFile = Settings::getCamera_videoFilePath();
if(QFile::exists(videoFile))
{
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_) if(!capture_)
{ {
capture_ = cvCaptureFromCAM(Settings::getCamera_deviceId()); capture_ = cvCaptureFromCAM(Settings::getCamera_deviceId());
if(capture_) 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_WIDTH, double(Settings::getCamera_imageWidth()));
cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_HEIGHT, double(Settings::getCamera_imageHeight())); cvSetCaptureProperty(capture_, CV_CAP_PROP_FRAME_HEIGHT, double(Settings::getCamera_imageHeight()));
} }
} }
}
if(!capture_) if(!capture_)
{ {
printf("Failed to create a capture object!\n"); printf("Failed to create a capture object!\n");

View File

@ -19,6 +19,8 @@ public:
virtual void stop(); virtual void stop();
virtual bool isRunning() {return cameraTimer_.isActive();} virtual bool isRunning() {return cameraTimer_.isActive();}
void pause();
signals: signals:
void imageReceived(const cv::Mat & image); void imageReceived(const cv::Mat & image);

View File

@ -71,6 +71,7 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) :
connect(ui_->pushButton_updateObjects, SIGNAL(clicked()), this, SLOT(updateObjects())); connect(ui_->pushButton_updateObjects, SIGNAL(clicked()), this, SLOT(updateObjects()));
ui_->actionStop_camera->setEnabled(false); ui_->actionStop_camera->setEnabled(false);
ui_->actionPause_camera->setEnabled(false);
ui_->actionSave_objects->setEnabled(false); ui_->actionSave_objects->setEnabled(false);
// Actions // Actions
@ -79,12 +80,20 @@ MainWindow::MainWindow(Camera * camera, QWidget * parent) :
connect(ui_->actionLoad_scene_from_file, SIGNAL(triggered()), this, SLOT(loadSceneFromFile())); connect(ui_->actionLoad_scene_from_file, SIGNAL(triggered()), this, SLOT(loadSceneFromFile()));
connect(ui_->actionStart_camera, SIGNAL(triggered()), this, SLOT(startProcessing())); connect(ui_->actionStart_camera, SIGNAL(triggered()), this, SLOT(startProcessing()));
connect(ui_->actionStop_camera, SIGNAL(triggered()), this, SLOT(stopProcessing())); 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_->actionExit, SIGNAL(triggered()), this, SLOT(close()));
connect(ui_->actionSave_objects, SIGNAL(triggered()), this, SLOT(saveObjects())); connect(ui_->actionSave_objects, SIGNAL(triggered()), this, SLOT(saveObjects()));
connect(ui_->actionLoad_objects, SIGNAL(triggered()), this, SLOT(loadObjects())); 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_->actionAbout, SIGNAL(triggered()), aboutDialog_ , SLOT(exec()));
connect(ui_->actionRestore_all_default_settings, SIGNAL(triggered()), ui_->toolBox, SLOT(resetAllPages())); 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()) if(Settings::getGeneral_autoStartCamera())
{ {
// Set 1 msec to see state on the status bar. // 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) void MainWindow::showObject(ObjWidget * obj)
{ {
if(obj) if(obj)
@ -257,6 +281,7 @@ void MainWindow::showObject(ObjWidget * obj)
id = obj->id()+1; id = obj->id()+1;
Settings::setGeneral_nextObjID(id); 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 * 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); QLabel * detectorDescriptorType = new QLabel(QString("%1/%2").arg(obj->detectorType()).arg(obj->descriptorType()), this);
@ -345,14 +370,28 @@ void MainWindow::updateData()
for(int i=0; i<objects_.size(); ++i) for(int i=0; i<objects_.size(); ++i)
{ {
if(dim >= 0 && objects_.at(i)->descriptors().cols != dim) if(dim >= 0 && objects_.at(i)->descriptors().cols != dim)
{
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).")); 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; return;
} }
dim = objects_.at(i)->descriptors().cols; dim = objects_.at(i)->descriptors().cols;
if(type >= 0 && objects_.at(i)->descriptors().type() != type) if(type >= 0 && objects_.at(i)->descriptors().type() != type)
{
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.")); 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; return;
} }
type = objects_.at(i)->descriptors().type(); 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 &))); connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
ui_->actionStop_camera->setEnabled(true); ui_->actionStop_camera->setEnabled(true);
ui_->actionPause_camera->setEnabled(true);
ui_->actionStart_camera->setEnabled(false); ui_->actionStart_camera->setEnabled(false);
ui_->actionLoad_scene_from_file->setEnabled(false); ui_->actionLoad_scene_from_file->setEnabled(false);
ui_->label_timeRefreshRate->setVisible(true); ui_->label_timeRefreshRate->setVisible(true);
@ -391,8 +431,15 @@ void MainWindow::startProcessing()
else else
{ {
this->statusBar()->clearMessage(); this->statusBar()->clearMessage();
if(this->isVisible())
{
QMessageBox::critical(this, tr("Camera error"), tr("Camera initialization failed! (with device %1)").arg(Settings::getCamera_deviceId())); 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());
}
}
} }
void MainWindow::stopProcessing() void MainWindow::stopProcessing()
@ -403,10 +450,26 @@ void MainWindow::stopProcessing()
camera_->stop(); camera_->stop();
} }
ui_->actionStop_camera->setEnabled(false); ui_->actionStop_camera->setEnabled(false);
ui_->actionPause_camera->setEnabled(false);
ui_->actionStart_camera->setEnabled(true); ui_->actionStart_camera->setEnabled(true);
ui_->actionLoad_scene_from_file->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) void MainWindow::update(const cv::Mat & image)
{ {
// reset objects color // reset objects color
@ -707,4 +770,7 @@ void MainWindow::notifyParametersChanged()
this->update(image); this->update(image);
ui_->label_timeRefreshRate->setVisible(false); 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());
} }

View File

@ -40,6 +40,7 @@ protected:
public slots: public slots:
void startProcessing(); void startProcessing();
void stopProcessing(); void stopProcessing();
void pauseProcessing();
private slots: private slots:
void loadObjects(); void loadObjects();
@ -47,6 +48,7 @@ private slots:
void addObject(); void addObject();
void addObjectsFromFiles(); void addObjectsFromFiles();
void loadSceneFromFile(); void loadSceneFromFile();
void setupCameraFromVideoFile();
void removeObject(ObjWidget * object); void removeObject(ObjWidget * object);
void update(const cv::Mat & image); void update(const cv::Mat & image);
void updateObjects(); void updateObjects();

View File

@ -403,6 +403,12 @@ void ObjWidget::load(QDataStream & streamPtr)
descriptors = cv::Mat(rows, cols, type, data.data()).clone(); descriptors = cv::Mat(rows, cols, type, data.data()).clone();
streamPtr >> image_; streamPtr >> image_;
this->setData(kpts, descriptors, 0, detectorType, descriptorType); this->setData(kpts, descriptors, 0, detectorType, descriptorType);
if(iplImage_)
{
cvReleaseImage(&iplImage_);
iplImage_ = 0;
}
iplImage_ = QImage2Ipl(image_.toImage());
//this->setMinimumSize(image_.size()); //this->setMinimumSize(image_.size());
} }

View File

@ -123,6 +123,36 @@ void ParametersToolBox::setupUi()
} }
} }
void ParametersToolBox::updateParameter(const QString & key)
{
QWidget * widget = this->findChild<QWidget*>(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, void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key, const QString & key,
const QVariant & value) const QVariant & value)
@ -216,11 +246,11 @@ void ParametersToolBox::addParameter(QVBoxLayout * layout,
if(def>0) if(def>0)
{ {
widget->setMaximum(def*10); widget->setMaximum(def*1000000);
} }
else if(def<0) else if(def<0)
{ {
widget->setMinimum(def*10); widget->setMinimum(def*1000000);
widget->setMaximum(0); widget->setMaximum(0);
} }
widget->setValue(value); widget->setValue(value);
@ -253,6 +283,7 @@ void ParametersToolBox::changeParameter(const QString & value)
if(sender()) if(sender())
{ {
Settings::setParameter(sender()->objectName(), value); Settings::setParameter(sender()->objectName(), value);
emit parametersChanged();
} }
} }
void ParametersToolBox::changeParameter() void ParametersToolBox::changeParameter()

View File

@ -20,6 +20,7 @@ public:
void setupUi(); void setupUi();
QWidget * getParameterWidget(const QString & key); QWidget * getParameterWidget(const QString & key);
void updateParameter(const QString & key);
private: private:
void addParameter(QVBoxLayout * layout, const QString & key, const QVariant & value); void addParameter(QVBoxLayout * layout, const QString & key, const QVariant & value);

View File

@ -56,6 +56,7 @@ class Settings
PARAMETER(Camera, imageWidth, int, 640); PARAMETER(Camera, imageWidth, int, 640);
PARAMETER(Camera, imageHeight, int, 480); PARAMETER(Camera, imageHeight, int, 480);
PARAMETER(Camera, imageRate, int, 2); // Hz PARAMETER(Camera, imageRate, int, 2); // Hz
PARAMETER(Camera, videoFilePath, QString, "");
//List format : [Index:item0;item1;item3;...] //List format : [Index:item0;item1;item3;...]
PARAMETER(Detector, Type, QString, "7:Dense;Fast;GoodFeaturesToTrack;Mser;Orb;Sift;Star;Surf"); PARAMETER(Detector, Type, QString, "7:Dense;Fast;GoodFeaturesToTrack;Mser;Orb;Sift;Star;Surf");

View File

@ -15,10 +15,10 @@ QImage Ipl2QImage(const IplImage *newImage)
int y; int y;
char* data = newImage->imageData; char* data = newImage->imageData;
qtemp= QImage(newImage->width, newImage->height,QImage::Format_RGB32 ); qtemp= QImage(newImage->width, newImage->height,QImage::Format_RGB32);
for( y = 0; y < newImage->height; y++, data +=newImage->widthStep ) 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; uint *p = (uint*)qtemp.scanLine (y) + x;
*p = qRgb(data[x * newImage->nChannels+2], data[x * newImage->nChannels+1],data[x * newImage->nChannels]); *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; 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;
}

View File

@ -8,6 +8,10 @@
#include <QtGui/QImage> #include <QtGui/QImage>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
// IplImage to QImage
QImage Ipl2QImage(const IplImage *newImage); QImage Ipl2QImage(const IplImage *newImage);
// QImage to IplImage
IplImage * QImage2Ipl(const QImage & image);
#endif #endif

View File

@ -153,8 +153,12 @@
<addaction name="actionLoad_scene_from_file"/> <addaction name="actionLoad_scene_from_file"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionStart_camera"/> <addaction name="actionStart_camera"/>
<addaction name="actionPause_camera"/>
<addaction name="actionStop_camera"/> <addaction name="actionStop_camera"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionSetup_camera_from_video_file"/>
<addaction name="actionSetup_camera_from_video_file_2"/>
<addaction name="separator"/>
<addaction name="actionRestore_all_default_settings"/> <addaction name="actionRestore_all_default_settings"/>
</widget> </widget>
<widget class="QMenu" name="menuView"> <widget class="QMenu" name="menuView">
@ -495,6 +499,21 @@
<string>Load scene from file...</string> <string>Load scene from file...</string>
</property> </property>
</action> </action>
<action name="actionPause_camera">
<property name="text">
<string>Pause camera</string>
</property>
</action>
<action name="actionSetup_camera_from_video_file">
<property name="text">
<string>Setup camera from video file...</string>
</property>
</action>
<action name="actionSetup_camera_from_video_file_2">
<property name="text">
<string>Setup camera from video file...</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>