C++ 如何将 QImage 转换为 opencv Mat
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11886123/
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
How to convert QImage to opencv Mat
提问by user1576633
I have searched on the internet but I cannot find a method of converting a QImage
(or QPixmap
) to a OpenCV Mat
. How would I do this?.
我在互联网上搜索过,但找不到将 a QImage
(or QPixmap
) 转换为 OpenCV 的方法Mat
。我该怎么做?。
Any help is appreciated.
任何帮助表示赞赏。
回答by timfeirg
One year after you issued this question there've been great answers on the internet:
在您提出这个问题一年后,互联网上已经有了很好的答案:
But the way I see it, if you're working with Qt and OpenCV at the same time then type QImage
is probably just for displaying, that case you might want to use QPixmap
since it's optimized for displaying. So this is what I do:
但在我看来,如果您同时使用 Qt 和 OpenCV,那么 typeQImage
可能仅用于显示,在这种情况下您可能想要使用QPixmap
它,因为它已针对显示进行了优化。所以这就是我所做的:
- Load image as
cv::Mat
, if you'd like to display the image, convert toQPixmap
using the non-copy method introduced in the second article. - Do your image processing in
cv::Mat
. - Any time during the workflow you can call upon something like
Mat2QPixmap()
to get realtime result. - Never convert
QPixmap
tocv::Mat
, there's no sense doing it considering the purpose of each type.
- Load image as
cv::Mat
,如果你想显示图像,转换为QPixmap
使用第二篇文章中介绍的非复制方法。 - 在
cv::Mat
. - 在工作流程中的任何时候,您都可以调用诸如
Mat2QPixmap()
获取实时结果之类的东西。 - 永远不要转换
QPixmap
为cv::Mat
,考虑到每种类型的目的,这样做是没有意义的。
回答by Martin Beckett
If the QImage will still exist and you just need to perform a quick operation on it then ou can construct a cv::Mat using the QImage memory
如果 QImage 仍然存在并且您只需要对其执行快速操作,那么您可以使用 QImage 内存构造一个 cv::Mat
cv::Mat mat(image.rows(),image.cols(),CV_8UC3,image.scanline());
This assumes that the Qimage is 3channels, ie RGB888
cv::Mat mat(image.rows(),image.cols(),CV_8UC3,image.scanline());
这假设 Qimage 是 3channels,即 RGB888
If the Qimage is going away then you need to copy the data, see Qimage to cv::Mat convertion strange behaviour
如果 Qimage 消失了,那么您需要复制数据,请参阅Qimage 到 cv::Mat 转换奇怪的行为
If QImage is Format_ARGB32_Premultiplied (the preffered format) then you will need to convert each pixel to openCV's BGR layout. The cv::cvtcolor() function can convert ARGB to RGB in the latest versions.
Or you can use QImage::convertToformat()to convert to RGB before copying the data
如果 QImage 是 Format_ARGB32_Premultiplied(首选格式),那么您需要将每个像素转换为 openCV 的 BGR 布局。最新版本的 cv::cvtcolor() 函数可以将 ARGB 转换为 RGB。
或者您可以在复制数据之前使用QImage::convertToformat()转换为 RGB
回答by dev_nut
The answer to this with Qt 5.11 (and probably some earlier versions):
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
Again the QImage is assumed to be RGB888 (ie QImage::Format_RGB888)
再次假设 QImage 为 RGB888(即 QImage::Format_RGB888)
回答by TimSC
My attempt in OpenCV 3.1+ style code:
我在 OpenCV 3.1+ 风格代码中的尝试:
void qimage_to_mat(const QImage& image, cv::OutputArray out) {
switch(image.format()) {
case QImage::Format_Invalid:
{
Mat empty;
empty.copyTo(out);
break;
}
case QImage::Format_RGB32:
{
Mat view(image.height(),image.width(),CV_8UC4,(void *)image.constBits(),image.bytesPerLine());
view.copyTo(out);
break;
}
case QImage::Format_RGB888:
{
Mat view(image.height(),image.width(),CV_8UC3,(void *)image.constBits(),image.bytesPerLine());
cvtColor(view, out, COLOR_RGB2BGR);
break;
}
default:
{
QImage conv = image.convertToFormat(QImage::Format_ARGB32);
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:
{
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:
{
Mat mat;
cvtColor(image, mat, 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:
{
Mat mat;
cvtColor(image, mat, 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;
}
}
}
回答by G Sree Teja Simha
I'd save the image to disk and reopen it from cv ;)
我会将图像保存到磁盘并从 cv 重新打开它;)
@^ I've tried the previous solution. It doesn't seem to working with me. Although I'm getting some image, it looks like some bar code information kind of image. I guess there are some mismatch of parameters.
@^ 我已经尝试过以前的解决方案。它似乎不适合我。虽然我得到了一些图像,但它看起来像一些条形码信息类型的图像。我猜有一些参数不匹配。