cv::Mat to QImage conversion

后端 未结 3 1009
说谎
说谎 2021-02-10 08:01

I\'ve found very similiar topic: how to convert an opencv cv::Mat to qimage , but it does not solve my problem.

I have function converting cv::Mat to QImage



        
相关标签:
3条回答
  • 2021-02-10 08:41

    The problem is that both the cv::Mat and QImage data isn't necessarily contiguous. New data rows in opencv start on a 32bit boundary (not sure about QImage - I think it's system dependant) so you can't copy a memeory block unless your rows happen to be exact multiples of 4bytes

    See How to output this 24 bit image in Qt

    0 讨论(0)
  • 2021-02-10 08:59

    Your solution to the problem is not efficient, in particular it is less efficient then the code I posted on the other question you link to.

    Your problem is that you have to convert from grayscale to color, or RGBA. As soon as you need this conversation, naturally a copy of the data is needed.

    My solution does the conversion between grayscale and color, as well as between cv::Mat and QImage at the same time. That's why it is the most efficient you can get.

    In your solution, you first try to convert and then want to build QImage around OpenCV data directly to spare a second copy. But, the data you point to is temporary. As soon as you leave the function, the cv::Mat free's its associated memory and that's why it is not valid anymore also within the QImage. You could manually increase the reference counter of the cv::Mat beforehand, but that opens the door for a memory leak afterwards.

    In the end, you attempt a dirty solution to a problem better solved in a clean fashion.

    0 讨论(0)
  • 2021-02-10 09:02

    It may be easiest to roll your own solution. Below is the current OpenCV implementation for going from gray to RGBA format:

    template<typename _Tp>
    struct Gray2RGB
    {
        typedef _Tp channel_type;
    
        Gray2RGB(int _dstcn) : dstcn(_dstcn) {}
        void operator()(const _Tp* src, _Tp* dst, int n) const
        {
            if( dstcn == 3 )
                for( int i = 0; i < n; i++, dst += 3 )
                {
                    dst[0] = dst[1] = dst[2] = src[i];
                }
            else
            {
                _Tp alpha = ColorChannel<_Tp>::max();
                for( int i = 0; i < n; i++, dst += 4 )
                {
                    dst[0] = dst[1] = dst[2] = src[i];
                    dst[3] = alpha;
                }
            }
        }
    
        int dstcn;
    };
    

    Here is where the actual cvtColor call occurs:

        case CV_GRAY2BGR: case CV_GRAY2BGRA:
            if( dcn <= 0 ) dcn = 3;
            CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
            _dst.create(sz, CV_MAKETYPE(depth, dcn));
            dst = _dst.getMat();
    
            if( depth == CV_8U )
                CvtColorLoop(src, dst, Gray2RGB<uchar>(dcn));
    

    This code is contained in the color.cpp file in the imgproc library.

    As you can see, since you are not setting the dstCn parameter in your cvtColor calls, it defaults to dcn = 3. To go straight from gray to BGRA, set dstCn to 4. Since OpenCV's default color order is BGR, you'll still need to swap the color channels for it to look right (assuming you get your image data from an OpenCV function). So, it may be worth it to implement your own converter possibly following the above example, or using ypnos answer here.

    Also, have a look at my other answer involving how to integrate OpenCV with Qt.

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