//对不起我的英语。
请告诉我,我做错了什么? 我已经阅读了很多关于此的内容。并写了一些代码,但结果很糟糕。
据我了解 在 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;
}
我制作了临时垫,因为我想在 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 的位置,就会把这个颜色的位置改回来,因为我没有找到 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();
}
和.pro文件
INCLUDEPATH += /usr/local/include/opencv /usr/local/include/opencv2
LIBS += -lopencv_core -lopencv_imgproc\
-lopencv_highgui
QT += gui
QT += core
SOURCES += \
QcvMat.cpp \
我的结果很糟糕!!!
有吗?各位,我需要帮助!
我添加了一些调试信息来获取 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
这是什么意思,可能是什么问题?
最佳答案
代码看起来不错,但有一个异常(exception)。
内存管理。 cv::Mat
不像 QImage
在这个 mater 中工作。请记住,QImage
使用写时复制机制并为每个拷贝共享内存。
cv::Mat
也共享内存,但它不会在写入时复制(我也是 open 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;
}
所以我们都必须阅读有关 open-CV 中的内存管理的内容:)。
OFFTOPIC:
在 Linux 上的 qt 项目中包含 openCV 的最佳方法是在 pro 文件中添加如下内容:
# add open CV
unix {
CONFIG += link_pkgconfig
PKGCONFIG += opencv
}
将代码移动到另一台机器时不会出现路径问题。
关于c++ - cv::Mat 到 QImage 并返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17127762/