1. 程式人生 > >OpenCV學習筆記——《OpenCV3程式設計入門》讀書筆記

OpenCV學習筆記——《OpenCV3程式設計入門》讀書筆記

這篇讀書筆記,主要記錄我閱讀《OpenCV3程式設計入門》的讀書筆記,作者毛星雲寫的這本書十分適合接觸OpenCV的初學者,雖然理論性的內容是簡要概括,但還是可以大致的理解。。此書最好的就是提供了大量的完整例子的程式碼,對初學者入門相當有幫助,建議各位OpenCV的初學者可以認真閱讀一下這本書,會對OpenCV的程式設計有個一個整體的初步認識。

OpenCV學習筆記

    chap1 邂逅OpenCV

1.using namespace cv;  //包含cv名稱空間

2.Mat srcImage = ("1.jpg"); //載入影象

3.imshow("[原始圖]",srcImage);//顯示影象

4.waitKey(0);   //等待任意按鍵按下

5.waitKey(6000); //等待6000ms後窗口自動關閉

6.blur(srcImage,dstImage,Size(7,7)); //均值濾波操作

7. cvtColor(srcImage, grayImage, CV_BGR2GRAY ); //將原影象轉換為灰度影象

8.讀入視訊

  法一:VideoCapturecapture("1.avi");

  法二:VideoCapturecapture; capture.open("1.avi");

9. 呼叫攝像頭讀入視訊

  VideoCapture capture(0);

chap2. 啟程前的認知準備

chap3. HighGUI圖形使用者介面初步

1.OpenCV中的C++類和函式都是定義在名稱空間cv之內的,所以在程式碼開頭  的位置加上using namespacecv; 這句程式碼。

2.Mat類是用於儲存影象以及其他矩陣資料的資料結構,預設尺寸為0

3. 影象的載入:Matimread(const string& filename, int flags=1);第一個引數conststring& filename指的是載入圖片的路徑名;第二個引數int flags是載入識別符號,指定一個夾在影象的型別,預設為1,flags>0返回3通道彩色影象,flags=0返回灰度影象,flags<0返回Alpha通道的載入影象。

4.影象的顯示:imshow(conststring& winname, InputArray mat);第一個引數指的是要顯示視窗標識名稱;第二個引數填要顯示的影象。

5. 建立視窗namedWindow

namedWindow(cosnt string& winname, int flags=WINDOW_AUTOSIZE);

第一個引數填寫被用作視窗識別符號的視窗名稱;第二個引數視窗的標識,可以填如下幾種值:WINDOW_NORMAL使用者可以改變視窗的大小,WINDOW_AUTOSIZE設定這個值(為預設值),視窗大小會自動調整以適應所顯示的影象,且使用者沒法手動改變視窗大小。

6. 輸出影象到檔案imwrite()函式

imwrite(cosntstring& filename, InputArray img, const vector<int>&params=vecror<int>() );

第一個引數,填需要的寫入的檔名,要帶上字尾,如“123.jpg”;第二個引數,一般填一個Mat型別的影象資料;第三個引數,表示特定格式儲存的引數編碼,預設值vecror<int>()

7.建立滑動條:creatTrackbar()函式

creatTrackbar( conststring& trackbarname, conststring& winname, int* value, intcount, TrackbarCallback onChange=0, void* userdata=0)

第一個引數,trackbarname,軌跡條的名字;

第二個引數,winname,視窗的名字,表示軌跡條依附到的視窗;

第三個引數,value,指向整形的指標,表示滑塊的位置,建立時滑塊的初始位置就是該變數當前的值;

第四個引數,count,表示滑塊可以達到的最大位置的值;

第五個引數,onChange,指向回撥函式的指標,滑塊位置改變,這個函式都進行回撥,且這個函式的原型必須為voidXXXX(int, void*),第一個引數是軌跡條的位置,第二個引數是使用者資料。若回撥是NULL指標,則表示沒有回撥函式的作用,僅第三個引數value有變化;

第六個引數,userdata,預設值0。

chap4. OpenCV資料結構與基本繪圖

1.使用函式clone()或者copyTo() 來複制一幅影象的矩陣

Mat F= A.clone();       Mat G; A.copyTo(G)

2. 矩形的表示:Rect類

Rect類的成員有x,y,width,height,分別為左上角點的座標和矩形的寬、高。

contains(Point)判斷點是否在矩形內;

inside(Rect)判斷矩形是否在該矩形內;

tl()返回左上角點座標; br()返回右下角點座標

3.顏色空間轉換:cvtColor()函式

cvtColor(InputArraysrc, OutputArray dst, int code, int dstCn=0)

第一個引數,輸入影象;

第二個引數,輸出影象;

第三個引數,顏色空間轉換的識別符號;

第四個引數,目標影象的通道數,若為0,則表示其取源影象的通道數。

4. 建立空白的Mat影象

MatatomImage=Mat::zeros( 長, 寬, CV_8UC3 );

5.OpenCV預設的圖片通道儲存順序是BGR,即藍綠紅,而不是RGB

chap5. core元件進階

1. 按原始圖的引數規格來建立建立效果圖

MatsrcImage = imread("1.jpg");

Mat dstImage;

dstImage.create(srcImage.rows,srcImage.cols,srcImage.type());//效果圖的大小、型別與原圖片相同

2.計時函式 getTickCount()和getTickFrequency()

//記錄起始時間

doubletime0 = static_cast<double>(getTickCount()); 

//計算執行時間並輸出

time0= ((double)getTickCount() - time0)/getTickFrequency();

cout<<"\t此方法執行時間為:"<<time0<<"秒"<<endl;  //輸出執行時間

3.Mat類的公有成員變數cols和rows給出了影象的寬和高

srcImage.rows

srcImage.cols

4.Mat類的成員函式channels()用於返回影象的通道數;

灰度圖的通道數為1,彩色圖的通道數為3.

5. Mat類提供ptr函式得到影象任意行的首地址

uchar*data = outputImage.ptr<uchar>(i); //獲取第i行的首地址

6.訪問影象中的畫素P100-114

7. 感興趣區域(ROI,regionof interest)

兩種方法定義ROI:

第一種,用表示矩形區域的Rect,它指定矩形的左上角座標和矩形的長寬

MatimageROI;

imageROI=image(Rect(500,250,logo.cols,logo.rows));

第二種,指定感興趣行或者列的範圍(Range),Range是指從起始索引到終止索引(不包括終止索引)的一連段連續序列。

imageROI=image(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols))

8. MatimageROI=image(Rect(500,250,logo.cols,logo.rows));

Matmask=imread("logo.jpg",0);//載入掩膜,必須為灰度圖

logoImage.copyTo(imageROI,mask);//將掩膜複製到ROI

9. 計算陣列加權和:addWeighted()函式 (影象線性混合)

voidaddWeighted(InputArray src1, double alpha, InputArray src2, double beta, doublegamma, OutputArray dst, int dtype=-1);

第一個引數,src1,表示要加權的第一個陣列;

第二個引數,alpha,表示第一個陣列的權重;

第三個引數,src2,第二個陣列,需要和第一個陣列有相同的尺寸和通道數;

第四個引數,beta,第二個陣列的權重;

第五個引數,gamma,一個加到權重和上的標量值;

第六個引數,dst,輸出的陣列,和輸入的兩個陣列有相同的尺寸和通道數;

第七個引數,dtype,輸出陣列的可選深度,預設值-1.

數學公式表達:

dst =src1[I]*alpha + src2[I]*beta + gamma;

10. 通道分離:split()函式

將一個多通道陣列分離成幾個單通道陣列

voidsplit(const Mat&src, Mat*mvbegin);

或者 voidsplit(InputArray m, OutputArrayOfArrays mv);

第一個引數,m或者src,填需要進行分離的多通道陣列;

第二個引數,mv,填輸出陣列或者輸出的vector容器

eg.

vector<Mat>channels;

MatimageBlueChannel;

MatimageGreenChannel;

MatimageRedChannel;

srcImage4=imread("dota.jpg");

split(srcImage4,channels);//分離彩色通道,將3通道影象轉成3個單通道影象;

imageBlueChannel=channels.at(0);

imageGreenChannel=channels.at(1);

imageRedChannel=channels.at(2);

11. 通道合併:merge()函式,是split()函式的逆向操作

將多個數組合併成一個多通道的陣列

voidmerge(InputArrayOfArrays mv,OuoputArray dst);

eg.接著上面

merge(channels,mergeImage);

12. 建立0矩陣的影象

g_srcImage= imread( "1.jpg");

g_dstImage= Mat::zeros( g_srcImage.size(), g_srcImage.type() );

13. 一般的影象處理運算元都是一個函式,它接受一個或多個輸入影象,併產生輸出影象

14.g(i,j)=a*f(i,j)+b;

a稱為增益(gain),對比度

b稱為偏置(bias),亮度

15. 訪問影象的每一個畫素,使用這樣的語法image.at<Vec3b>(y,x)[c]

y是畫素所在的行,x是畫素坐在的列,c是B,G,R(對應0,1,2)其中之一;

eg.

// 三個for迴圈,執行運算 g_dstImage(i,j) = a*g_srcImage(i,j)+ b

         for(inty = 0; y < g_srcImage.rows; y++ )

         {

                   for(intx = 0; x < g_srcImage.cols; x++ )

                   {

                            for(intc = 0; c < 3; c++ )

                            {

                                     g_dstImage.at<Vec3b>(y,x)[c] = saturate_cast<uchar>((g_nContrastValue*0.01)*( g_srcImage.at<Vec3b>(y,x)[c]) + g_nBrightValue );

                            }

                   }

         }

★運算結果可能會超出畫素取值範圍(溢位),還可能是非整數(如果是浮點數的話),所以用saturate_cast對結果進行轉換,確保它為有效值。

16. //輸出一些幫助資訊

         cout<<endl<<"\t執行成功,請調整滾動條觀察影象效果\n\n"

                   <<"\t按下“q”鍵時,程式退出\n";

         //按下“q”鍵時,程式退出

         while(char(waitKey(1))!= 'q') {}

17. Mat srcImage = imread("1.jpg",0); //1】以灰度模式讀取原始影象並顯示

18. 離散傅立葉變換DFT  P135

19.getOptimalDFTSize 返回給定向量尺寸的傅立葉最優尺寸大小

20.copyMakeBorder 擴充影象邊界

21.magnitude 計算二維向量的幅值

22.log 計算每個陣列元素絕對值的自然對數

23.normalize 進行矩陣歸一化

chap6. 影象處理

1. 平滑處理(smoothing)也稱模糊處理(bluring)

用途:減少影象上的噪點、失真、降低影象解析度。

2. 影象濾波,儘量保留影象細節特徵的條件下對目標影象的噪聲進行抑制。

3. 訊號或者影象,能量大多集中在幅度譜的低頻和中頻段,在高頻段,有用的資訊經常被噪聲淹沒,所以,一個能降低高頻成分幅度的濾波器就能夠減弱噪聲的影響。

4. 平滑濾波是低頻增強的空間域濾波技術,目的:一,模糊;二,消除噪音。

5. 線性濾波

方框濾波,均值濾波,高斯濾波

6. 非線性濾波

中值濾波,雙邊濾波

7.常見的線性濾波

低通濾波器:允許低頻率通過;

高通濾波器:允許高頻率通過;

帶通濾波器:允許一定範圍頻率通過;

帶阻濾波器:阻止一定範圍頻率通過並允許其他頻率通過;

全通濾波器:允許所有頻率通過,僅改變相位關係;

陷波濾波器:阻止一個狹窄頻率範圍通過,一種特殊的帶阻濾波器。

8. 濾波:

是將訊號中特定波段頻率濾除的操作,是抑制和防止干擾的一項重要措施。

9. 濾波可分為低通濾波和高通濾波:

低通就是模糊

高通就是銳化

10. 高斯濾波:指用高斯函式作為濾波函式的濾波操作;

11. 高斯模糊:就是高斯低通濾波。

12. 方框濾波BoxFilter()         P157

13. 均值濾波是方框濾波歸一化(normalized)後的特殊情況

14. 均值濾波的缺陷:不能很好的保護細節,在去噪的同時也破壞了影象的細節部分,影象變的模糊,不能很好地去除噪聲點。

15. 均值濾波:blur函式

16. 高斯濾波:GaussianBlur函式

作用:模糊一張圖片

17. 中值濾波(Medianfilter),非線性濾波,用點鄰域灰度值的中指來代替該畫素點的灰度值,在去除脈衝噪聲、椒鹽噪聲的同時又可以保留影象的邊緣細節。

函式medianBlur()

18. 雙邊濾波(Bilateralfilter),非線性濾波,結合影象的空間鄰近度和畫素值相似度的一種這種處理,同時考慮空域資訊和灰度相似性,達到保邊去噪的目的,具有簡單、非迭代、區域性的特點。

函式bilateralFilter()

19. 膨脹(dilate) 腐蝕(erode)

功能:消除噪聲;分割獨立的影象元素,在影象中連線相鄰的元素;尋找影象中的明顯的極大值區域或極小值區域;求出影象的梯度。

20. 腐蝕和膨脹是對白色部分(高亮部分)而言的,不是黑色部分。

膨脹,對影象中的高亮部分進行膨脹,效果圖擁有比原圖更大的高亮區域;

腐蝕,原圖中的高亮部分被腐蝕,效果圖擁有比原圖更小的高亮區域。

21.膨脹,就是求區域性最大值的操作;

複試,就是求區域性最小值的操作。

22. 函式getStructuringElement返回指定形狀和尺寸的結構元素(核心矩陣)

第一個引數,表示核心的形狀,三種形狀可以選擇,

矩形:MORPH_RECT;

交叉形:MORPH_CROSS;

橢圓形:MORPH_ELLIPSE。

第二個引數,核心的尺寸,eg:   Size(15,15)

第三個引數,錨點的位置

23. 利用morphologyEx函式進行膨脹

Matelement=getStructuringElement(MORPH_RECT,Size(15,15));

morphologyEx(srcimage,dstimage, MORPH_DILATE, element);

24. 利用morphologyEx函式進行腐蝕

morphologyEx(srcimage,dstimage, MORPH_ERODE, element);

25. 開運算,就是先腐蝕後膨脹的過程

數學表示式:dst=open(src,element)=dilate(erode(src,element))

函式:morphologyEx(src,dst,MORPH_OPEN,element);

它可以用來消除小物體,在纖細點分離物體,且在平滑較大物體的邊界的同時不明顯改變其面積。

26. 閉運算,先膨脹後腐蝕的過程

數學表示式:dst=clese(src,element)=erode(dilate(src,element))

函式:morphologyEx(image,image, MORPH_CLOSE, element);

它可以排除小型黑洞(黑色區域)。

27. 形態學梯度,是膨脹圖與腐蝕圖之差

數學表示式:dst=morph-grad(src,element)=dilate(src,element)-erode(src,element)

函式morphologyEx(image,image, MORPH_GRADIENT, element);

28. 頂帽運算,原影象與開運算的結果圖之差

數學表示式:dst=tophat(src,element)=src-open(src,element)

函式 morphologyEx(image, image, MORPH_TOPHAT, element);

它得到的效果圖突出了比原圖輪廓周圍更明亮的區域

29. 黑帽運算,閉運算的結果與原影象之差

數學表示式:dst=blacehat(src,element)=close(src,element)-src

函式 morphologyEx(image, image, MORPH_BLACKHAT, element);

它突出了比原圖輪廓周圍的區域更暗的區域,可以用來分離比鄰近點暗一些的斑塊,效果圖有著非常完美的輪廓。

30. 漫水填充  floodFill

選中和種子點相連的區域,將該區域替換成指定的顏色。

31. 影象金字塔

是影象中多尺度表達的一種,最主要應用於影象的分割,是一種以多解析度來解釋影象的有效但概念簡單的結構。

32. 一幅影象的金字塔是一系列以金字塔形狀排列,解析度逐步降低,且來源於同一張原始圖的影象集合。通過梯次向下取樣獲得,直到達到某個終止條件時停止。

33. 金字塔的底部是待處理影象的高解析度表示,頂部是低解析度的近似。

34. 層級越高,影象越小,解析度越低。

35. 兩種常見的影象金字塔

★高斯金字塔(Gaussianpyramid),用來向下取樣。

★拉普拉斯金字塔(Laplacianpyramid),從金字塔低層影象重建上層未取樣影象,預測殘差,可以對影象進行最大程度還原,配合高斯金字塔一起使用。

二者區別:

★高斯金字塔用來向下取樣影象;

★拉普拉斯金字塔從金字塔底層影象中向上取樣,重建一個影象。

36. 尺寸調整:resize()函式

37. 向上取樣:pyrUp()函式

作用,向上取樣並模糊一張圖片,簡言之,放大一張圖片。

38. 取樣:pyrDown()函式

作用,向下取樣並模糊一張圖片,簡言之,縮小一張圖片。

39. 固定閾值操作:Threshold()函式   p238

40. 自適應閾值操作:adaptiveThreshold()函式

chap7. 影象變換

1. Mat srcImage1=srcImage.clone(); //使用函式clone() 複製一幅影象的矩陣

2.  dstImage.create( srcImage1.size(),srcImage1.type() ); // 1】建立與src同類型和大小的矩陣(dst)

3.  cvtColor( srcImage1, grayImage, CV_BGR2GRAY ); // 2】將原影象轉換為灰度影象

4.  dstImage = Scalar::all(0);//5】將g_dstImage內的所有元素設定為0

5.Canny邊緣檢測:Canny()函式    P250

6.sobel運算元           P253

7.Laplacian運算元      P256

8.convertScaleAbs()函式 用線性變換轉換輸入陣列元素成8位無符號整型

9.scharr濾波器

主要是陪著Sobel運算元的運算而存在

10. 霍夫變換(HoughTransform)

它是影象處理中的一種特徵提取技術,該過程在一個引數空間中通過計算累計結果的區域性最大值得到一個符合該特定形狀的集合作為霍夫變換的結果。

優點:

分割結果Robustness,對資料的不完全或者噪聲不是非常敏感。

11. 霍夫變換運用兩個座標空間之間的變換將在一個空間中具有相同形狀的曲線或直線對映到另一個座標空間的一個點上形成峰值,從而把檢測任意形狀的問題轉化為統計峰值問題。

12. 在使用霍夫變換之前,首先要對影象進行邊緣檢測處理,即霍夫變換的直接輸入只能是邊緣的二值影象。

23.OpenCV支援三種不同的霍夫線變換:

標準霍夫變換(StandardHough Transform, SHT);

多尺度霍夫變換(Multi-ScaleHough Transform, MSHT);

累計概率霍夫變換(ProgressiveProbabilistic Hough Transform, PPHT).

24.HoughLines函式用來呼叫標準霍夫變換(SHT)和多尺度霍夫變換(MSHT)。

25. HoughLinesP函式呼叫累計概率霍夫變換(PPHT)。PPHT執行效率很高,相比於HoughLines,更傾向於HoughLinesP函式。

26. 霍夫線變換的原理 P268

(1)一條直線在影象二維空間,可由兩個變量表示

笛卡爾座標系:用斜率和截距

極座標系:用極徑和極角

對於霍夫變換採用極座標系來表示直線。

(2)對於一個點(x,y),每一對的極座標系的引數,極徑和極角,代表一條通過(x,y)的直線。

(3)對於一個定點(x,y),在極座標下,對極徑極角繪製出所有通過(x,y)的直線,得到的是一條正弦曲線。

(4)如果兩個不同的點進行上述操作,得到的曲線在平面θ-r相交,則意味著它們通過同一條直線。

(5)一條直線可以通過在平面θ-r尋找交於一點的曲線數量來檢測;越多的曲線交於一點,意味著這個交點表示的直線由更多的點組成。一般,可以設定直線上的點的閾值來定義多少條曲線交於一點,這樣才認為檢測到了一條直線。

(6)霍夫變換要做的就是追蹤影象中每個點對應曲線間的角點,若交於一點的曲線數量超過了閾值,則可認為這個角點所代表的引數對(θ,rθ)為原影象中的一條直線。

27. 霍夫圓變換HoughCircles()函式

28. 重對映  remap() 函式

29. 放射變換:wrapAffine()函式

30. 求得仿射變換:

warpMat=getAffineTransform(srcTriangle,dstTriangle);

31. 計算二維旋轉變換矩陣:getRotationMatrix2D()函式

32. 直方圖均衡化:equalizeHist()函式

chap8. 影象輪廓與影象分割修復

1. 尋找輪廓:findContours()函式

2. 繪製輪廓drawContours()函式

3. 尋找凸包:convexHull()函式

4. 使用多邊形將輪廓包圍

返回外部矩形邊界:boundingRect()函式

尋找最小包圍矩形:minAreaRect()函式

尋找最小包圍圓形:minEnclosingCircle()函式

用橢圓擬合二維點集:fitEllipse()函式

逼近多邊形曲線:approxPolyDP()函式

5. 影象的矩

矩的計算:moments()函式

計算輪廓面積:contourArea()函式

計算輪廓長度:arcLength()函式

6. 分水嶺演算法:watershed()函式

7. 影象修補:inpaint()函式

chap9. 直方圖與匹配

1. 計算直方圖:calcHist()函式

2. 找尋最值:minMaxLoc()函式   p348

3. 對比直方圖:compareHist()函式

4.MatND類是用於儲存直方圖的一種資料結構。

5. 計算反向投影:calBackProject()函式

6. 通道複製:mixChannels()函式

7. 模板匹配:matchTemplate()函式

模板匹配是一項在一幅影象中尋找與另一幅模板影象最匹配(相似)部分的技術。

模板匹配不是基於直方圖的,而是通過在輸入影象上滑動影象快,對實際的影象快和輸入影象進行匹配的一種匹配方法。

chap10. 角點檢測

1. 角點,通常定義為兩條邊的角點;

更嚴格的說,角點的區域性鄰域應該具有兩個不同區域的不同方向的邊界;

在實際中,大多數角點檢測方法檢測的是擁有特定特徵的影象點,而不僅僅是“角點”;

這些特徵點在影象中有具體的座標,並具有某些數學特徵,如,區域性最大、最小灰度、某些梯度特徵等。

2. 興趣點(interestpoints),也稱為關鍵點(keypoints)、特徵點(featurepoints)

3. 影象特徵型別可分為三種:邊緣、角點(感興趣關鍵點)、斑點(Blobs)(感興趣區域);

4. 角點:

如果,某一點在任意方向的一個微笑變動都會引起灰度很大的變化,則將其稱之為角點!

5. 角點的具體描述:

a.一階導數(即灰度的梯度)的區域性最大所對應的畫素點;

b.兩條及兩條以上邊緣的交點;

c.影象中梯度值和梯度方向的變化速率都很高的點;

d.角點處的一階導數最大,二階導數為0,它只是了物體邊緣變化的不連續的方向。

6. 當前影象處理領域,角點檢測演算法:

a.基於灰度影象的;

b.基於二值影象的;

c.基於輪廓影象的。

7. 基於灰度影象的角點檢測,可分為三種:

a.基於梯度;

b.基於模板;

c.基於模板梯度。

8. 基於模板的方法,主要考慮畫素領域點的灰度變化,即影象亮度的變化,將與鄰點亮度對比足夠大的點定義為角點。

9. 常見的基於模板的角點檢測演算法有:

a.Kitchen-Rosenfeld角點檢測演算法

b.Harris角點檢測演算法

c.KLT角點檢測演算法

d.SUSAN角點檢測演算法

10.Harris角點檢測是一種直接基於灰度影象的角點提取演算法,穩定性高,尤其對L型角點檢測精度高。

但,由於採用了高斯濾波,運算速度相對較慢,角點資訊有丟失和位置偏移的現象,且角點提取有聚簇現象。

11.Shi-Tomasi運算元是Harriss演算法的改進。

12. 尋找亞畫素角點:cornerSubPix()函式

chap11. 特徵檢測與匹配

1.SUFT, SpeededUp Robust Features,加速版的具有魯棒性的特徵。

2.SUFT是SIFT(尺度不變特徵變換演算法)的加速版;一般來說,標準的SUFT運算元比SIFT運算元快好幾倍;且,在多幅圖片下具有更好的穩定性。

3. 繪製關鍵點:drawKeypoints()函式      p401

4.KeyPoint類      p402

5. //2】使用SURF運算元檢測關鍵點

         intminHessian = 700;//SURF演算法中的hessian閾值

         SurfFeatureDetector detector( minHessian );//定義一個SurfFeatureDetectorSURF特徵檢測類物件

         std::vector<KeyPoint>keyPoint1, keyPoints2;//vector模板類,存放任意型別的動態陣列

         //3】呼叫detect函式檢測出SURF特徵關鍵點,儲存在vector容器中

         detector.detect(srcImage1, keyPoint1 );

         detector.detect(srcImage2, keyPoints2 );

         //4】計算描述符(特徵向量)

         SurfDescriptorExtractor extractor;

         Mat descriptors1, descriptors2;

         extractor.compute(srcImage1, keyPoint1, descriptors1 );

         extractor.compute( srcImage2,keyPoints2, descriptors2 );

6. //5】使用BruteForce進行匹配

         //例項化一個匹配器

         BruteForceMatcher< L2<float>> matcher;

         std::vector< DMatch >matches;

         //匹配兩幅圖中的描述子(descriptors

         matcher.match( descriptors1,descriptors2, matches );

7.

         //6】繪製從兩個影象中匹配出的關鍵點

         Mat imgMatches;

         drawMatches( srcImage1, keyPoint1,srcImage2, keyPoints2, matches, imgMatches );//進行繪製

8. 繪製匹配點:drawMatches()函式    p405

9.BruteForceMatcher類

  用於進行暴力匹配。

10. //6】存下符合條件的匹配結果(即其距離小於2*min_dist的),使用radiusMatch同樣可行

         std::vector< DMatch >good_matches;

         for(inti = 0; i < descriptors_1.rows; i++ )

         {

                   if(matches[i].distance < 2*min_dist )

                   {good_matches.push_back( matches[i]); }

         }

11.ORB特徵提取     p425