C++ cv::Mat 到 QImage 并返回
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17127762/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
cv::Mat to QImage and back
提问by user1113159
//Sorry for my english.
//对不起我的英语不好。
Tell me please, what I am doing wrong? I have read a lot about this. And write some code, but I have a terrible result.
请告诉我,我做错了什么?我已经阅读了很多关于这方面的内容。并写了一些代码,但我的结果很糟糕。
As I understand in Opencv CV_8UC3is the same as QImage::Format_RGB888, except BRG and RGB accordingly.
据我了解,在Opencv CV_8UC3与QImage::Format_RGB888相同,除了相应的 BRG 和 RGB。
to read cv::Mat in this format I can do:
以这种格式读取 cv::Mat 我可以这样做:
cv::Mat mat1 = cv::imread("bugero.jpg",3);
So, to convert cv::Mat to QImage I can do:
因此,要将 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;
}
I made temp mat becouse I want to have copy of data in QImage.
我制作了临时垫,因为我想在 QImage 中复制数据。
Then. To convert it back I Have to do:
然后。要将其转换回我必须执行的操作:
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;
}
I have inserted cvtColor(res, res,CV_BGR2RGB); to make cv Mat with BGR colors. I do not exactly know what in inside this function cvtColor(res, res,CV_BGR2RGB);, But I decided that if cvtColor(res, res,CV_BGR2RGB);change places R and B, that will chage places of this colors back, because I did not found CV_BGR2RGB.
我插入了cvtColor(res, res,CV_BGR2RGB); 用 BGR 颜色制作 cv Mat。我不完全知道这个函数里面是什么cvtColor(res, res,CV_BGR2RGB);, 但我决定如果cvtColor(res, res,CV_BGR2RGB); 改变位置 R 和 B,这将改变这种颜色的位置,因为我没有找到CV_BGR2RGB。
So, I wrote short sample program
所以,我写了简短的示例程序
#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();
}
and .pro file
和 .pro 文件
INCLUDEPATH += /usr/local/include/opencv /usr/local/include/opencv2
LIBS += -lopencv_core -lopencv_imgproc\
-lopencv_highgui
QT += gui
QT += core
SOURCES += \
QcvMat.cpp \
And I have got a BAD result!!!
我得到了一个糟糕的结果!!!
Is there some? People,I need help!
有吗?人,我需要帮助!
I added some debug info to get cv::Mat.step and QImage.bytesPerLine() and it is different.
我添加了一些调试信息来获取 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
What does it means and may be problem in it?
它是什么意思,可能有什么问题?
回答by Marek R
Code looks fine with one exception.
Memory management. cv::Mat
doesn't work like QImage
in this mater. Remember that QImage
is using copy on write mechanism and shares memory for each copy.
cv::Mat
also shares memory but it doesn't do copy on write (I'm also new with open cv (2 weeks) so I can't explain yet exactly how it works but I've stumbled on some crushes because of that)!
Another thing is that when you are creating QImage
from memory image is using this memory and doesn't take ownership of it.
Final outcome is that on Linux and Qt5 your code is crashes because of problems with memory management. On your screen shot you can see at the top of second window that something strange is going on and you see some memory trash.
代码看起来不错,但有一个例外。
内存管理。cv::Mat
不像QImage
在这件事上那样工作。请记住,这QImage
是使用写时复制机制并为每个副本共享内存。
cv::Mat
也共享内存,但它不会在写入时进行复制(我也是 open cv 的新手(2 周),所以我无法确切解释它是如何工作的,但因此我偶然发现了一些迷恋)!
另一件事是,当您QImage
从内存创建映像时,将使用此内存并且不拥有它的所有权。
最终结果是,在 Linux 和 Qt5 上,您的代码由于内存管理问题而崩溃。在屏幕截图上,您可以在第二个窗口的顶部看到发生了一些奇怪的事情,并且您会看到一些内存垃圾。
So I've corrected your conversion functions it works perfectly:
所以我更正了你的转换功能,它完美地工作:
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;
}
So we both have to do a reading about memory management in open-CV :).
所以我们都必须在 open-CV 中阅读有关内存管理的内容:)。
OFFTOPIC:
Best way to include openCV in qt projects on Linux is to add to pro file something like:
OFFTOPIC:
在 Linux 上的 qt 项目中包含 openCV 的最佳方法是添加到 pro 文件中,例如:
# add open CV
unix {
CONFIG += link_pkgconfig
PKGCONFIG += opencv
}
You will be free of path problems when moving code to another machine.
将代码移动到另一台机器时,您将不会遇到路径问题。
回答by user1113159
Thanks a Lot! It is realy works! But. Why does memory whas spoiled? First. I have some memory load incv::Mat
多谢!真的很管用!但。为什么记忆会变质?第一的。我有一些内存负载 incv::Mat
cv::Mat mat1 = cv::imread("bugero.jpg",3);
mat1 - [=====================================]
then I put a copy of this cvMat to other cv:Mat
然后我把这个 cvMat 的副本放到其他 cv:Mat
cv::Mat temp(src.cols,src.rows,src.type());
cvtColor(src, temp,CV_BGR2RGB);
mat1 - [=========================================]
temp - [=========================================]
then make QImage from this data QImage dest= QImage((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
然后从这个数据制作 QImage QImage dest= QImage((uchar*) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
mat1 - [============================================]
temp - > [============================================]
/
dest --/
And then temp goes out of scope and delete it self? QImage does not take ownership of it so memory in temp1 and dest marked as free, and there compiler can put other data? Is I am right?
然后 temp 超出范围并自行删除?QImage 不拥有它的所有权,因此 temp1 和 dest 中的内存标记为空闲,并且编译器可以放置其他数据吗?我是对的吗?