QImage and Iplimage conversion more efficient display video

Source: Internet
Author: User
Tags sleep function

Compared with MFC, the signal slot mechanism of QT is slower than the signal mechanism of MFC, but because it can achieve cross-platform, so I summarize here may be a bit of use for some people.

0. Build Environment: OpenCV + QT 4.6

My experiment is based on VS2008, QT official although provide vs2008-add-in plug-ins, I do not use. The direct downloader compiles the library file to configure, OpenCV in the VS2008 below the configuration method Google is everywhere, here no longer complements. The first thing you need to do in VS2008 is that you need to make QT and OPENCV programs run separately. For QT in VS configuration is quite simple, there is a header file and the corresponding link library, to ensure that the call when the path is correct, generally there is no problem. People who use command line make programs should know that the IDE is nothing more than a layer of painted skin.

1. Display Image

Qwidget is the first subclass of Qobject, and using it to display images reduces unnecessary overhead. Start by customizing a qwidget you need:

Class
 Mywidget:public
 qwidget

{

  q_object

  public
:

    mywidget (const
 iplimage *img, Qwidget *parent = 0);

    ~mywidget ();

  Protected
:

    void
 paintevent (qpaintevent *e);

  Private
:

    iplimage* iplimg;

    QImage *qimg;

} ;

Need to draw an image, I overload paintevent (Qpaintevent *e), I use qpainter here to draw.

void
 Mywidget::p aintevent (qpaintevent *e)

{

    qpainter painter (this
);

    Painter.drawimage (Qpoint (5,5), *qimg);

}

DrawImage (Qpoint (5,5), qimg); the function is to draw the qimg at the upper-left vertex located at Qpoint (5,5).

There are two possible problems, the first one is that the picture is too small to be displayed, the widget is too large, and the last display is ugly. Then you can get the qimg in this function and then resize it. Another problem is that the qimage is used when drawing, not the Iplimage type. On this issue forum someone specifically wrote the Iplimage <-> qimage conversion Code, I do not repeat the practice here, one has been done, another in the efficiency of consideration, here provides another method.

Usually the students are using cvloadimage to read pictures, save in the iplimage inside, where this picture we save in IMG, and then through the IMG into Qwidget, and then I new a qimage

qimg = new
 QImage (Qsize (img->width,img->height), qimage::format_rgb888);

I'm assuming iplimg is in RGB format and each channel size is 8. Then create a iplimage file header

iplimg = Cvcreateimageheader (Cvsize (Img.width (), Img.height ()), 8, 3);

The difference between this iplimage and Qimage is that Qimage does not directly provide a way to create a header, you can create a qimage with only header data in the following ways

qimg = new
 QImage (Qsize (0,0), qimage::format_rgb888);

In addition, the two image matrix pixel arrangement is a little different, such as Iplimage in the BGR to the qimage should be RGB, of course, the single channel of Gray is the same, and thankfully the two pixel matrices are the same shape of the multidimensional array. This allows us to share this part of the data through pointers, one of the following methods:

Iplimg->imagedata = (char
*) qimg.bits ();

Will iplimg image matrix to qimg there, after we only need to iplimage use the function of OPENCV inside processing, in fact, directly in the processing of qimg inside the data. But now the image data is still inside the IMG, first have to get the data, and then put it in the iplimg and Qimg shared area, in addition, the color arrangement to qimage in the RGB order as the standard.

If
 (Img->origin = = Ipl_origin_tl)

{

	cvcopy (img,iplimg,0);

}

else


{

	cvflip (img,iplimg,0);

}



Cvcvtcolor (IPLIMG,IPLIMG,CV_BGR2RGB);

In fact, as long as the picture here can be shown. As shown in the following figure

Give the MyWidget.cpp complete code

#include "myWidget.h
"

#include <QtGui/QPainter>

#include <QtCore/QPoint>



mywidget:: Mywidget (const
 iplimage *img,qwidget *parent/* = 0 */
): Qwidget (parent)

{



 	qimg = new
 QImage (qsize (img->width,img->height),

 		qimage::format_rgb888);

	iplimg = Cvcreateimageheader (Cvsize (img->width,img->height),

		8,3);

	Iplimg->imagedata = (char
*) qimg->bits ();



	If
 (Img->origin = = Ipl_origin_tl)

	{

		cvcopy (img,iplimg,0);

	}

	else


	{

		cvflip (img,iplimg,0);

	}



	Cvcvtcolor (IPLIMG,IPLIMG,CV_BGR2RGB);



	This
->resize (img->width,img->height);



}



Mywidget::~mywidget ()

{

	cvreleaseimage (&iplimg);

	Delete
 qimg;

}



void
 Mywidget::p aintevent (qpaintevent *e)

{

	qpainter painter (this
);

	Painter.drawimage (Qpoint (0,0), *qimg);

}

The code that is invoked is simple:

int
 Main (int
 argc,char
* argv[])

{

	qapplication app (ARGC,ARGV);



	Iplimage *img = Cvloadimage ("460.jpg
", 1);

	If
 (img)

	{

		Mywidget *mw = new
 Mywidget (IMG);

		Mw->show ();

	}

	int
 re = App.exec ();

	Cvreleaseimage (&img);

	return
 re;

}

2. Play Video

Sometimes we need to deal with video files, such as AVI, and of course it's just an image sequence. When the sleep function is not working because of the multithreading mechanism of the QT runtime, the playback of the video file can be controlled by the qtimer provided by it. Before giving an example, you should wordy the signal/slot mechanism of QT. MFC inside the message map is very fast, but let a person involved in their deep reading will feel very obscure, QT through the signal/slot mechanism to achieve a message exchange. Using signal to evoke slot, such as clicking on the button's clicked () event is a signal, which can evoke other actions after this event occurs, as long as you connect the clicked message to the actual operating slot.

OpenCV inside the function can easily read video frames, if the use of widgets to play video, how to control the frame rate is a very clever place, I use a Qtimer control time (can be understood as frame rate), and periodically arouse the reading of video frame operation, The widget is then redrawn in this operation, or by imitating the previous method, using a qimage as a shared area for paintevent to display.

With the underlying image shown above, I'll change the code above to give an example:

MyWidget.h

#ifndef mywidget_h

#define MYWIDGET_H



#include <QtGui/QWidget>

#include <qtgui/qpaintevent >

#include <QtGui/QImage>

#include <QtCore/QTimer>

#include <cv.h>

#include 

MyWidget.cpp

#include "myWidget.h" #include <QtGui/QPainter> #include <QtCore/QPoint> mywidget::mywidget (const char

	*filename,qwidget *parent/* = 0/*: Qwidget (parent) {capture = Cvcapturefromfile (filename);

		if (capture) {frame = Cvqueryframe (capture);



		if (frame) this->resize (frame->width,frame->height);

		qimg = new QImage (Qsize (frame->width,frame->height), qimage::format_rgb888);

		iplimg = Cvcreateimageheader (Cvsize (frame->width,frame->height), 8,3);



		Iplimg->imagedata = (char *) qimg->bits ();

		Timer = new Qtimer (this);

		Timer->setinterval (30);

		Connect (timer,signal (timeout ()), this, SLOT (NextFrame ()));

	Timer->start ();

	} mywidget::~mywidget () {cvreleaseimage (&iplimg);

	Cvreleasecapture (&capture);

	Delete qimg;



Delete timer;

	} void Mywidget::p aintevent (qpaintevent *e) {qpainter painter (this);

Painter.drawimage (Qpoint (0,0), *qimg); } void Mywidget::NextFrame () {frame = Cvqueryframe (capture);

		if (frame) {if (Frame->origin = = Ipl_origin_tl) {cvcopy (frame,iplimg,0);

		else {cvflip (frame,iplimg,0);



		} cvcvtcolor (IPLIMG,IPLIMG,CV_BGR2RGB);



	This->update (); }

}

The main function inside the call

int
 Main (int
 argc,char
* argv[])

{

	qapplication app (ARGC,ARGV);



	char
 *filename = "Test.avi
";

	Mywidget *MW = new
 mywidget (filename);

	Mw->show ();



	int
 re = App.exec ();

	return
 re;

}


Because you can not see the screenshot, so do not take screenshots.

The latter program because it involves slots, so add a q_object macros, before compiling need to MyWidget.h program MOC

Like what:

MoC Mywidget.h–o Moc_mywidget.cpp

This will generate a. cpp file in the directory, add it to the source file together with make, or compile it into the source file list.

After you know how to use QT to display images and play video, it's easy to insert the code that handles the image in the code above. Display images in the constructor can be inserted in the processing code, of course, can also be processed in the PaintEvent function, playback video can be processed in the NextFrame function, some preprocessing can be completed in the constructor.

Compared to MFC's code, QT's code structure looks obvious and more graceful.

Original: http://bugway.appspot.com/?p=469802

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.