cv :: Mat到QImage并返回

use*_*159 16 c++ qt opencv qimage mat

//对不起我的英语不好.

请告诉我,我做错了什么?我已经阅读了很多关于此的内容.并写一些代码,但我有一个可怕的结果.

据我所知,Opencv CV_8UC3QImage :: Format_RGB888相同,但BRG和RGB除外.

以这种格式阅读cv :: Mat我能做到:

cv::Mat mat1 = cv::imread("bugero.jpg",3); 
Run Code Online (Sandbox Code Playgroud)

所以,要将cv :: Mat转换为QImage,我可以这样做:

QImage Mat2QImage(cv::Mat const& src)
{
     cv::Mat temp(src.cols,src.rows,src.type());
     cvtColor(src, temp,CV_BGR2RGB);
     QImage dest= QImage((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
     return dest;
}
Run Code Online (Sandbox Code Playgroud)

我做了临时垫因为我想在QImage中拥有数据副本.

然后.要将其转换回来,我必须这样做:

cv::Mat QImage2Mat(QImage const& src)
{
     QImage temp = src.copy();
     cv::Mat res(temp.height(),temp.width(),CV_8UC3,(uchar*)temp.bits(),temp.bytesPerLine());
     cvtColor(res, res,CV_BGR2RGB); 
     return res;
}
Run Code Online (Sandbox Code Playgroud)

我插入了cvtColor(res,res,CV_BGR2RGB) ; 使用BGR颜色制作cv Mat.我不知道这个函数里面有什么cvtColor(res,res,CV_BGR2RGB) ;但是我决定如果cvtColor(res,res,CV_BGR2RGB); 改变地方R和B,这将使这些颜色的地方变回,因为我没有找到CV_BGR2RGB.

所以,我写了一个简短的示例程序

#include <QApplication>
#include <QtGui>
#include <cv.h>
#include "opencv2/highgui/highgui.hpp"

QImage Mat2QImage(cv::Mat const& src)
{
     cv::Mat temp(src.cols,src.rows,src.type()); // make the same cv::Mat
     cvtColor(src, temp,CV_BGR2RGB); // cvtColor Makes a copt, that what i need
     QImage dest= QImage((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
     return dest;
}

cv::Mat QImage2Mat(QImage const& src)
{
     QImage temp = src.copy(); 
     cv::Mat res(temp.height(),temp.width(),CV_8UC3,(uchar*)temp.bits(),temp.bytesPerLine());
     cvtColor(res, res,CV_BGR2RGB); // make convert colort to BGR ! 
     return res; 
}


int main(int argc, char *argv[])
{
     QApplication a(argc, argv);
     QWidget W1;
     QWidget W2;
     QLabel imlab1(&W1);
     QLabel imlab2(&W2);
     W1.setWindowTitle("Convert cv::Mat to QImage First time"); 
     W2.setWindowTitle("Convert cv::Mat to QImage Second time");    




     cv::Mat mat1 = cv::imread("bugero.jpg",3);

     QImage qim1  = Mat2QImage(mat1);

     cv::Mat mat2 = QImage2Mat(qim1);

     QImage qim2 = Mat2QImage(mat2); 

     cv::Mat mat3 = QImage2Mat(qim2);



     cv::imshow("First Mat",mat1);
     imlab1.setPixmap(QPixmap::fromImage(qim1)); 
     W1.setFixedSize(qim1.size()); 
     cv::imshow("Convert QImage to cv::Mat firstly",mat2);
     imlab2.setPixmap(QPixmap::fromImage(qim2));
     W2.setFixedSize(qim2.size()); 
     cv::imshow("Convert QImage to cv::Mat secondly",mat2);
     W1.show();
     W2.show();

     return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

和.pro文件

INCLUDEPATH += /usr/local/include/opencv /usr/local/include/opencv2
LIBS += -lopencv_core -lopencv_imgproc\
                                       -lopencv_highgui
QT       += gui
QT       += core
SOURCES += \
    QcvMat.cpp \
Run Code Online (Sandbox Code Playgroud)

我有一个不好的结果! 我的结果不好

有一些吗?人,我需要帮助!

我添加了一些调试信息来获取cv :: Mat.step和QImage.bytesPerLine(),它是不同的.

alex@lenovo /media/Files/Programming/Cpp/tests/QImagecvMat $ ./QcvMat 
cv step  942 
QImage  bytesPerLine  944 
cv step  942 
QImage  bytesPerLine  944 
Run Code Online (Sandbox Code Playgroud)

它意味着什么,可能是问题?

Mar*_*k R 34

代码看起来很好,有一个例外.
内存管理.在这个主人身上cv::Mat不起作用QImage.请记住,QImage正在使用写入机制上的副本并为每个副本共享内存. cv::Mat也分享内存,但它没有复制写(我也是新的开放cv(2周)所以我无法解释它究竟是如何工作但我偶然发现了一些粉碎因为那)!
另一件事是,当你QImage从内存创建时,图像使用的是这个内存而不是它的所有权.
最终的结果是,在Linux和Qt5上,由于内存管理问题,您的代码崩溃了.在屏幕截图中,您可以在第二个窗口的顶部看到发生了奇怪的事情并且您看到了一些内存垃圾.

所以我已经纠正了它完美运行的转换函数:

QImage Mat2QImage(cv::Mat const& src)
{
     cv::Mat temp; // make the same cv::Mat
     cvtColor(src, temp,CV_BGR2RGB); // cvtColor Makes a copt, that what i need
     QImage dest((const uchar *) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
     dest.bits(); // enforce deep copy, see documentation 
     // of QImage::QImage ( const uchar * data, int width, int height, Format format )
     return dest;
}

cv::Mat QImage2Mat(QImage const& src)
{
     cv::Mat tmp(src.height(),src.width(),CV_8UC3,(uchar*)src.bits(),src.bytesPerLine());
     cv::Mat result; // deep copy just in case (my lack of knowledge with open cv)
     cvtColor(tmp, result,CV_BGR2RGB);
     return result;
}
Run Code Online (Sandbox Code Playgroud)

所以我们都必须在open-CV :)中阅读有关内存管理的内容.

OFFTOPIC:
在Linux上的qt项目中包含openCV的最佳方法是在pro文件中添加如下内容:

# add open CV
unix {
    CONFIG += link_pkgconfig
    PKGCONFIG += opencv
}
Run Code Online (Sandbox Code Playgroud)

将代码移动到另一台机器时,您将免于路径问题.

  • 你不能只做`dest.detach()`并返回'dest`吗?另外,`detach()`不在[文档]中(http://qt-project.org/doc/qt-5/qimage.html).为什么?无论哪种方式,[此解决方案](http://asmaloney.com/2013/11/code/converting-between-cvmat-and-qimage-or-qpixmap/)使用Qt的`rgbSwapped()`,它可以工作并记录在案. (2认同)