在上一講OpenCV學習筆記(四十二)——Mat數據操做之普通青年、文藝青年、暴力青年裏,對Mat內數據的各類讀寫操做進行了速度的比較,都是我本身想到的方法,感受不夠系統,此次整理了下思路,參考了文獻,把能想到的方法進行了彙總,但願能對你們有所幫助。編程
最一般的方法就是數組
img.at<uchar>(i,j) = 255; img.at<Vec3b>(i,j)[0] = 255;
若是你以爲at操做顯得太笨重了,不想用Mat這個類,也能夠考慮使用輕量級的Mat_類,使用重載操做符()實現取元素的操做。多線程
cv::Mat_<uchar> im2= img; // im2 refers to image im2(50,100)= 0; // access to row 50 and column 100
對於一幅圖像的掃描,用at就顯得不太好了,仍是是用指針的操做方法更加推薦。先介紹一種上一講提到過的函數
for (int j=0; j<nl; j++) { uchar* data= image.ptr<uchar>(j); for (int i=0; i<nc; i++) { data[i] = 255; } }
更高效的掃描連續圖像的作法多是把W*H的衣服圖像當作是一個1*(w*h)的一個一維數組,這個想法是否是有點奇葩,這裏要利用isContinuous這個函數判斷圖像內的像素是否填充滿,使用方法以下:學習
if (img.isContinuous()) { nc = img.rows*img.cols*img.channels(); } uchar* data = img.ptr<uchar>(0); for (int i=0; i<nc; i++) { data[i] = 255; }
更低級的指針操做就是使用Mat裏的data指針,以前我稱之爲暴力青年,使用方法以下:測試
uchar* data = img.data; // img.at(i, j) data = img.data + i * img.step + j * img.elemSize();
cv::MatIterator_<Vec3b> it;
或者是:spa
cv::Mat_<Vec3b>::iterator it;
掃描圖像的方法以下:.net
Mat_<Vec3b>::iterator it = img.begin<Vec3b>(); Mat_<Vec3b>::iterator itend = img.end<Vec3b>(); for (; it!=itend; it++) { (*it)[0] = 255; }
仍是用咱們以前使用過的getTickCount、getTickFrequency函數測試速度。這裏我就不一一列舉我測試的結果了,直接上結論。測試發現,好的編寫風格能夠提升50%的速度!要想減小程序運行的時間,必要的優化包括以下幾個方面:線程
(1)內存分配是個耗時的工做,優化之;
(2)在循環中重複計算已經獲得的值,是個費時的工做,優化之;舉例:
int nc = img.cols * img.channels(); for (int i=0; i<nc; i++) {.......} //************************** for (int i=0; i<img.cols * img.channels(); i++) {......}
後者的速度比前者要慢上好多。
(3)使用迭代器也會是速度變慢,但迭代器的使用能夠減小程序錯誤的發生概率,考慮這個因素,能夠酌情優化
(4)at操做要比指針的操做慢不少,因此對於不連續數據或者單個點處理,能夠考慮at操做,對於連續的大量數據,不要使用它
(5)掃描連續圖像的作法多是把W*H的衣服圖像當作是一個1*(w*h)的一個一維數組這種辦法也能夠提升速度。短的循環比長循環更高效,即便他們的操做數是相同的
以上的這些優化可能對於你們的程序運行速度提升並不明顯,但它們畢竟是個獲得速度提高的好的編程策略,但願你們能多采納。
還有就是利用多線程也能夠高效提升運行速度。OpenMP和TBB是兩種流行的APT,不過對於多線程的東西,我是有些迷糊的,呵呵
對於整行或者整列的數據,能夠考慮這種方式處理
img.row(i).setTo(Scalar(255)); img.col(j).setTo(Scalar(255));
這節就先介紹這麼多攻略吧~但願你們喜歡