How to convert QImage to opencv Mat

前端 未结 5 1527
一个人的身影
一个人的身影 2020-12-14 12:38

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?.

相关标签:
5条回答
  • 2020-12-14 13:05

    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

    cv::Mat mat(image.rows(),image.cols(),CV_8UC3,image.scanline()); This assumes that the Qimage is 3channels, ie RGB888

    If the Qimage is going away then you need to copy the data, see Qimage to cv::Mat convertion strange behaviour

    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

    0 讨论(0)
  • 2020-12-14 13:15

    One year after you issued this question there've been great answers on the internet:

    • Convert between cv::mat and Qimage correctly
    • Converting Between cv::Mat and QImage or QPixmap

    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:

    1. Load image as cv::Mat, if you'd like to display the image, convert to QPixmap using the non-copy method introduced in the second article.
    2. Do your image processing in cv::Mat.
    3. Any time during the workflow you can call upon something like Mat2QPixmap() to get realtime result.
    4. Never convert QPixmap to cv::Mat, there's no sense doing it considering the purpose of each type.
    0 讨论(0)
  • 2020-12-14 13:15

    The answer to this with Qt 5.11 (and probably some earlier versions):

        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)

    0 讨论(0)
  • 2020-12-14 13:23

    My attempt in OpenCV 3.1+ style code:

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-14 13:25

    I'd save the image to disk and reopen it from 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.

    0 讨论(0)
提交回复
热议问题