[Tutorial] Nokia Qt4 & OpenCV 2.1 C++

Visualizzare un flusso video o un’immagine su un’interfaccia grafica di propria realizzazione non è una delle operazioni più banali da realizzare se non si conoscono le basi di programmazione di GUI. Questo tutorial spiegherà nel modo più semplice possibile le operazioni da seguire per visualizzare immagini da OpenCV 2.1 in una GUI realizzata con Qt4 utilizzando il framework C++ introdotto in OpenCV dalla versione 2.0.
Il tutorial è stato realizzato utilizzando l’ambiente di sviluppo “Eclipse Helios” con installato il PlugIn “Qt Eclipse Integrator”. Il compilatore utilizzato è MinGW nella versione fornita con l’installazione “completa” di Qt SDK.
Molti concetti di programmazione Qt e di installazione dell’ambiente di sviluppo Eclipse e OpenCV sono dati per scontati, per approfondire consiglio la lettura del libro C++ GUI Programming with Qt4 (2nd Edition), la cui prima edizione è disponibile online gratuitamente.

Per chi è abituato ad utilizzare OpenCV con il linguaggio C deve innanzitutto abbandonare l’idea della differenza che esisteva tra CvMat e IplImage. OpenCV in modalità C++ utilizza un oggetto unico per la rappresentazione di immagini e dati matriciali: cv::Mat.

Ma partiamo dall’inizio… o meglio dalla fine: l’interfaccia dell’applicazione, la GUI

OpenCV Qt4 GUI

OpenCV Qt4 GUI

La GUI sarà composta da una zona di rendering delle immagini e da alcuni pulsanti di “azione” posti sulla sinistra. Per il rendering delle immagini verrà adottata la “tecnica della QLabel”: non verrà realizzato un Widget apposito, ma si utilizzeranno le caratteristiche del Widget Qt QLabel.

Al flusso video proveniente dalla Webcam potrà essere applicato un filtro di Canny:

Canny

Canny

o un filtro di estrazione dei segmenti tramite algoritmo di Hough probabilistico:

Hough

Hough

il progetto completo può essere scaricato qui.

C++ GUI Programming with Qt 4 (2nd Edition)

Questo è un video dell’applicazione di esempio:

Per poter renderizzare un’immagine in una finestra di dialogo Qt è sufficiente creare un oggetto QLabel e utilizzare il seguente codice:

void TestOpenCV_GUI::on_loadImageButton_clicked()
{
	mImage.release(); // Reinizializzazione dell'immagine

	Mat tmpImg = imread( "puzzle.bmp" );
	cvtColor( tmpImg, mImage, CV_BGR2RGB);

	QImage tmp( (uchar*)mImage.data, mImage.cols, mImage.rows, mImage.step,
			QImage::Format_RGB888 );

	ui.imageFrame->setPixmap( QPixmap::fromImage( tmp ) );
	ui.fpsLabel->setText( "puzzle.bmp loaded");
}

Il rendering dello stream dalla webcam si ottiene grazie a un oggetto “QTimer“:
QTimer mCameraTimer;
al suo setting nella funzione di gestione del click sul pulsante “Start/Stop Camera”:

void TestOpenCV_GUI::on_cameraButton_clicked()
{
	if( !mCameraRunning )
	{
		mCap.open( CV_CAP_ANY );
		if( !mCap.isOpened() )
			return;

		bool res = mCap.set( CV_CAP_PROP_FRAME_WIDTH, 640.0 );
		res = mCap.set( CV_CAP_PROP_FRAME_HEIGHT, 480.0 );
		res = mCap.set( CV_CAP_PROP_FPS, 100.0 );

		mCameraRunning = true;

		mCameraTimer.start( 20 ); // 50 fps (richiesti)
		connect( &mCameraTimer, SIGNAL( timeout() ),
				 this, SLOT( on_cameraTimerTimeout() ) );

		ui.cameraButton->setText( "Stop Camera" );

		ui.loadImageButton->setEnabled( false );
		ui.cannyButton->setEnabled( false );
	}
	else
	{
		if( !mCap.isOpened() )
			return;

		mCameraTimer.stop();

		mCap.release();

		mCameraRunning = false;
		ui.cameraButton->setText( "Start Camera" );

		ui.loadImageButton->setEnabled( true );
		ui.cannyButton->setEnabled( true );
	}
}

e alla funzione di gestione dell’evento “Timeout” del timer:

void TestOpenCV_GUI::on_cameraTimerTimeout()
{
	if( mCameraRunning && mCap.isOpened() )
	{
		mCap >> mImage; // Nuovo frame dalla camera

		// ---> Calcolo e visualizzazione FPS
		int time = mTime.elapsed();
		mTime.restart();
		mFPS = (1.0/(double)time)*1000.0;
		QString str = QString( "FPS: %1" ).arg( mFPS );
		ui.fpsLabel->setText( str );
		// < --- Calcolo e visualizzazione FPS

		cvtColor( mImage, mImage, CV_BGR2RGB);

		if( ui.houghCheckBox->checkState() == Qt::Checked )
		{
			Mat gray, color;

			cv::cvtColor( mImage, gray, CV_RGB2GRAY );
			GaussianBlur( gray, gray, Size(5, 5), 2, 2 );
			cv::Canny( gray, gray, 20, 60, 3 );

			vector lines;
		    HoughLinesP( gray, lines, 1, CV_PI/180, 80, 30, 10 );

			mImage.copyTo( color );
			for( size_t i = 0; i < lines.size(); i++ )
			{
				line( color, Point(lines[i][0], lines[i][1]),
					Point(lines[i][2], lines[i][3]), Scalar(0,0,255), 2, 8 );
			}

			QImage tmp( (uchar*)color.data, color.cols, color.rows,
					color.step, QImage::Format_RGB888  );
			ui.imageFrame->setPixmap( QPixmap::fromImage( tmp ) );
		}
		else if( ui.cannyCheckBox->checkState() == Qt::Checked )
		{
			Mat gray;
			cv::cvtColor( mImage, gray, CV_RGB2GRAY );
			GaussianBlur( gray, gray, Size(9, 9), 2, 2 );

			cv::Canny( gray, gray, 20, 60, 3 );

			QImage tmp( (uchar*)gray.data, gray.cols, gray.rows,
					gray.step, QImage::Format_Indexed8  );
			ui.imageFrame->setPixmap( QPixmap::fromImage( tmp ) );
		}
		else
		{

			QImage tmp( (uchar*)mImage.data, mImage.cols, mImage.rows,
					mImage.step,
					QImage::Format_RGB888 );
			ui.imageFrame->setPixmap( QPixmap::fromImage( tmp ) );
		}
	}
}

Vorrei farvi notare la semplicità del rendering di immagini RGB o in bianco/nero in Qt.

Se osservete le righe di codice 36 e 44 noterete che per le immagini a colori ho utilizzato
QImage::Format_RGB888
mentre per quelle in bianco/nero
QImage::Format_Indexed8
Tutto il rimanente codice è identico!


Per quanto riguarda la realizzazione della GUI vi rimando al libro che vi ho consigliato sopra… una trentina di pagine di lettura e partirete come razzi.

Il tutorial è terminato, spero vi sia stato utile nel qual caso ricordatevi di offrirmi un caffè.
Per ogni dubbio, domanda, critica non esitate a inviare commenti utilizzando l’apposito thread del forum.

No tags for this post.

6 Responses to [Tutorial] Nokia Qt4 & OpenCV 2.1 C++

  1. Markus scrive:

    Great and simple code! Thank you very much!
    First time that I found one which ran almost out of the box (Mac OS X with Qt 4.7 and OpenCV 2.2 installed via MacPorts).

    To compile it under Linux/Mac OS X just add:

    unix|macx {
    INCLUDEPATH += /opt/local/include /usr/local/include

    LIBS += -L/opt/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui

    TARGET += release
    }

    One Problem: When I use the CANNY, the picture is distorted, red, green, and half the size and two times in the frame instead of black/white.
    My Webcam is 640x480.

    Any help / idea would be great!!!

  2. [...] installiert unter Mac OS X via MacPorts. Der Sourcecode wurde auf dieser (italienischen) Seite gefunden. Es muss nur noch herausgefunden werden, warum der Canny-Algorithmus nicht so läuft, wie er [...]

  3. Myzhar scrive:

    Canny filter works on greyscale images and result itself is in greyscale format.
    On Windows Format_Indexed8 is the right way to render greyscale images, I don’t the correct type for Mac, sorry.

  4. Inprimus scrive:

    To the publisher of the document: WOW!! Can’t thank you enough. This was a great tutorial for getting a complete opencv Newbie started. I was able to adapt your code to be able to output a greyscale image and a colour image at the same time. I am trying to implement motion and event detection. What libraries should I be looking at to achieve this? Thanks in advance for any hints.

    @Markus Thanks for the tip, it tidied up my include path a lot.

  5. Myzhar scrive:

    Hi Inprimus, thank you for your beautiful words.
    To implement motion and event detection take a look at these pages of OpenCV manual:
    - http://opencv.willowgarage.com/documentation/cpp/video_motion_analysis_and_object_tracking.html
    - http://opencv.willowgarage.com/documentation/cpp/ml_statistical_models.html?highlight=statmodel#CvStatModel

  6. Inprimus scrive:

    @Myzhar If you’re ever in England, drop me a mail. I owe you several beers and a meal. :)

Lascia un Commento

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *

*

Questo sito supporta SyntaxHighlighter attraverso WP SyntaxHighlighter. E' possibile evidenziare il tuo codice.

Come evidenziare il codice: Incolla il codice nei form di commento, selezionalo e premi il pulsante linguaggio sottostante. In questo modo il codice sarà racchiuso tra i tag <pre> e verrà formattato in modo corretto.

C | C++ |

È possibile utilizzare questi tag ed attributi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">

Powered by WordPress | Designed by: Email Search