如何将opencv cv :: Mat转换为qimage

Hie*_*ien 38 c++ qt opencv qimage

我想知道如何将OpenCV C++标准cv :: Mat类型转换为Qimage.我一直在寻找,但没有运气.我找到了一些将IPlimage转换为Qimage的代码,但这不是我想要的.谢谢

chA*_*Ami 36

Michal Kottman的答案是有效的,并给出了一些图像的预期结果,但在某些情况下它会失败.这是我发现这个问题的解决方案.

QImage imgIn= QImage((uchar*) img.data, img.cols, img.rows, img.step, QImage::Format_RGB888);
Run Code Online (Sandbox Code Playgroud)

区别在于添加img.step部分.如果没有它,qt不会抱怨,但如果没有它,一些图像将无法正常显示.希望这会有所帮助.

  • 这基本上就是OpenCV内部用来转换的内容(http://code.opencv.org/projects/opencv/repository/revisions/df262b340cbe1b362977573bb34138d837f79648/entry/modules/highgui/src/window_QT.cpp,第2389行)`image2Draw_qt = QImage( image2Draw_mat-> data.ptr,image2Draw_mat-> cols,image2Draw_mat-> rows,image2Draw_mat-> step,QImage :: Format_RGB888);`另外(大约,第2400行)`cvConvertImage(mat,image2Draw_mat,CV_CVTIMG_SWAP_RB);`来自BGR到RGB. (5认同)
  • `img.step` 使一切变得不同。我在这种转换中遇到了奇怪的问题,包括生成的图像显示失真和颜色错误。稍微测试一下,我得到了相同的代码。 (2认同)

ypn*_*nos 28

这是24位RGB和灰度浮点的代码.可轻松调节其他类型.它尽可能高效.

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;
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*man 24

要转换cv::MatQImage,您可以尝试使用QImage(uchar * data, int width, int height, Format format)构造函数,如下所示(matcv::Mat):

QImage img((uchar*)mat.data, mat.cols, mat.rows, QImage::Format_RGB32);
Run Code Online (Sandbox Code Playgroud)

它比手动将像素转换为更有效QImage,但您必须将原始cv::Mat图像保留在内存中.它可以很容易地转换为a QPixmap并使用以下方式显示QLabel:

QPixmap pixmap = QPixmap::fromImage(img);
myLabel.setPixmap(pixmap);
Run Code Online (Sandbox Code Playgroud)

更新

因为OpenCV默认使用BGR顺序,所以首先应该使用cvtColor(src, dst, CV_BGR2RGB)Qt理解的图像布局.

更新2:

如果您尝试显示的图像具有非标准步幅(当它是非连续的,子矩阵时),图像可能会失真.在这种情况下,最好使用cv::Mat::step1()以下方法明确指定步幅:

QImage img((uchar*)mat.data, mat.cols, mat.rows, mat.step1(), QImage::Format_RGB32);
Run Code Online (Sandbox Code Playgroud)

  • 嗯,是的,它也可以有多个维度,或者可以有不同的"步长".我期待Hien想要显示'标准'cv :: Mat,即由`imread`加载,或者转换为适当的类型. (2认同)

Gun*_*son 8

Mat默认情况下,OpenCV 将图像加载为蓝绿红 (BGR) 格式,而QImage期望使用 RGB。这意味着如果您将 a 转换MatQImage,则蓝色和红色通道将交换。要解决此问题,在构建 之前QImage,您需要Mat通过cvtColor使用参数的方法将 BRG 格式更改为 RGB CV_BGR2RGB,如下所示:

Mat mat = imread("path/to/image.jpg");
cvtColor(mat, mat, CV_BGR2RGB);
QImage image(mat.data, mat.cols, mat.rows, QImage::Format_RGB888);
Run Code Online (Sandbox Code Playgroud)

或者,rgbSwapped()QImage

QImage image = QImage(mat.data, mat.cols, mat.rows, QImage::Format_RGB888).rgbSwapped());
Run Code Online (Sandbox Code Playgroud)


eta*_*ion 2

cv::Mat 有一个到 IplImage 的转换运算符,因此如果您有将 IplImage 转换为 QImage 的东西,只需使用它(或者进行 - 可能较小的 - 调整以直接采用 cv::Mat ,内存布局是相同,“只是”标题不同。)