我在想如何将OpenCV C++标准cv :: Mat类型转换为Qimage。我一直在寻找,但没有运气。我发现了一些将IPlimage转换为Qimage的代码,但这不是我想要的。谢谢如何将opencv cv :: Mat转换为qimage
回答
cv :: Mat有一个到IplImage的转换运算符,所以如果你有东西将IplImage转换成QImage,那就使用它(或者直接使用cv :: Mat来进行小调整 - 内存布局是一样的,它的“公正”的是不同的头)
我正在处理的项目需要我将图像打印到QtGui上,但我会在大多数时间在cv :: Mat上处理图像。我问的原因是我的程序会做很多计算,所以我想摆脱cv :: Mat转换为IplImage然后转换为qimage的开销。这是我的第一个图像处理项目,所以我不太了解图像中的数据。一旦我更加深入这个项目,我会很快了解这一点。无论如何,如果我找不到任何东西,那么我会按照你的建议=) – Hien
你可以请共享代码为IplImage - > QImage转换?我有兴趣进行必要的调整,将其转换为cv :: Mat。 –
@Hien:转换cv :: Mat到IplImage的开销与您在进行图像处理时所做的所有其他操作相比,完全可以忽略不计。没有涉及数据的复制。 – etarion
从cv::Mat
转换为QImage
,你可以尝试使用QImage(uchar * data, int width, int height, Format format)
构造如下(mat
是cv::Mat
):
QImage img((uchar*)mat.data, mat.cols, mat.rows, QImage::Format_RGB32);
这比手动将像素转换为t更高效他QImage
,但你必须保持原来的cv::Mat
图像在内存中。它可以方便地转换为QPixmap
和使用显示QLabel
:
QPixmap pixmap = QPixmap::fromImage(img);
myLabel.setPixmap(pixmap);
更新
因为OpenCV的使用BGR顺序默认情况下,你应该先用cvtColor(src, dst, CV_BGR2RGB)
来获得图像的布局,Qt的理解。
更新2:
如果你想显示的图像具有非标准stride(当它是不连续的,子矩阵),图像可能appeard失真。在这种情况下,最好是明确指定使用cv::Mat::step1()
步幅:
QImage img((uchar*)mat.data, mat.cols, mat.rows, mat.step1(), QImage::Format_RGB32);
这在一般情况下不起作用。如果mat> 1个通道或数据格式不是RGB32,会怎么样? –
嗯,是的,它也可以有多个维度,或者可以有不同的“步长”。我希望Hien希望显示'标准'cv :: Mat,即通过'imread'加载,或转换为适当的类型。 –
@Michael是的,这是我想要的。一旦我有时间处理我的项目,我会尝试一下你的代码。 =) – Hien
This post演示如何将QImage
到的OpenCV的IplImage
,反之亦然转换。
后,如果您需要帮助之间IplImage*
到cv::Mat
转换:
// Assume data is stored by:
// IplImage* image;
cv::Mat mat(image, true); // Copies the data from image
cv::Mat mat(image, false); // Doesn't copy the data!
这是一个黑客,但会完成这项工作。
这里是24位RGB和灰度浮点的代码。其他类型可轻松调整。它的效率与其获得的效率相同。
QImage Mat2QImage(const cv::Mat3b &src) {
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
for (int y = 0; y < src.rows; ++y) {
const cv::Vec3b *srcrow = src[y];
QRgb *destrow = (QRgb*)dest.scanLine(y);
for (int x = 0; x < src.cols; ++x) {
destrow[x] = qRgba(srcrow[x][2], srcrow[x][1], srcrow[x][0], 255);
}
}
return dest;
}
QImage Mat2QImage(const cv::Mat_<double> &src)
{
double scale = 255.0;
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
for (int y = 0; y < src.rows; ++y) {
const double *srcrow = src[y];
QRgb *destrow = (QRgb*)dest.scanLine(y);
for (int x = 0; x < src.cols; ++x) {
unsigned int color = srcrow[x] * scale;
destrow[x] = qRgba(color, color, color, 255);
}
}
return dest;
}
这回答了我即将发布的有关将浮点灰度值转换为QImage的问题......谢谢! –
Mat opencv_image = imread("fruits.jpg", CV_LOAD_IMAGE_COLOR);
Mat dest;
cvtColor(opencv_image, dest,CV_BGR2RGB);
QImage image((uchar*)dest.data, dest.cols, dest.rows,QImage::Format_RGB888);
这是对我工作。我修改了上面的Michal Kottman的代码。
Michal Kottman的答案是有效的,并给出了一些图像的预期结果,但它在某些情况下会失败。这是我发现这个问题的解决方案。
QImage imgIn= QImage((uchar*) img.data, img.cols, img.rows, img.step, QImage::Format_RGB888);
区别在于加入了img.step部分。没有它qt不会抱怨,但一些图像不会没有它正确显示。希望这会有所帮助。
这实质上就是OpenCV在内部用来转换(http://code.opencv.org/projects/opencv/repository/dvisions/df262b340cbe1b362977573bb34138d837f79648/entry/modules/highgui/src/window_QT.cpp,2389行)image2Draw_qt = QImage (image2Draw_mat-> data.ptr,image2Draw_mat-> cols,image2Draw_mat-> rows,image2Draw_mat-> step,QImage :: Format_RGB888);'也是(大约2400行)'cvConvertImage(mat,image2Draw_mat,CV_CVTIMG_SWAP_RB);'从BGR到RGB。 –
'img.step'使所有的区别。这次转换出现了奇怪的问题,包括产生的图像扭曲且颜色错误。测试一下,我得到了相同的代码。 – MeloMCR
谢谢!那正是我期待的! – Dredok
使用静态函数convert16uc1深度图像:
QPixmap Viewer::convert16uc1(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
quint8 value = (quint8) ((*(pSource)) >> 8);
*(pDest++) = value; // B
*(pDest++) = value; // G
*(pDest++) = value; // R
*(pDest++) = 0; // Alpha
pSource++;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert8uc3(const cv::Mat& source)
{
quint8* pSource = source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
QPixmap Viewer::convert16uc3(const cv::Mat& source)
{
quint16* pSource = (quint16*) source.data;
int pixelCounts = source.cols * source.rows;
QImage dest(source.cols, source.rows, QImage::Format_RGB32);
char* pDest = (char*) dest.bits();
for (int i = 0; i < pixelCounts; i++)
{
*(pDest++) = *(pSource+2); // B
*(pDest++) = *(pSource+1); // G
*(pDest++) = *(pSource+0); // R
*(pDest++) = 0; // Alpha
pSource+=3;
}
return QPixmap::fromImage(dest);
}
这奏效了我。这是一个有点狡猾,有可怕的表现(正如评论中指出的那样),但是可以使用到目前为止所有的颜色格式,而且它的操作也很简单。
的过程如下:
cv::Mat image = //...some image you want to display
// 1. Save the cv::Mat to some temporary file
cv::imwrite("../Images/tmp.jpg",image);
// 2. Load the image you just saved as a QImage
QImage img;
img.load("../Images/tmp.jpg");
完成!
如果你,说,想在一个QLabel来显示它,然后继续:
// Set QImage as content of MyImageQLabel
ui-> MyImageQLabel->setPixmap(QPixmap::fromImage(img, Qt::AutoColor));
我个人用这个简单的图像编辑器。
这有一个可怕的表现。 – AxeEffect
@AeeEffect考虑到您必须对硬盘进行读取/写入操作,这当然不是一个高性能的解决方案。但对于一些用途来说,这并不重要。 :-) –
我有同样的问题,你也一样,所以我开发四大功能,以减轻我的痛苦,他们是
QImage mat_to_qimage_cpy(cv::Mat const &mat, bool swap = true);
QImage mat_to_qimage_ref(cv::Mat &mat, bool swap = true);
cv::Mat qimage_to_mat_cpy(QImage const &img, bool swap = true);
cv::Mat qimage_to_mat_ref(QImage &img, bool swap = true);
这些功能可与1,3,4个通道,每个像素处理图像必须占用只有一个字节(CV_8U-> Format_Indexed8,CV_8UC3-> QImage :: Format_RGB888,CV_8UC4-> QImage :: Format_ARGB32),我还没有处理其他类型(QImage :: Format_RGB16,QImage :: Format_RGB666等等上)。该代码位于 在github。
的关键概念的 **变换垫QImage的**是
/**
* @brief copy QImage into cv::Mat
*/
struct mat_to_qimage_cpy_policy
{
static QImage start(cv::Mat const &mat, QImage::Format format)
{
//The fourth parameters--mat.step is crucial, because
//opencv may do padding on every row, you need to tell
//the qimage how many bytes per row
//The last thing is if you want to copy the buffer of cv::Mat
//to the qimage, you need to call copy(), else the qimage
//will share the buffer of cv::Mat
return QImage(mat.data, mat.cols, mat.rows, mat.step, format).copy();
}
};
struct mat_to_qimage_ref_policy
{
static QImage start(cv::Mat &mat, QImage::Format format)
{
//every thing are same as copy policy, but this one share
//the buffer of cv::Mat but not copy
return QImage(mat.data, mat.cols, mat.rows, mat.step, format);
}
};
的关键概念的变换cv::Mat to Qimage
是
/**
* @brief copy QImage into cv::Mat
*/
struct qimage_to_mat_cpy_policy
{
static cv::Mat start(QImage const &img, int format)
{
//same as convert mat to qimage, the fifth parameter bytesPerLine()
//indicate how many bytes per row
//If you want to copy the data you need to call clone(), else QImage
//cv::Mat will share the buffer
return cv::Mat(img.height(), img.width(), format,
const_cast<uchar*>(img.bits()), img.bytesPerLine()).clone();
}
};
/**
* @brief make Qimage and cv::Mat share the same buffer, the resource
* of the cv::Mat must not deleted before the QImage finish
* the jobs.
*/
struct qimage_to_mat_ref_policy
{
static cv::Mat start(QImage &img, int format)
{
//same as copy policy, but this one will share the buffer
return cv::Mat(img.height(), img.width(), format,
img.bits(), img.bytesPerLine());
}
};
如果将是一件好事,如果有一个人能扩展这些功能并使它们支持更多类型,请告知我是否有任何错误。
看起来很愚蠢,但将图像保存到文件夹中,然后读入QImage对象似乎是最快捷的方式。
Mat x = imread("--.jpg");
imwrite("x.jpg", x);
QImage img("x.jpg");
- 1. 如何将QImage转换为opencv Mat
- 2. cv :: Mat到QImage的转换
- 3. 将Qimage转换为Mat时出错opencv
- 4. Qimage cv :: Mat转换奇怪的行为
- 5. 如何将从/到QImage的ROI转换为/从cv :: Mat?
- 6. 转换为&从OpenCV cv :: Mat,NSImage
- 7. 将HBITMAP转换为cv :: Mat
- 8. 如何将Simd :: View转换为cv :: Mat?
- 9. 如何将cv :: Mat转换为OpenCv中的灰度级?
- 10. 错误将cv :: mat转换为cv :: arr
- 11. 将BufferedImage转换为OpenCv Mat
- 12. 将uchar Mat转换为OpenCV中的Mat?
- 13. openCV cv :: mat release
- 14. opencv cv :: mat allocation
- 15. 将OpenGL纹理转换为OpenCV Mat
- 16. 将cv :: mat转换为OpenCV中的字节字符串
- 17. 将GDIPlus :: Bitmap转换为cv :: Mat(OpenCV C++接口)
- 18. 将cv :: Mat转换为UIImage时发生崩溃opencv 2.4
- 19. 将opencv图像cv :: Mat格式转换为C#BitmapImage
- 20. 将Caffe caffe :: Datum转换为OpenCV cv :: Mat in C++
- 21. 在OpenCV中将UIImage转换为cv :: Mat问题
- 22. 如何将灰度/二进制Mat转换为QImage?
- 23. C++将cv :: Mat从CV_8U转换为CV_32F
- 24. 要将cv :: Mat转换为CvArr *
- 25. 将数据从cv :: Mat转换为mxArray
- 26. 将MATLAB中的.mat文件转换为OpenCV中的cv :: Mat矩阵
- 27. cv :: Mat转换为Eigen-Matrix并返回
- 28. 如何在C++中将SFML图像转换为OpenCV mat?
- 29. OpenCV:分区cv :: Mat
- 30. 打印cv :: Mat opencv
如果存在这样的代码将是有益的,但也有一些问题写它:CV ::垫支持更多的数据类型比的QImage,CV ::垫支持多个通道,如果数据被复制或包裹围绕原始数据... –