cv::Mat 到 QImage 的奇怪行为

Posted

技术标签:

【中文标题】cv::Mat 到 QImage 的奇怪行为【英文标题】:cv::Mat to QImage strange behavior 【发布时间】:2012-11-17 22:02:01 【问题描述】:

我正在使用 (how to convert an opencv cv::Mat to qimage) 中建议的代码在我的 Qt 应用程序中显示 cv::Mat。但是,我得到了奇怪的结果。黑色部分显示为黑色,但所有其他值都反转。

转换代码:

QImage ImgConvert::matToQImage(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;

显示代码:

void MainWindow::redraw()

    static QImage image = ImgConvert::matToQImage(im);

    static QGraphicsPixmapItem item( QPixmap::fromImage(image));
    static QGraphicsScene* scene = new QGraphicsScene;
    scene->addItem(&item);

    ui->graphicsView->setScene(scene);
    ui->graphicsView->repaint();

现在我正在使用if(color&gt;0) color = 255-color; 来纠正这种影响,但我更愿意了解它的来源。

另外,第二个小问题:如果我删除 redraw() 中的 static 声明,当方法退出时,图像会立即从内存中删除。这是解决此问题的最佳方法吗?如果我显示多个帧,是否会产生任何意外的副作用?

【问题讨论】:

内部 opencv::Mat 是 BGR 而 QImage ARGB32 是 BGRA 所以你可以复制 3 字节组然后在目的地设置 'a' 等等,我不认为灰度图像应该使用 QRgb 和 QImage::Format_ARGB32 进行转换。这不仅适用于彩色图像,比如 cv::Mat3b? 【参考方案1】:

我不知道。对我来说,首先设置一个数组听起来是一种更简洁的方式,请参阅 https://***.com/a/3387400/1705967 ,这可能会给你一些想法。

虽然我也使用 Ypnos 的解决方案在彩色图像上取得了巨大成功。 :)

啊,关于第二个问题,不要担心QPixmap。正如我所经历的那样,它使图像数据私有(必要时克隆),因此您不会错误地覆盖它。

【讨论】:

【参考方案2】:

如果有人遇到这个问题,我通过将像素值减去256 快速而肮脏地修复它:

QImage ImgConvert::matToQImage(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 = 256 - (srcrow[x] * scale);
                    destrow[x] = qRgba(color, color, color, 255);
            
    
    return dest;

不过,这会稍微损坏图像,将其亮度修改为 1。我的目的是可视化,因此肉眼可以忽略不计,但是对于图像处理中的某些应用程序,这种损坏可能是至关重要的。我不知道为什么会发生这种情况,因为我很着急,所以没有再看。

【讨论】:

这基本上是我做的,除了没有修改亮度。查看我在原始问题中的注释......从技术上讲,我解决了这个问题,但如果我不明白它为什么会起作用,那么它就是一个黑客。我希望有人解释为什么该 hack 有效/必要。

以上是关于cv::Mat 到 QImage 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

将 cv::mat 转换为 QImage

使用原始数据将 QImage 转换为 cv::Mat

使用 QImage::loadFromData 将 cv::mat 转换为 QImage

cv::Mat转换为QImage错误

Convert between cv::Mat and QImage 两种图片类转换

Convert between cv::Mat and QImage 两种图片类转换