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)
{
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);

View File

@ -6,6 +6,7 @@
#include <stdio.h>
#include <opencv2/imgproc/imgproc_c.h>
#include "Settings.h"
#include <QtCore/QFile>
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_)

View File

@ -19,6 +19,8 @@ public:
virtual void stop();
virtual bool isRunning() {return cameraTimer_.isActive();}
void pause();
signals:
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()));
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());
}

View File

@ -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();

View File

@ -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());
}

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,
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()

View File

@ -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);

View File

@ -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");

View File

@ -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;
}

View File

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

View File

@ -153,8 +153,12 @@
<addaction name="actionLoad_scene_from_file"/>
<addaction name="separator"/>
<addaction name="actionStart_camera"/>
<addaction name="actionPause_camera"/>
<addaction name="actionStop_camera"/>
<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"/>
</widget>
<widget class="QMenu" name="menuView">
@ -495,6 +499,21 @@
<string>Load scene from file...</string>
</property>
</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>
<customwidgets>
<customwidget>