從零單排Opencv---新舊版本函數變化

剛剛學習Opencv沒多久,網上大部分例子都停留在舊版本,也就是2.1版本之前,引用的頭文件還是cv.h,highgui.h,函數名大部分以cv開頭,舊版本的例子和經典教材非常多。但是,但是舊版本用起來需要很注意內存的申請和釋放,如圖片初始化申請的空間,存儲輪廓的空間等,處理圖片素材不會出太多問題。處理視頻素材經常稍不注意內存溢出。有時編程邏輯不清晰出現在嵌套調用,釋放就更麻煩了。

個人建議使用時最好統一版本,版本混用會出現很多想不到的BUG。Opencv每次版本更新都會對上一個版本的BUG進行修復,優化算法。所以建議用高一點的版本。我這裏用的是2.4.9,比較穩定的一個版本。官方說3.0是最快功能最全的一個版本。

下面記錄一些版本轉換時對應的函數變化:

1、舊版 cvConvertScale(src, dst, scale, shift);
      新版src.convertTo(dst, type, scale, shift);

函數作用:縮放並轉換到另外一種數據類型
dst:目的矩陣
type:需要的輸出矩陣類型,或者更明確的,是輸出矩陣的深度,如果是負值(常用-1)則輸出矩陣和輸入矩陣類型相同
scale和shift:縮放參數,也可以寫爲alpha和beta
這個命令也等價於下面的轉換公式:
dst = src*scale+shift;

其中type=-1時默認新圖像與就圖像格式相同,但是我使用時用-1轉換後圖像輸出不是想要的,我直接規定了格式CV_64F或CV_8U。

ps:opencv中大部分圖像處理函數的輸入圖像格式一般必須是CV_8U或CV_32F

2、傅里葉變換
舊版本:fft2(src, Fourier);
舊版本傅里葉變換一般長這樣,核心函數是cvDFT(src, dst, type),網上百度裏很多,都一個樣。

新版本:dft(src,dst,type);但一般需要加下面的東西
OpenCV中的DFT採用的是快速算法,這種算法要求圖像的尺寸是2、3和5的倍數時處理速度最快。所以需要用getOptimalDFTSize()找到最適合的尺寸,然後用copyMakeBorder()填充多餘的部分。這裏是讓原圖像和擴大的圖像左上角對齊。填充的顏色如果是純色對變換結果的影響不會很大,
Mat padded;
int opWidth = getOptimalDFTSize(srcImg.rows);
int opHeight = getOptimalDFTSize(srcImg.cols);
copyMakeBorder(srcImg, padded, 0, opWidth-srcImg.rows, 0, opHeight-srcImg.cols, BORDER_CONSTANT, Scalar::all(0));
DFT要分別計算實部和虛部,把要處理的圖像作爲輸入的實部、一個全零的圖像作爲輸入的虛部。dft()輸入和輸出應該分別爲單張圖像,所以要先用merge()把實虛部圖像合併,分別處於圖像comImg的兩個通道內。計算得到的實虛部仍然保存在comImg的兩個通道內。
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat comImg;
merge(planes,2,comImg);
dft(comImg, comImg);
一般都會用幅度圖像來表示圖像傅里葉的變換結果(傅里葉譜)。
        幅度的計算公式:magnitude = sqrt(Re(DFT)^2 + Im(DFT)^2)。
        由於幅度的變化範圍很大,而一般圖像亮度範圍只有[0,255],容易造成一大片漆黑,只有幾個點很亮。所以要用log函數把數值的範圍縮小。
split(comImg, planes);
magnitude(planes[0], planes[1], planes[0]);
Mat magMat = planes[0];
magMat += Scalar::all(1);
log(magMat, magMat);


3、舊版:cvSplit(Fourier, ImageRe, ImageIm, 0, 0);
新版:
vector<Mat>channels;
split(comImg,channels);
ImageRe = channels.at(0);
ImageIm = channels.at(1);

函數作用:通道分離


4、計算傅里葉振幅譜

舊版:實部和虛部平方和再開方,得到振幅譜存到tmp3中
cvPow(ImageRe, tmp1, 2.0);
cvPow(ImageIm, tmp2, 2.0);
cvAdd(tmp1, tmp2, tmp3);
cvPow(tmp3, tmp3, 0.5);

新版:

split(complexI, planes);                                  // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
magnitude(planes[0], planes[1], planes[0]);  // planes[0] = magnitude
Mat magI = planes[0];

5、剩下的是一些簡單的變化,變化不大

舊版:CvCapture* pCapture = cvCreateFileCapture("gu3.avi");

新版:VideoCapture capture("gu3.avi");

函數作用:讀取視頻文件。(文件已放入工程目錄下)


舊版:cvDiv(ImageIm, tmp3, Sine);
新版:divide(ImageRe, tmp3, Sine);

函數作用:舊版是數組逐元素相除,新版是矩陣對應元素相除。


舊版:cvMul(Residual, Cosine, tmp1);

新版:multiply(Residual,Sine,tmp1);

函數作用:舊版是數組逐元素相乘,新版是矩陣對應元素相乘。


舊版:cvExp(src,dst);

新版:exp(src,dst);

函數作用:指數運算 dst(I)=EXP(src(I))。以自然數底數e爲底的指數。


最大的變化還是Mat,好用,懂的都懂。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章