2012-06-13 176 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