#include <QtGui/QFileDialog>#include <QtGui/QMessageBox>#include "image.h"#include "image_op.h"#include "rgba.h"#include "calibrateWidget.hh"#include "crossWidget.hh"#include "mandoWizard.hh"#include "selectRectWidget.hh"#include "tools.hh"#include "videoWidget.hh"#include "image_funcs.h"#define CALIBDELAY 900using namespace mimas;using namespace std;MandoWizard::MandoWizard( QWidget *parent, Qt::WFlags f ):QDialog( parent, f ), videoTimer(0), calibrateWidget(NULL), calibTimer(0),segmentationTimer(0), pointerTimer(0){ui.setupUi( this );// Finalise GUI.videoWidget = new VideoWidget;ui.videoDisplay->setWidget( videoWidget );searchPatternWidget = new VideoWidget;ui.searchPatternDisplay->setWidget( searchPatternWidget );projectedPatternWidget = new VideoWidget;ui.projectedPatternDisplay->setWidget( projectedPatternWidget );calibFrameWidget = new CrossWidget;ui.calibFrameDisplay->setWidget( calibFrameWidget );referenceImageWidget = new SelectRectWidget;ui.referenceImageDisplay->setWidget( referenceImageWidget );segmentedWidget = new CrossWidget;ui.segmentedDisplay->setWidget( segmentedWidget );// Connect signals and slots.connect( ui.brightnessSlider, SIGNAL(valueChanged(int)),this, SLOT(setCameraParameters()) );connect( ui.hueSlider, SIGNAL(valueChanged(int)),this, SLOT(setCameraParameters()) );connect( ui.colourSlider, SIGNAL(valueChanged(int)),this, SLOT(setCameraParameters()) );connect( ui.contrastSlider, SIGNAL(valueChanged(int)),this, SLOT(setCameraParameters()) );connect( ui.shutterSlider, SIGNAL(valueChanged(int)),this, SLOT(setCameraParameters()) );connect( ui.gainSlider, SIGNAL(valueChanged(int)),this, SLOT(setCameraParameters()) );connect( ui.balanceSlider, SIGNAL(valueChanged(int)),this, SLOT(setCameraParameters()) );connect( ui.searchPatternButton, SIGNAL(clicked()),this, SLOT(loadSearchPattern()) );connect( ui.projectedPatternButton, SIGNAL(clicked()),this, SLOT(loadProjectedPattern()) );connect( ui.previousButton, SIGNAL(clicked()),this, SLOT(previousPage()) );connect( ui.nextButton, SIGNAL(clicked()),this, SLOT(nextPage()) );connect( ui.cancelButton, SIGNAL(clicked()),this, SLOT(reject()) );connect( ui.finishButton, SIGNAL(clicked()),this, SLOT(accept()) );connect( ui.reconnectButton, SIGNAL(clicked()),this, SLOT(reconnectCamera()) );connect( ui.calibrateButton, SIGNAL(clicked()),this, SLOT(calibrate()) );connect( ui.calibrateSlider, SIGNAL(valueChanged(int)),this, SLOT(displayCalibFrame(int)) );connect( ui.differenceCheckBox, SIGNAL(toggled(bool)),this, SLOT(displayDifference(bool)) );connect( ui.grabButton, SIGNAL(clicked()),this, SLOT(grabReferenceImage()) );connect( referenceImageWidget, SIGNAL(rectDefined(bool)),this, SLOT(updateEnabled()) );connect( ui.thresholdSlider, SIGNAL(valueChanged(int)),this, SLOT(setThreshold(int)) );connect( ui.sigmaSpinBox, SIGNAL(valueChanged(double)),this, SLOT(setSigma(double)) );connect( ui.rangeSlider, SIGNAL(valueChanged(int)),this, SLOT(setRange(int)) );// Load default patterns.searchPatternWidget->setImage( qImageToMimasImage( QImage( ":/images/searchPattern.png" ) ) );projectedPatternWidget->setImage( qImageToMimasImage( QImage( ":/images/projectedPattern.png" ) ) );showPage( 0 );}void MandoWizard::previousPage(){showPage( ui.stackedWidget->currentIndex() - 1 );}void MandoWizard::nextPage(){showPage( ui.stackedWidget->currentIndex() + 1 );}void MandoWizard::showPage( int index ){// Check index.assert( index >= 0 );assert( index < ui.stackedWidget->count() );// Update title.switch ( index ) {case 0:ui.titleLabel->setText( "Adjust camera position" );break;case 1:ui.titleLabel->setText( "Select calibration patterns" );break;case 2:ui.titleLabel->setText( "Perform calibration" );break;case 3:ui.titleLabel->setText( "Capture image and select reference image for ""colour segmentation and select" );break;case 4:ui.titleLabel->setText( "Set parameters for pointer recognition" );break;case 5:ui.titleLabel->setText( "Set parameters for mouse-clicks" );break;default:assert( false );};// Show page.ui.stackedWidget->setCurrentIndex( index );// Enable/disable controls.updateEnabled();// Set up video display.setupVideo();}void MandoWizard::setupVideo(void){int index = ui.stackedWidget->currentIndex();if ( index == 0 ) {if ( videoTimer == 0 )videoTimer = startTimer( 0 );} elseif ( videoTimer != 0 ) {killTimer( videoTimer );videoTimer = 0;};if ( index == 4 ) {if ( segmentationTimer == 0 )segmentationTimer = startTimer( 0 );} elseif ( segmentationTimer != 0 ) {killTimer( segmentationTimer );segmentationTimer = 0;};if ( index == 5 ) {if ( pointerTimer == 0 )pointerTimer = startTimer( 0 );} elseif ( pointerTimer != 0 ) {killTimer( pointerTimer );pointerTimer = 0;};}void MandoWizard::updateEnabled(void){// Enable/disable controls.int index = ui.stackedWidget->currentIndex();ui.previousButton->setEnabled( index > 0 );ui.finishButton->setEnabled( index == 5 );ui.brightnessSlider->setEnabled( (bool)v4lInput );ui.hueSlider->setEnabled( (bool)v4lInput );ui.colourSlider->setEnabled( (bool)v4lInput );ui.contrastSlider->setEnabled( (bool)v4lInput );ui.shutterSlider->setEnabled( (bool)dc1394Input );ui.gainSlider->setEnabled( (bool)dc1394Input );ui.balanceSlider->setEnabled( (bool)dc1394Input );switch ( index ) {case 0:ui.nextButton->setEnabled( (bool)input );break;case 1:ui.nextButton->setEnabled( searchPatternWidget->getImage().initialised() &&projectedPatternWidget->getImage().initialised() );break;case 2: {bool calibFinished;if ( cameraProjectorCalibration )calibFinished = cameraProjectorCalibration->getNumCalibFrames() >= 5;elsecalibFinished = false;ui.nextButton->setEnabled( calibFinished );ui.selectImageLabel->setEnabled( calibFinished );ui.calibrateSlider->setEnabled( calibFinished );ui.differenceCheckBox->setEnabled( calibFinished );break;}case 3:ui.nextButton->setEnabled( referenceImageWidget->isRectDefined() );if ( !referenceImageWidget->isRectDefined() )pointerRecognition.reset();break;case 4:ui.nextButton->setEnabled( true );break;case 5:ui.nextButton->setEnabled( false );break;default:assert( false );};}void MandoWizard::loadSearchPattern(){image< rgba< unsigned char > > img;if ( loadImage( "Load search pattern", img ) ) {searchPatternWidget->setImage( img );cameraProjectorCalibration.reset();pointerRecognition.reset();updateEnabled();};}void MandoWizard::loadProjectedPattern(){image< rgba< unsigned char > > img;if ( loadImage( "Load projected pattern", img ) ) {projectedPatternWidget->setImage( img );cameraProjectorCalibration.reset();pointerRecognition.reset();updateEnabled();};}void MandoWizard::reconnectCamera(){input.reset();v4lInput.reset();dc1394Input.reset();cameraProjectorCalibration.reset();pointerRecognition.reset();referenceImageWidget->clearSelection();assert( ui.stackedWidget->currentIndex() == 0 );setupVideo();}void MandoWizard::displayCalibFrame( int index ){displayCalibResult( index, ui.differenceCheckBox->isChecked() );}void MandoWizard::displayDifference( bool diff ){displayCalibResult( ui.calibrateSlider->value(), diff );}void MandoWizard::grabReferenceImage(){referenceImageWidget->setImage( grabColourFrame() );updateEnabled();}void MandoWizard::setThreshold( int _value ){assert( pointerRecognition );assert( ui.thresholdSlider->minimum() == 0 );pointerRecognition->setThreshold( 0.25 * _value / ui.thresholdSlider->maximum() );}void MandoWizard::setRange( int _value ){assert( pointerRecognition );pointerRecognition->setTrackingRange( _value );}void MandoWizard::setSigma( double _value ){pointerRecognition->setSigma( _value );}void MandoWizard::displayCalibResult( int index, bool diff ){assert( cameraProjectorCalibration );assert( index >= 0 &&index < cameraProjectorCalibration->getNumCalibFrames() + 1 );if ( index == 0 ) {calibFrameWidget->setImage( cameraProjectorCalibration->getBackgroundFrame() );calibFrameWidget->clearCross();} else {if ( diff )calibFrameWidget->setImage( normalise( image< int >( cameraProjectorCalibration->getCalibFrame( index - 1 ) ) -image< int >( cameraProjectorCalibration->getBackgroundFrame() ), 0, 255 ) );elsecalibFrameWidget->setImage( cameraProjectorCalibration->getCalibFrame( index - 1 ) );calibFrameWidget->setCross( cameraProjectorCalibration->getCalibPointPair( index - 1 ).second );};}bool MandoWizard::loadImage( const char *title,image< rgba< unsigned char > > &img ){bool retVal = false;try {QString s = QFileDialog::getOpenFileName( this, title,".","Images (*.png *.jpg);;""All Files (*)" );if ( s != QString::null ) {img = qImageToMimasImage( QImage( s ) );MMERROR( img.initialised(), mimasexception, ,"Error loading file \"" << (const char *)s.toLatin1()<< "\"." );retVal = true;};} catch ( exception &e ) {QMessageBox::critical( this, "Error loading image", e.what() );};return retVal;}void MandoWizard::timerEvent( QTimerEvent *e ){if ( e->timerId() == videoTimer ) {try {videoWidget->setImage( grabColourFrame( false ) );assert( ui.stackedWidget->currentIndex() == 0 );} catch ( exception &e ) {assert( videoTimer != 0 );killTimer( videoTimer );videoTimer = 0;videoWidget->setImage( image< rgba< unsigned char > >() );input.reset();v4lInput.reset();dc1394Input.reset();ui.errorLabel->setText( e.what() );updateEnabled();};} else if ( e->timerId() == calibTimer ) {assert( calibrateWidget != NULL );killTimer( calibTimer );calibTimer = 0;if ( !calibrateWidget->isVisible() ) {delete calibrateWidget;calibrateWidget = NULL;cameraProjectorCalibration.reset();pointerRecognition.reset();} else {switch ( calibState ) {case Init:calibrateWidget->setPattern( 0 );calibState = First;break;case First:cameraProjectorCalibration->setBackgroundFrame( grabFrame() );calibrateWidget->setPattern( 1 );calibState = Second;break;case Second:cameraProjectorCalibration->addCalibFrame( grabFrame(), calibrateWidget->getPos( 1 ) );calibrateWidget->setPattern( 2 );calibState = Third;break;case Third:cameraProjectorCalibration->addCalibFrame( grabFrame(), calibrateWidget->getPos( 2 ) );calibrateWidget->setPattern( 3 );calibState = Fourth;break;case Fourth:cameraProjectorCalibration->addCalibFrame( grabFrame(), calibrateWidget->getPos( 3 ) );calibrateWidget->setPattern( 4 );calibState = Fifth;break;case Fifth:cameraProjectorCalibration->addCalibFrame( grabFrame(), calibrateWidget->getPos( 4 ) );calibrateWidget->setPattern( 5 );calibState = Closing;break;case Closing:cameraProjectorCalibration->addCalibFrame( grabFrame(), calibrateWidget->getPos( 5 ) );calibrateWidget->setPattern( 0 );calibState = Finished;break;default:calibState = Init;displayCalibFrame( ui.calibrateSlider->value() );// Get size of screen.// This is only done at this point, because directly after// initialisation of calibrateWidget, calibrateWidget->width() and// ..->height() will not have the correct valuies.screenW = calibrateWidget->width();screenH = calibrateWidget->height();delete calibrateWidget;calibrateWidget = NULL;updateEnabled();};if ( calibState != Init )calibTimer=startTimer( CALIBDELAY );};} else if ( e->timerId() == segmentationTimer ) {if ( !pointerRecognition ) {assert( cameraProjectorCalibration );pointerRecognition =PointerRecognitionPtr( new PointerRecognition( cameraProjectorCalibration,referenceImageWidget->selectedImage() ) );setThreshold( ui.thresholdSlider->value() );setSigma( ui.sigmaSpinBox->value() );setRange( ui.rangeSlider->value() );pointerRecognition->setClip( 0, 0, screenW, screenH );};Vector camPos( 3 ), pos( 3 );image< rgba< unsigned char > > frame( grabColourFrame() );if ( pointerRecognition->findPointer( frame, camPos, pos ) )segmentedWidget->setCross( camPos );elsesegmentedWidget->clearCross();segmentedWidget->setImage( pointerRecognition->getMinX(),pointerRecognition->getMinY(),frame.getWidth(),frame.getHeight(),pointerRecognition->getSegmentedImage() );} else if ( e->timerId() == pointerTimer ) {Vector camPos( 3 ), pos( 3 );image< rgba< unsigned char > > frame( grabColourFrame() );if ( pointerRecognition->findPointer( frame, camPos, pos ) ) {// Display *d = XOpenDisplay( NULL );// XTestFakeMotionEvent( d, DefaultScreen( d ),// (int)pos[0], (int)pos[1], 0 );// XCloseDisplay( d );ui.mouseXLCD->setSegmentStyle( QLCDNumber::Flat );ui.mouseYLCD->setSegmentStyle( QLCDNumber::Flat );ui.mouseXLCD->display( (int)pos[0] );ui.mouseYLCD->display( (int)pos[1] );} else {ui.mouseXLCD->setSegmentStyle( QLCDNumber::Outline );ui.mouseYLCD->setSegmentStyle( QLCDNumber::Outline );};} elseQDialog::timerEvent( e );}MandoWizard::VideoPtr MandoWizard::camera(void)throw (mimas::mimasexception){if ( !input ) {if ( ui.cameraStack->currentIndex() == 0 ) {__u16 norm;switch ( ui.modeBox->currentIndex() ) {case 0:norm = VIDEO_MODE_PAL;break;case 1:norm = VIDEO_MODE_NTSC;break;case 2:norm = VIDEO_MODE_SECAM;break;case 3:norm = VIDEO_MODE_AUTO;break;default:norm = VIDEO_MODE_PAL;};v4lInput =V4LInputPtr( new V4LInput( (const char *)ui.v4lDeviceEdit->text().toLatin1(),ui.v4lChannelSpinBox->value(),-1, -1, norm ) );input = v4lInput;setCameraParameters();ui.errorLabel->setText( "" );updateEnabled();} else {dc1394Input =DC1394InputPtr( new DC1394Input( (const char *)ui.dc1394DeviceEdit->text().toLatin1(),ui.dc1394NodeSpinBox->value(),ui.dc1394ChannelSpinBox->value() ) );input = dc1394Input;dc1394_feature_info shutter = dc1394Input->get_feature( FEATURE_SHUTTER );ui.shutterSlider->setMinimum( shutter.min );ui.shutterSlider->setMaximum( shutter.max );ui.shutterSlider->setValue( shutter.value );dc1394_feature_info gain = dc1394Input->get_feature( FEATURE_GAIN );ui.gainSlider->setMinimum( gain.min );ui.gainSlider->setMaximum( gain.max );ui.gainSlider->setValue( gain.value );dc1394_feature_info balance = dc1394Input->get_feature( FEATURE_WHITE_BALANCE );ui.balanceSlider->setMinimum( balance.min );ui.balanceSlider->setMaximum( balance.max );ui.balanceSlider->setValue( ( balance.min + balance.max ) / 2 );setCameraParameters();ui.errorLabel->setText( "" );updateEnabled();};};return input;}void MandoWizard::setCameraParameters(void){if ( v4lInput )v4lInput->setSensivity( ui.brightnessSlider->value(),ui.hueSlider->value(),ui.colourSlider->value(),ui.contrastSlider->value() );if ( dc1394Input ) {dc1394Input->set_feature_value( FEATURE_SHUTTER,ui.shutterSlider->value() );dc1394Input->set_feature_value( FEATURE_GAIN,ui.gainSlider->value() );dc1394Input->set_feature_value( FEATURE_WHITE_BALANCE,ui.balanceSlider->value() );};}image< unsigned char > MandoWizard::grabFrame(void)throw (mimasexception){return image< unsigned char >( grabColourFrame() );}image< rgba< unsigned char > > MandoWizard::grabColourFrame( bool twice )throw (mimasexception){image< rgba< unsigned char > > retVal;// discard old frame.if ( twice ) (*camera()) >> retVal;(*camera()) >> retVal;return retVal;}void MandoWizard::calibrate(){if ( calibrateWidget != NULL ) {delete calibrateWidget;calibrateWidget = NULL;};assert( projectedPatternWidget->getImage().initialised() );calibrateWidget = new CalibrateWidget( image< unsigned char >( projectedPatternWidget->getImage() ),this );assert( searchPatternWidget->getImage().initialised() );cameraProjectorCalibration =CameraProjectorCalibrationPtr( new CameraProjectorCalibration( searchPatternWidget->getImage() ) );pointerRecognition.reset();calibrateWidget->setWindowFlags( Qt::Dialog );// calibrateWidget->setWindowModality( Qt::WindowModal );calibrateWidget->showFullScreen();updateEnabled();if ( calibTimer != 0 ) {killTimer( calibTimer );calibTimer = 0;};calibState = Init;calibTimer = startTimer( CALIBDELAY );}void MandoWizard::startDrag(){ui.statusLabel->setText( "<b>button pressed</b>" );}void MandoWizard::stopDrag(){ui.statusLabel->setText( "button released" );}