【问题标题】:QPixmap fromImage gives segment fault on image converted from cv::matQPixmap fromImage 在从 cv::mat 转换的图像上给出段错误
【发布时间】:2026-01-17 11:55:02
【问题描述】:

我简化了代码,是这样的:

Mat mat = imread("xxx.jpg"); //Successfully read the image, confirmed by cvShowImage.

if (mat.empty())
{
    qDebug() << "Couldn't load image";
    return;
}

Mat cpy = mat.clone();
cvtColor(mat,cpy,CV_BGR2RGB);
QImage image(cpy.data, cpy.cols, cpy.rows, cpy.step, QImage::Format_RGB888);

try {
    pm = QPixmap::fromImage(image); //crash line
} catch(std::exception const &ex){
    qDebug()<<ex.what();
}

但是程序在没有任何调试日志的情况下就崩溃了。我尝试了很多图像,结果都是一样的。我试图找到“堆栈跟踪”,这似乎给出了段错误..

【问题讨论】:

  • 首先你做QImage image(...); 然后你做pm = QPixmap::fromImage(fim);fim 是什么? (崩溃的原因?)我强烈建议将其设为MCVE。如果这不能解决您的问题,它至少有助于在这个社区中引起更多关注。
  • 我猜 fim 有一些未初始化的数据
  • @Scheff 对不起对不起。那应该是“image”而不是“fim”,因为我从不同的函数中复制了代码。
  • 有时,图像线必须以一定的对齐方式提供。 (例如在 OpenGL 中看到)因此,如果您有三元组(RGB 值),由于 cpy.cols 中的值,结果字节数可能是(或可能不是)4 的倍数,而 QImage 可能期望相反.我刚刚查看了 Qt 文档。 QImage::bytesPerLine() 但乍一看找不到相关信息。您可能会更深入地研究这个方向。恕我直言,这可能是对段的解释。错误,因为您的代码在此旁边看起来“无辜”。
  • 啊。看看 Qt 文档。你使用的构造函数:QImage::QImage(): ...数据必须是32位对齐的,并且图像中的每个扫描线数据也必须是32位对齐的。你确定@987654331 @ 是否以这种方式提供数据?

标签: qt opencv qt5 qpixmap


【解决方案1】:

在 QPixmap.fromImage 中有类似的崩溃。通过将图像大小调整为与 4 字节对齐的大小找到了解决方法

aligned = cv2.resize(img, (img.shape[1]//4*4, img.shape[0]//4*4), fx=0, fy=0, interpolation=cv2.INTER_NEAREST)
rgb = cv2.cvtColor(aligned, cv2.COLOR_BGR2RGB)
qimage = QImage(rgb.data, rgb.shape[1], rgb.shape[0], QImage.Format_RGB888)
pixmap = QPixmap.fromImage(qimage)

【讨论】:

    【解决方案2】:

    好的..只需将转换代码更改为

    QImage image(cpy.data, cpy.cols, cpy.rows, cpy.step, QImage::Format_RGB888);
    image = image.rgbSwapped();
    

    解决了。其实我不知道为什么这解决了它。也许是因为我应该使用 COLOR_BGR2RGB 而不是 CV_BGR2RGB..

    【讨论】: