C++ cv::垫到齐马格和背面

C++ cv::垫到齐马格和背面,c++,qt,opencv,qimage,mat,C++,Qt,Opencv,Qimage,Mat,//对不起我的英语 请告诉我,我做错了什么? 我读了很多关于这方面的书。并编写一些代码,但我有一个可怕的结果 据我所知 在Opencv中,除了相应的BRG和RGB外,CV中的UC3与QImage::Format_RGB888相同 要阅读此格式的cv::Mat,我可以执行以下操作: cv::Mat mat1 = cv::imread("bugero.jpg",3); QImage Mat2QImage(cv::Mat const& src) { cv::Mat temp(sr

//对不起我的英语

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

据我所知 在Opencv中,除了相应的BRG和RGB外,CV中的UC3与QImage::Format_RGB888相同

要阅读此格式的cv::Mat,我可以执行以下操作:

cv::Mat mat1 = cv::imread("bugero.jpg",3); 
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;
}
因此,要将cv::Mat转换为QImage,我可以执行以下操作:

cv::Mat mat1 = cv::imread("bugero.jpg",3); 
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;
}
我制作了临时材料,因为我想在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垫。我不太清楚该函数中的内容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();
}
我得到了一个坏结果!!!

有一些吗?大家,我需要帮助

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

这意味着什么,可能是其中的问题?

代码看起来不错,只有一个例外。
内存管理
cv::Mat
与此材料中的
QImage
不一样。请记住,
QImage
正在使用写时复制机制,并为每个副本共享内存。
cv::Mat
也共享内存,但它不会在写的时候复制(我也是OpenCV的新手(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;
}
因此,我们都必须阅读OpenCV中的内存管理:)

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

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

将代码移动到另一台机器时,将不会出现路径问题。

非常感谢!这真的很有效! 但是为什么记忆被破坏了? 第一。我有一些内存加载incv::Mat

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)


然后temp超出范围并自行删除?QImage不拥有它的所有权,所以temp1和dest中的内存被标记为空闲,编译器可以在那里放置其他数据吗?我是对的吗

未损坏(内存泄漏),但已损坏(指针悬空)。IMO问题是
Mat2QImage
中的本地
temp
矩阵。QImage是指该矩阵的内存,它是局部变量,因此在返回表单
Mat2QImage
时释放了内存。您不能只执行
dest.detach()
并返回
dest
?另外,
detach()
不在中。为什么?无论哪种方式,都使用Qt的
rgbSwapped()
,它可以工作,并且有文档记录。确切地说,这是更好的解决方案(更通用)。我看到case
CV_8UC1
(内存未分离)有一个错误。它没有公开,因为它与
cvMatToQPixmap
一起在链中使用,并且复制内容。关于这个
detach
我没有注意到它没有文档记录。所以我会解决这个问题。我现在就可以拥抱你了!“这对我来说就像魔术一样,”小伙子很好地解释道!因此,当调用函数时,比如说,
QImage2Mat
我们应该传递Qimage的引用还是直接传递变量?