從IplImage到QImage的轉化看效能最佳化

來源:互聯網
上載者:User

      最近對VP的資料協議進行了反思,昨天進行了重大改進,去掉了智能指標的使用,在模組內部使用了緩衝區概念,既方便了記憶體管理又極大地提高了效率,效能檢測結果對比如下:

     改進之前:

/*---------------------------------------------------*/<br />Providers Execute: 0<br />WebCam Provider Execute: 1<br />CvContourExtractor Execute: 6<br />Processors Execute: 145<br />VPImageConsumer Execute: 1<br />Consumers Execute: 2<br />Total: 147<br />/*---------------------------------------------------*/<br />

     改進之後:

/*---------------------------------------------------*/<br />Providers Execute: 0<br />CvContourExtractor Execute: 2<br />Processors Execute: 52<br />VPImageConsumer Execute: 1<br />VPImageConsumer Execute: 0<br />Consumers Execute: 1<br />Total: 53<br />/*---------------------------------------------------*/<br />

上述所有的數字都以cpu刻度為單位。

 

      運行結果還是不太滿意,繼續追蹤各個模組的已耗用時間,結果大大出乎意料,從IplImage到QImage的轉化函數居然這麼耗時,效能檢測結果如下:

/*---------------------------------------------------*/<br />Providers Execute: 0<br />Topo Sort : 1<br />IntProvider Exec: 0<br />FileLoader Exec: 0<br />VideoLoader Exec: 0<br />CvContourExtractor Execute: 1<br />CvContourExtractor Exec: 1<br />CvImage2QImage Exec: 22<br />ImageDisplayer Exec: 0<br />CvImage2QImage Exec: 23<br />ImageDisplayer Exec: 0<br />Processors Execute: 52<br />VPImageConsumer Execute: 0<br />VPImageConsumer Execute: 1<br />Consumers Execute: 1<br />Total: 53<br />/*---------------------------------------------------*/<br />

注意其中的CvImage2QImage的執行時間。 跟蹤那段函數代碼,使用的兩重迴圈執行圖片的轉化:

// 23 clock.<br />void vpCvImageToQImage(const IplImage* pImage, QImage &qImage)<br />{<br />const IplImage* pIplImage = pImage;<br />if(!pIplImage)<br />return;<br />if(qImage.isNull())<br />{<br />int w = pIplImage->width;<br />int h = pIplImage->height;<br />qImage = QImage(w, h, QImage::Format_RGB32);<br />}<br />// 複製像素<br />int x, y;<br />for(x = 0; x < pIplImage->width; ++x)<br />{<br />for(y = 0; y < pIplImage->height; ++y)<br />{<br />CvScalar color = cvGet2D(pIplImage, y, x);<br />int r = color.val[2];<br />int g = color.val[1];<br />int b = color.val[0];<br />qImage.setPixel(x, y, qRgb(r,g,b));<br />}<br />}<br />} // vpCvImageToQImage

     下面是改進的代碼:

 // 4 clock<br />void vpCvImageToQImage(const IplImage* cvimage, QImage &qimage)<br />{<br />if (!cvimage)<br />return;<br />if ( qimage.isNull() )<br />qimage = QImage(cvimage->width, cvimage->height, QImage::Format_RGB32);</p><p>int cvIndex = 0;<br />int cvLineStart = 0;<br />for (int y = 0; y < cvimage->height; y++)<br />{<br />unsigned char red,green,blue;<br />cvIndex = cvLineStart;<br />for (int x = 0; x < cvimage->width; x++)<br />{<br />// DO it<br />red = cvimage->imageData[cvIndex+2];<br />green = cvimage->imageData[cvIndex+1];<br />blue = cvimage->imageData[cvIndex+0];<br />qimage.setPixel(x,y,qRgb(red, green, blue));<br />cvIndex += 3;<br />}<br />cvLineStart += cvimage->widthStep;<br />}<br />} // vpCvImageToQImage

      改進後的效能檢測結果如下:

/*---------------------------------------------------*/<br />Providers Execute: 1<br />Topo Sort : 0<br />IntProvider Exec: 0<br />FileLoader Exec: 0<br />VideoLoader Exec: 1<br />CvContourExtractor Execute: 1<br />CvContourExtractor Exec: 1<br />CvImage2QImage : 3<br />CvImage2QImage Exec: 4<br />ImageDisplayer Exec: 0<br />CvImage2QImage : 4<br />CvImage2QImage Exec: 5<br />ImageDisplayer Exec: 0<br />Processors Execute: 15<br />VPImageConsumer Execute: 0<br />VPImageConsumer Execute: 0<br />Consumers Execute: 0<br />Total: 16<br />/*---------------------------------------------------*/<br />

     原因分析

     第一種情況要差不多23個刻度,然後第二個卻只需要4個刻度,效率差距這麼大。原因在於opencv中圖片儲存是按行存取,所以行優先處理可以更加符合程式的局部性原理。

    尾聲

    對於一個即時性強的系統每秒處理幾十幀,從一幀處理147個刻度到16個刻度。。。

/*---------------------------------------------------*/<br />Providers Execute: 1<br />Topo Sort : 0<br />IntProvider Exec: 0<br />FileLoader Exec: 0<br />VideoLoader Exec: 1<br />CvContourExtractor Execute: 1<br />CvContourExtractor Exec: 1<br />CvImage2QImage : 3<br />CvImage2QImage Exec: 4<br />ImageDisplayer Exec: 0<br />CvImage2QImage : 4<br />CvImage2QImage Exec: 5<br />ImageDisplayer Exec: 0<br />Processors Execute: 15<br />VPImageConsumer Execute: 0<br />VPImageConsumer Execute: 0<br />Consumers Execute: 0<br />Total: 16<br />/*---------------------------------------------------*/

 

一種更好的改進:

通過QImage和IplImage共用記憶體,需要注意的是,QT中的的圖片是RGB格式,而OpenCV網路攝影機獲得圖片是BGR格式。具體實現代碼如下:

void vpCvImageToQImage(const IplImage* frame, QImage &qimage)<br />{<br />if (!frame)<br />return;<br />if ( qimage.isNull() )<br />{<br />// 使用24位<br />// QImage to draw on paint event<br />qimage = QImage( QSize(frame->width, frame->height), QImage::Format_RGB888 );<br />// IplImage * to work with OpenCV functions<br />_cvimage = cvCreateImageHeader( cvSize(frame->width, frame->height), 8, 3 );<br />// Share the buffer between QImage and IplImage *<br />_cvimage->imageData = (char *)qimage.bits();<br />}</p><p>cvCopy(frame, _cvimage, 0);<br />// Convert it from BGR to RGB. QImage works with RGB and cvQueryFrame returns a BGR IplImage<br />cvCvtColor(_cvimage, _cvimage, CV_BGR2RGB);<br />} // vpCvImageToQImage

經測試,對於640*480的幀圖片,轉化為qimage只需要五個刻度左右。

add: 2011/1/14  by RYF 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.