Videoausgabe über QLabel

Alles rund um die Programmierung mit Qt
Antworten
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Videoausgabe über QLabel

Beitrag von Saul »

Hi Leute,
schön das es ein deutschsprachiges Qt Forum gibt und ich freue mich daran teilhaben zu dürfen =) Ich beschäftige mich jetzt seit einer Woche mit Qt und möchte gerne zur Übung eine Webcamausgabe mittels Qt realisieren. Dazu greife ich mit OpenCV auf meine Webcam zu und übergebe das OpenCV IplImage an das QImage. Schließlich soll das QImage auf einem QLabel ausgegeben werden.

Die Übergabe des IplImage an das QImage funktioniert soweit. Woran es bei mir hapert ist die Ausgabe des QImage auf dem QLabel. Irgendetwas funktioniert nicht so wie ich es gerne hätte.

Mein Code dazu sieht so aus:

// main.cpp

Code: Alles auswählen

#include "kamera.h"
#include <QtGui/QApplication>

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	Kamera w;
	w.show();
	Kamera *test = new Kamera();
	test->showWebcam();
	return a.exec();
}
// kamera.h

Code: Alles auswählen

#ifndef KAMERA_H
#define KAMERA_H

#include <QtGui/QMainWindow>
#include "ui_kamera.h"
#include "cv.h"
#include "highgui.h"

class Kamera : public QMainWindow
{
	Q_OBJECT

public:
	Kamera(QWidget *parent = 0, Qt::WFlags flags = 0);
	~Kamera();

private:
	Ui::KameraClass ui;

public slots:
	void showWebcam();
};

#endif // KAMERA_H
// kamera.cpp

Code: Alles auswählen

#include "kamera.h"

Kamera::Kamera(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);

	connect(ui.actionStart, SIGNAL(triggered()), this, SLOT(showWebcam()));
}

Kamera::~Kamera()
{

}

void Kamera::showWebcam()
{
	IplImage *image;
	CvCapture *capture = cvCaptureFromCAM(0);

	int esc = 0;
	while(true)
	{
		image = cvQueryFrame(capture);
		cvCvtColor(image, image,CV_BGR2RGB);

		QImage qimg((const uchar *)image->imageData, image->width, image->height, QImage::Format_RGB888);
		ui.label->setPixmap(QPixmap::fromImage(qimg));
		
		esc= cvWaitKey(10);
		if (esc== 27) break;
	}
	cvReleaseCapture(&capture);
}
In dem kamera.ui befindet sich eigentlich nur ein QLabel namens "label" mit einer größe von 640x480 Pixeln.

Wenn ich das Programm übersetze erscheint keine Ausgabe durch das QLabel. Das QImage ist aber komplett bzw. einwandfrei. Scheint also irgendetwas mit der Funktion setPixmap nicht zu klappen. Wäre furchtbar nett wenn sich dazu mal jemand äußern könnte.
Gruß, Saul
softwaremaker
Beiträge: 149
Registriert: 1. April 2009 19:25

qtapps

Beitrag von softwaremaker »

Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Beitrag von Saul »

Das hab ich schon gefunden, doch leider bin ich daraus auch nicht schlauer geworden =(
Er macht ja vom Prinzip auch nix anderes als das OpenCV bild in ein QImage umzuwandeln und es dann über setPixmap auszugeben. Irgendwie find ich den Fehler bei mir nicht.
softwaremaker
Beiträge: 149
Registriert: 1. April 2009 19:25

keine schleife sonder timer

Beitrag von softwaremaker »

Auf jeden Fall würde ich keine while-Schleife verwenden, sondern einen Timer.
Denn diese "frist" die CPU-Zeit und QLabel wird nicht gezeichnet.
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Beitrag von Saul »

Hi softwaremaker,
vielen Dank für deinen Tip!
Hab in der Qt Doku ein Beispiel gefunden, das mir eigentlich weiterhelfen sollte: http://doc.trolltech.com/4.7/widgets-wiggly.html

Was mir aber irgendwie noch unklar ist, wie ich eine Schleife durch einen Timer ersetzen kann. Heißt sicher das die Funktion zum zeichnen nach einer bestimmten Zeit bzw. wenigen ms immer wieder erneut aufgerufen wird. Aber woher weiß ich in welchen Abständen dies am besten geschehen soll?
softwaremaker
Beiträge: 149
Registriert: 1. April 2009 19:25

frames pro sekunde

Beitrag von softwaremaker »

Na sagen wir mal du willst 20 Bilder pro Sekunde (Kino: 24 fps, TV: 25 fps), dann müsstest du einen Timer mit 50 ms (1s / 20 fps) nutzen.

Die fps deiner Webcam:
int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Beitrag von Saul »

Oh man, ich bin da echt überfordert =(
Hab nun schon den ganzen Abend dran gebastelt, aber nichts lauffähiges zusammen bekommen. Anstatt nachzudenken, probiere ich seit Stunden nur noch aus. Dabei weiß ich schon gar nicht mehr was ich getestet hab und was nicht ... Manchmal kann programmieren echt demotivierend sein.

Also im großen und ganzen habe ich es versucht über einen Timer zu lösen. Wobei es wohl noch eine weitere Möglichkeit über Threads geben soll, durch die man die Bilder mittels connect(... , SIGNAL(), this, SLOT(showWebcam())); anzeigen lassen kann. Keine Ahnung wie das gemeint ist und welche Variante nun geeigneter sein soll.

Der Grundgedanke ist doch eigentlich "nur" die Webcam mit dem QLabel zu synchronisieren. Mittels Timer habe ich versucht die zeichen Funktion aufzurufen. Dachte mir das eigentlich so:
// kamera.h

Code: Alles auswählen

private:
			QBasicTimer timer;
// kamera.cpp

Code: Alles auswählen

void WebCam::timerEvent(QTimerEvent*) 
{
	displayWebcam();
}
In dem Beispiel Programm das softwaremaker gepostet hat, habe ich nirgends einen Aufruf der Funktion void timerEvent(QTimerEvent*); gefunden. Normaler weise müsste doch irgendwo ein Aufruf zu finden sein der den Timer startet und dieser wiederum die Funktion ausführt.
softwaremaker hat geschrieben:schau mal hier:
http://qt-apps.org/content/show.php/Qt+ ... tent=89995
Naja, ich werd mich jetzt erstmal ins Bett werfen und die Nacht drüber schlafen. Schönen Abend noch.
Gruß, Saul
softwaremaker
Beiträge: 149
Registriert: 1. April 2009 19:25

Beitrag von softwaremaker »

in dem Beispiel nutzt er die Timer-Funktion des QObjects
An alternative to using QTimer is to call QObject::startTimer() for your object and reimplement the QObject::timerEvent() event handler in your class (which must inherit QObject). The disadvantage is that timerEvent() does not support such high-level features as single-shot timers or signals.
Wenn du eine von QObject abgeleitete Klasse hast, brauchst du nur die timerEvent-Methode anlegen und startTimer(..) aufrufen.

oder den klassischen weg, über connect(....) und mytimer->start(..)
Saul
Beiträge: 29
Registriert: 17. Juni 2011 09:41

Beitrag von Saul »

Heyho,
da ich mich noch nicht wieder an den Timer rangetraut habe, hab ich mal kurz was anderes ausprobiert. Und zwar hab ich bei der Funktion showWebcam() mal die kleine Zeile ui.label->repaint(); hinter dem setPixmap hinzugefügt. Und siehe da, ich sehe endlich ein kontinuierliches Bild meiner Webcam. Läuft soweit ganz gut und auch flüssig. Ich kann das Programm nur nicht bedienen. Weder durch die ESC-Taste, noch durch das Klicken auf das X zum schließen des Programmes. Da hilf nur noch der Task Manager.

Heißt wohl, das ich wohl oder übel nicht an dem Timer vorbei komme =(
Antworten