在QLabel上显示图像的Qt + OpenCV

3
我正在尝试捕获相机的实时视图,并将其重定向到QLabel中以显示。但只有一半的视图显示出来(见下图): Screenshot 左侧的窗口使用cv :: imshow()显示,运作完美。我在不同的线程中捕获Mat,然后发射一个带有Qimage作为参数的信号,并在槽中设置图像到QLabel中。
以下是代码:
while(true){
    cam >> mat;
    cv::imshow("name",mat);
    emit send_UIupdate(mat2qimage(mat));
}

在插槽设置中,将图像设置为Qlabel:

void Dialog::updateUI(const QImage &img){
    label->setPixmap(QPixmap::fromImage(img));
}

使用以下代码将Mat转换为QImage:
QImage camera::mat2qimage(const cv::Mat& mat) {
    cv::Mat rgb;
    cv::cvtColor(mat, rgb, CV_BGR2RGB);
    return QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, QImage::Format_RGB888);
}

有什么建议来解决这个问题吗?
4个回答

8

你可以尝试以下方式:

QImage MainWindow::putImage(const Mat& mat)
{
    // 8-bits unsigned, NO. OF CHANNELS=1
    if(mat.type()==CV_8UC1)
    {
        // Set the color table (used to translate colour indexes to qRgb values)
        QVector<QRgb> colorTable;
        for (int i=0; i<256; i++)
            colorTable.push_back(qRgb(i,i,i));
        // Copy input Mat
        const uchar *qImageBuffer = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8);
        img.setColorTable(colorTable);
        return img;
    }
    // 8-bits unsigned, NO. OF CHANNELS=3
    if(mat.type()==CV_8UC3)
    {
        // Copy input Mat
        const uchar *qImageBuffer = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return img.rgbSwapped();
    }
    else
    {
        qDebug() << "ERROR: Mat could not be converted to QImage.";
        return QImage();
    }
}

我使用QTimer进行调用。我从这里获得了它:http://code.google.com/p/qt-opencv-multithreaded/
希望这可以帮到你。

1
VideoCapture cap("video.avi");
Mat frame;
QImage img;
QPixmap pixel;
while(cap.isOpened())
{
    cap >> frame;
    img= QImage((uchar*) frame.data, frame.cols, frame.rows, frame2.step, QImage::Format_RGB888);
    pixel = QPixmap::fromImage(img);
    ui->label->setPixmap(pixel);
}    

0

我认为问题来自以下代码:

while(true){
    cam >> mat;
    cv::imshow("name",mat);
    emit send_UIupdate(mat2qimage(mat));
}

你的应用程序因为你一直在循环并且没有让Qt进行必要的处理而冻结了。 参考链接:QT do while loop

你知道,Qt有自己的事件循环,所以,如果你在函数中使用while(true)循环,Qt可能永远无法接收事件。

尝试移除while循环,像@CTZStef建议的那样使用Qtimer。

以下源代码可能对你有所帮助: http://blog.csdn.net/robertkun/article/details/9030929


我认为 while 循环不会导致你所说的问题。他提到 Mat 在一个单独的线程中被捕获。 - may5694

0
在mat2qimage函数中,您应该返回一个副本。
返回翻译的文本:

return QImage((const unsigned char*)(rgb.data), rgb.cols, rgb.rows, Image::Format_RGB888).copy();


1
我很难理解这个回答怎么解决了原来的问题?你能解释一下吗? - Stewart_R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接