簡體   English   中英

如何將QImage轉換為opencv Mat

[英]How to convert QImage to opencv Mat

我在 inte.net 上搜索過,但找不到將QImage (或QPixmap )轉換為 OpenCV Mat的方法。 我該怎么做?

任何幫助表示贊賞。

在您提出這個問題一年后,互聯網上已經有了很好的答案:

但在我看來,如果您同時使用 Qt 和 OpenCV,那么鍵入QImage可能只是為了顯示,在這種情況下,您可能想要使用QPixmap因為它已針對顯示進行了優化。 所以這就是我所做的:

  1. 將圖像加載為cv::Mat ,如果要顯示圖像,請使用第二篇文章中介紹的非復制方法轉換為QPixmap
  2. cv::Mat圖像處理。
  3. 在工作流程中的任何時候,您都可以調用Mat2QPixmap()類的東西來獲得實時結果。
  4. 永遠不要將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 到 cv::Mat 轉換奇怪的行為

如果 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::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();
}

我會將圖像保存到磁盤並從 cv 重新打開它;)

@^ 我已經嘗試過以前的解決方案。 它似乎不適合我。 雖然我得到了一些圖像,但它看起來像一些條形碼信息類型的圖像。 我猜有一些參數不匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM