Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to push an OpenCV image viewing window into a QT GUI with Visual studio?

I want to create a GUI with 2 rectangles for viewing videos (one where you see the input video, one where you see the post-processed video).

I want it to be integrated into a QT-made GUI, but I want these video areas to be populated from OpenCV, as an alternative to OpenCV's cv::nameWindow method.

How can I do this?

like image 543
zebra Avatar asked Jan 14 '12 18:01

zebra


2 Answers

The basic workflow to do what you desire is:

  1. Open the video with OpenCV API (cvCreateFileCapture, for example)
  2. Grab IplImage frames from video (cvQueryFrame)
  3. Convert them to QImage (see attached code bellow)
  4. Show QImage on within a QLabel (QLabel::setPixmap and QPixmap::fromImage)
  5. Loop the frame update (using a QTimer, for example, with video framerate)

Code to convert IplImage to QImage (assuming RGB32Bits images):

QImage *IplImageToQImage(IplImage *input)
{
    if (!input)
        return 0;

    QImage image(input->width, input->height, QImage::Format_RGB32);

    uchar* pBits = image.bits();
    int nBytesPerLine = image.bytesPerLine();

    for (int n = 0; n < input->height; n++)
    {
        for (int m = 0; m < input->width; m++)
        {
            CvScalar s = cvGet2D(input, n, m);
            QRgb value = qRgb((uchar)s.val[2], (uchar)s.val[1], (uchar)s.val[0]);

            uchar* scanLine = pBits + n * nBytesPerLine;
            ((uint*)scanLine)[m] = value;
        }
    }

    return image;
}

The understanding of the code above should be straightforward. Any doubts just let us know.

This "low level" option allows you to manipulate each individual frame before displaying it. If you just want to display a video via Qt, you can use the Phonon framework.

like image 55
borges Avatar answered Nov 15 '22 19:11

borges


Here is code that converts a cv::Mat into a QImage. Methods are for 24bit RGB or grayscale floating point, respectively.

QImage Mat2QImage(const cv::Mat3b &src) {
        QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
        for (int y = 0; y < src.rows; ++y) {
                const cv::Vec3b *srcrow = src[y];
                QRgb *destrow = (QRgb*)dest.scanLine(y);
                for (int x = 0; x < src.cols; ++x) {
                        destrow[x] = qRgba(srcrow[x][2], srcrow[x][1], srcrow[x][0], 255);
                }
        }
        return dest;
}


QImage Mat2QImage(const cv::Mat_<double> &src)
{
        double scale = 255.0;
        QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
        for (int y = 0; y < src.rows; ++y) {
                const double *srcrow = src[y];
                QRgb *destrow = (QRgb*)dest.scanLine(y);
                for (int x = 0; x < src.cols; ++x) {
                        unsigned int color = srcrow[x] * scale;
                        destrow[x] = qRgba(color, color, color, 255);
                }
        }
        return dest;
}

Then, you can use the QImage inside a Qt widget. See borges' answer.

like image 42
ypnos Avatar answered Nov 15 '22 20:11

ypnos