2012-06-13 90 views
4

我发现非常类似的主题:how to convert an opencv cv::Mat to qimage,但它不能解决我的问题。cv :: Mat到QImage的转换

我有功能转换CV ::垫的QImage

QImage cvMatToQImg(cv::Mat& mat) 
{ 
    cv::Mat rgb; 
    if(mat.channels()==1) 
    { 
     cv::cvtColor(mat,rgb,CV_GRAY2BGR); 
     cv::cvtColor(rgb,rgb,CV_BGR2BGRA); 
     QImage temp = QImage((unsigned char*)(rgb.data), rgb.cols, 
           rgb.rows,QImage::Format_ARGB32); 

     QImage returnImage = temp.copy(); 
     return returnImage; 
} 

而且它适合我的,但我想使它更有效率。 第一:为什么改变2种cvtColor功能有:

cv::cvtColor(mat,rgb,CV_GRAY2BGRA) 

失败的

QImage returnImage = temp.copy() 

与段错误。

然后如何消除QImage的复制。当我简单地返回临时图像时,我正在收到段错误。

任何其他优化可以在那里完成?这是经常使用的功能,所以我想尽可能快地使用它。

+0

您还没有指定'mat'的图像格式,它甚至是一个24位灰度图像? – cmannett85

+0

大部分我正在使用8bit灰度。但是,越多的案件功能越好。 – krzych

+1

没有必要复制。 QImage是共享指针。 Segfauld不是因为不复制,而是由于对齐不正确。有类似的QImage的构造函数,每行指定附加字节 - 使用这个。 P.S:通过谷歌搜索发现:http://code.google.com/p/qt-opencv-multithreaded/source/browse/trunk/src/MatToQImage.cpp?r=75 –

回答

4

您对问题的解决方案效率不高,尤其是它不如您在链接到的其他问题上发布的代码效率更高。

你的问题是你必须从灰度转换为颜色或RGBA。只要你需要这个对话,自然需要一份数据。

我的解决方案同时进行灰度和颜色之间的转换,以及cv :: Mat和QImage之间的转换。这就是为什么它是您可以获得的最高效率。

在您的解决方案中,您首先尝试转换,然后希望围绕OpenCV数据直接构建QImage以节省第二个副本。但是,您指出的数据是暂时的。只要你离开函数,cv :: Mat free就是它的相关内存,这就是为什么它在QImage中也不再有效。您可以事先手动增加cv :: Mat的引用计数器,但这会打开之后内存泄漏的大门。

最后,您尝试了一个肮脏的解决方案,以更好地解决干净的方式解决问题。

3

这可能是最容易推出自己的解决方案。下面是打算从灰色到RGBA格式的当前OpenCV的实现:

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; 
}; 

这里就是实际cvtColor调用发生:

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)); 

此代码包含在color.cpp文件中imgproc库。

如您所见,由于您未在cvtColor调用中设置dstCn参数,因此它的默认值为dcn = 3。要直接从灰色到BGRA,请将dstCn设置为4.由于OpenCV的默认颜色顺序为BGR,因此您仍需要交换颜色通道以使其看起来正确(假设您从OpenCV函数获取图像数据)。因此,可能需要按照上述示例实现您自己的转换器,或者使用ypnos回答here

另外,看看我的其他answer涉及如何整合OpenCV与Qt。

1

问题是,cv :: Mat和QImage数据不一定是连续的。在OpenCV中 新的数据行的32位边界开始(不知道QImage的 - 我认为这是依赖于系统),所以你不能复制memeory块,除非你的行正好是4字节的整倍数

How to output this 24 bit image in Qt