cv :: Mat到QImage并返回

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

请告诉我,我做错了什么? 我读了很多关于这个。 并写一些代码,但我有一个可怕的结果。

据我所知在Opencv CV_8UC3是相同的QImage :: Format_RGB888 ,除了BRG和RGB相应。

以这种格式读取cv :: Mat我可以这样做:

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

所以,要将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; } 

我做了temp mat,因为我想在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; } 

我插入了cvtColor(res,res,CV_BGR2RGB) ; 用BGR颜色制作cv Mat。 我不完全知道里面的这个函数cvtColor(res,res,CV_BGR2RGB) ;但是我决定如果cvtColor(res,res,CV_BGR2RGB); 改变地方R和B,这将chage这个颜色的地方,因为我没有findCV_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(); } 

和.pro文件

 INCLUDEPATH += /usr/local/include/opencv /usr/local/include/opencv2 LIBS += -lopencv_core -lopencv_imgproc\ -lopencv_highgui QT += gui QT += core SOURCES += \ QcvMat.cpp \ 

而且我有一个坏结果! 我的坏结果

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

我添加了一些debugging信息来获取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 

这是什么意思,可能是问题呢?

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

所以我已经改正了你的转换函数,它完美的作品:

 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; } 

所以我们都必须在open-CV中做一个关于内存pipe理的内容:)。

无关:
在Linux上的qt项目中包含openCV的最佳方式是添加到pro文件,如:

 # add open CV unix { CONFIG += link_pkgconfig PKGCONFIG += opencv } 

将代码移到另一台机器时,您将没有path问题。

非常感谢! 这是真正的作品! 但。 为什么记忆被宠坏了? 第一。 我有一些内存加载incv ::垫

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

那么我把这个cvMat的副本放到其他cv:Mat

 cv::Mat temp(src.cols,src.rows,src.type()); cvtColor(src, temp,CV_BGR2RGB); mat1 - [=========================================] temp - [=========================================] 

然后使QImage从这个数据QImage dest = QImage((uchar *)temp.data,temp.cols,temp.rows,temp.step,QImage :: Format_RGB888);

 mat1 - [============================================] temp - > [============================================] / dest --/ 

然后,温度超出范围,并删除自我? QImage没有取得它的所有权,所以temp1和dest中的内存标记为空闲,并且那里编译器可以把其他数据? 我是对的吗?