我在互联网上搜索过,但找不到将 a QImage
(or QPixmap
) 转换为 OpenCV的方法Mat
。我该怎么做?
任何帮助表示赞赏。
在您发布此问题一年后,互联网上出现了很好的答案:
但在我看来,如果您同时使用 Qt 和 OpenCV,那么 typeQImage
可能只是用于显示,这种情况您可能想要使用,QPixmap
因为它已针对显示进行了优化。所以这就是我所做的:
cv::Mat
,如果要显示图片,请转换为QPixmap
使用第二篇介绍的非复制方法。cv::Mat
.Mat2QPixmap()
获取实时结果之类的东西。QPixmap
为cv::Mat
,考虑到每种类型的目的,这样做是没有意义的。如果 QImage 仍然存在,并且您只需要对其执行快速操作,那么您可以使用 QImage 内存构造一个 cv::Mat :
cv::Mat mat(image.height(), image.width(), CV_8UC3, (cv::Scalar*)image.scanLine(0));
这假设 QImage 是 3 通道,即 RGB888。
如果 QImage 正在消失,那么您需要复制数据,请参阅Qimage to cv::Mat conversion 奇怪的行为。
如果 QImage 是 Format_ARGB32_Premultiplied(首选格式),那么您需要将每个像素转换为 OpenCV 的 BGR 布局。cv::cvtcolor() 函数可以在最新版本中将 ARGB 转换为 RGB。
或者您可以在复制数据之前使用QImage::convertToFormat()转换为 RGB。
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 重新打开它;)
@^ 我已经尝试过以前的解决方案。它似乎不适合我。虽然我得到了一些图像,但它看起来像是一些条形码信息类型的图像。我猜有一些参数不匹配。