如何将 QImage 转换为 opencv Mat
How to convert QImage to opencv Mat
我在互联网上搜索过,但我找不到将QImage
(或QPixmap
)转换为OpenCV Mat
的方法。我该怎么做?
任何帮助,不胜感激。
如果 QImage 仍然存在,并且您只需要对它执行快速操作,那么您可以使用 QImage 内存构造一个 cv::Mat:
cv::Mat mat(image.height(), image.width(), CV_8UC3, (cv::Scalar*)image.scanLine(0));
这假设QImage是3通道,即RGB888。
如果 QImage 要消失,那么你需要复制数据,请参阅 Qimage 到 cv::Mat 转换的奇怪行为。
如果 QImage 是Format_ARGB32_Premultiplied(首选格式),那么您需要将每个像素转换为 OpenCV 的 BGR 布局。cv::cvtcolor() 函数可以在最新版本中将 ARGB 转换为 RGB.
或者,您可以使用QImage::convertToFormat()在复制数据之前转换为RGB。
在你提出这个问题一年后,互联网上得到了很好的答案:
- 在 cv::mat 和 Qimage 之间正确转换
- 在 cv::Mat 和 QImage 或 QPixmap 之间转换
但是在我看来,如果您同时使用Qt和OpenCV,那么键入QImage
可能仅用于显示,在这种情况下您可能希望使用QPixmap
,因为它针对显示进行了优化。这就是我所做的:
- 加载图像
cv::Mat
,如果要显示图像,请使用第二篇文章中介绍的非复制方法转换为QPixmap
。 - 在
cv::Mat
中进行图像处理。 - 在工作流程中,您可以随时调用类似
Mat2QPixmap()
的东西来获得实时结果。 - 永远不要将
QPixmap
转换为cv::Mat
,考虑到每种类型的目的,这样做是没有意义的。
Qt 5.11(可能还有一些早期版本)的答案:
cv::Mat mat(image.height(), image.width(),CV_8UC3, image.bits());
// image.scanline() does not exist,
//and height/width is interchanged for a matrix
同样,QImage被假定为RGB888(即QImage::Format_RGB888)
我在OpenCV 3.1+风格代码中的尝试:
void qimage_to_mat(const QImage& image, cv::OutputArray out) {
switch(image.format()) {
case QImage::Format_Invalid:
{
cv::Mat empty;
empty.copyTo(out);
break;
}
case QImage::Format_RGB32:
{
cv::Mat view(image.height(),image.width(),CV_8UC4,(void *)image.constBits(),image.bytesPerLine());
view.copyTo(out);
break;
}
case QImage::Format_RGB888:
{
cv::Mat view(image.height(),image.width(),CV_8UC3,(void *)image.constBits(),image.bytesPerLine());
cvtColor(view, out, cv::COLOR_RGB2BGR);
break;
}
default:
{
QImage conv = image.convertToFormat(QImage::Format_ARGB32);
cv::Mat view(conv.height(),conv.width(),CV_8UC4,(void *)conv.constBits(),conv.bytesPerLine());
view.copyTo(out);
break;
}
}
}
void mat_to_qimage(cv::InputArray image, QImage& out)
{
switch(image.type())
{
case CV_8UC4:
{
cv::Mat view(image.getMat());
QImage view2(view.data, view.cols, view.rows, view.step[0], QImage::Format_ARGB32);
out = view2.copy();
break;
}
case CV_8UC3:
{
cv::Mat mat;
cvtColor(image, mat, cv::COLOR_BGR2BGRA); //COLOR_BGR2RGB doesn't behave so use RGBA
QImage view(mat.data, mat.cols, mat.rows, mat.step[0], QImage::Format_ARGB32);
out = view.copy();
break;
}
case CV_8UC1:
{
cv::Mat mat;
cvtColor(image, mat, cv::COLOR_GRAY2BGRA);
QImage view(mat.data, mat.cols, mat.rows, mat.step[0], QImage::Format_ARGB32);
out = view.copy();
break;
}
default:
{
throw invalid_argument("Image format not supported");
break;
}
}
}
cv::Mat to_cvmat(QImage img)
{
img = img.convertToFormat(QImage::Format_RGB888, Qt::ColorOnly).rgbSwapped();
return cv::Mat(img.height(), img.width(), CV_8UC3, img.bits(), img.bytesPerLine()).clone();
}
相关文章:
- C++中的openCV Mat访问冲突
- 如何通过引用传递OpenCV MAT
- Read OpenCV Mat 16bit to QImage 8bit Greyscale
- 将本地 OpenCV Mat 变量声明为静态以防止重新分配
- 将 OpenCv Mat 从 C++ 传递给 Python
- 将帧从 h264 流解码到 OpenCV Mat
- 如果函数使用 OPENCV Mat 作为输入,如何编写头文件?
- 无法从Java读取C++中保存的Opencv Mat映像
- 如何通过套接字发送OpenCV Mat
- 如何有效地在OpenCV Mat和GpuMat上进行元素处理?
- 什么是使用 opencv::Mat 优化 c++ 矩阵计算
- openCV Mat 中的值在自定义类构造函数中设置后不会保留
- OpenCV Mat 的逗号分隔初始值设定项是如何用C++实现的?
- Libav AVFrame to Opencv Mat to AVPacket conversion
- 采用OpenCV Mat<doube>并转换为12位值数组。
- 如何将C++数组转换为opencv Mat
- 通过QT WebSocket将OpenCV Mat Image发送到HTML客户端
- OpenCV Mat::row assignment
- 如何在 OpenCV Mat 中保留固定的缓冲区大小
- OPENCV MAT问题:直方图和此循环之间的差异