當前位置:首頁 » 操作系統 » opencvsurf演算法

opencvsurf演算法

發布時間: 2023-02-21 06:08:36

『壹』 opencv surf演算法連線顏色怎麼設置一樣

/**
* @file SURF_Homography
* @brief SURF detector + descriptor + FLANN Matcher + FindHomography
* @author A. Huaman
*/

#include <stdio.h>
#include <iostream>
#include <cv.h>
#include "opencv2/core/core.hpp"
#include <opencv2/opencv.hpp>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/nonfree/nonfree.hpp>

using namespace cv;
using namespace std;

#ifdef _DEBUG
#pragma comment (lib, "opencv_calib3d246d.lib")
#pragma comment (lib, "opencv_contrib246d.lib")
#pragma comment (lib,"opencv_imgproc246d.lib")
#pragma comment (lib, "opencv_core246d.lib")
#pragma comment (lib, "opencv_features2d246d.lib")
#pragma comment (lib, "opencv_flann246d.lib")
#pragma comment (lib, "opencv_gpu246d.lib")
#pragma comment (lib, "opencv_highgui246d.lib")
#pragma comment (lib, "opencv_legacy246d.lib")
#pragma comment (lib, "opencv_ml246d.lib")
#pragma comment (lib, "opencv_objdetect246d.lib")
#pragma comment (lib, "opencv_ts246d.lib")
#pragma comment (lib, "opencv_video246d.lib")
#pragma comment (lib, "opencv_nonfree246d.lib")
#else
#pragma comment (lib, "opencv_calib3d246.lib")
#pragma comment (lib, "opencv_contrib246.lib")
#pragma comment (lib, "opencv_imgproc246.lib")
#pragma comment (lib, "opencv_core246.lib")
#pragma comment (lib, "opencv_features2d246.lib")
#pragma comment (lib, "opencv_flann246.lib")
#pragma comment (lib, "opencv_gpu246.lib")
#pragma comment (lib, "opencv_highgui246.lib")
#pragma comment (lib, "opencv_legacy246.lib")
#pragma comment (lib, "opencv_ml246.lib")
#pragma comment (lib, "opencv_objdetect246.lib")
#pragma comment (lib, "opencv_ts246.lib")
#pragma comment (lib, "opencv_video246.lib")
#pragma comment (lib, "opencv_nonfree246.lib")
#endif

int main()
{
initMole_nonfree();//初始化模塊,使用SIFT或SURF時用到
Ptr<FeatureDetector> detector = FeatureDetector::create( "SURF" );//創建SIFT特徵檢測器,可改成SURF/ORB
Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SURF" );//創建特徵向量生成器,可改成SURF/ORB
Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//創建特徵匹配器
if( detector.empty() || descriptor_extractor.empty() )
cout<<"fail to create detector!";

//讀入圖像
Mat img1 = imread("1.jpg");
Mat img2 = imread("2.jpg");

//特徵點檢測
double t = getTickCount();//當前滴答數
vector<KeyPoint> m_LeftKey,m_RightKey;
detector->detect( img1, m_LeftKey );//檢測img1中的SIFT特徵點,存儲到m_LeftKey中
detector->detect( img2, m_RightKey );
cout<<"圖像1特徵點個數:"<<m_LeftKey.size()<<endl;
cout<<"圖像2特徵點個數:"<<m_RightKey.size()<<endl;

//根據特徵點計算特徵描述子矩陣,即特徵向量矩陣
Mat descriptors1,descriptors2;
descriptor_extractor->compute( img1, m_LeftKey, descriptors1 );
descriptor_extractor->compute( img2, m_RightKey, descriptors2 );
t = ((double)getTickCount() - t)/getTickFrequency();
cout<<"SIFT演算法用時:"<<t<<"秒"<<endl;

cout<<"圖像1特徵描述矩陣大小:"<<descriptors1.size()
<<",特徵向量個數:"<<descriptors1.rows<<",維數:"<<descriptors1.cols<<endl;
cout<<"圖像2特徵描述矩陣大小:"<<descriptors2.size()
<<",特徵向量個數:"<<descriptors2.rows<<",維數:"<<descriptors2.cols<<endl;

//畫出特徵點
Mat img_m_LeftKey,img_m_RightKey;
drawKeypoints(img1,m_LeftKey,img_m_LeftKey,Scalar::all(-1),0);
drawKeypoints(img2,m_RightKey,img_m_RightKey,Scalar::all(-1),0);
//imshow("Src1",img_m_LeftKey);
//imshow("Src2",img_m_RightKey);

//特徵匹配
vector<DMatch> matches;//匹配結果
descriptor_matcher->match( descriptors1, descriptors2, matches );//匹配兩個圖像的特徵矩陣
cout<<"Match個數:"<<matches.size()<<endl;

//計算匹配結果中距離的最大和最小值
//距離是指兩個特徵向量間的歐式距離,表明兩個特徵的差異,值越小表明兩個特徵點越接近
double max_dist = 0;
double min_dist = 100;
for(int i=0; i<matches.size(); i++)
{
double dist = matches[i].distance;
if(dist < min_dist) min_dist = dist;
if(dist > max_dist) max_dist = dist;
}
cout<<"最大距離:"<<max_dist<<endl;
cout<<"最小距離:"<<min_dist<<endl;

//篩選出較好的匹配點
vector<DMatch> goodMatches;
for(int i=0; i<matches.size(); i++)
{
if(matches[i].distance < 0.2 * max_dist)
{
goodMatches.push_back(matches[i]);
}
}
cout<<"goodMatch個數:"<<goodMatches.size()<<endl;

//畫出匹配結果
Mat img_matches;
//紅色連接的是匹配的特徵點對,綠色是未匹配的特徵點
drawMatches(img1,m_LeftKey,img2,m_RightKey,goodMatches,img_matches,
Scalar::all(-1)/*CV_RGB(255,0,0)*/,CV_RGB(0,255,0),Mat(),2);

imshow("MatchSIFT",img_matches);
IplImage result=img_matches;

waitKey(0);

//RANSAC匹配過程
vector<DMatch> m_Matches=goodMatches;
// 分配空間
int ptCount = (int)m_Matches.size();
Mat p1(ptCount, 2, CV_32F);
Mat p2(ptCount, 2, CV_32F);

// 把Keypoint轉換為Mat
Point2f pt;
for (int i=0; i<ptCount; i++)
{
pt = m_LeftKey[m_Matches[i].queryIdx].pt;
p1.at<float>(i, 0) = pt.x;
p1.at<float>(i, 1) = pt.y;

pt = m_RightKey[m_Matches[i].trainIdx].pt;
p2.at<float>(i, 0) = pt.x;
p2.at<float>(i, 1) = pt.y;
}

// 用RANSAC方法計算F
Mat m_Fundamental;
vector<uchar> m_RANSACStatus; // 這個變數用於存儲RANSAC後每個點的狀態
findFundamentalMat(p1, p2, m_RANSACStatus, FM_RANSAC);

// 計算野點個數

int OutlinerCount = 0;
for (int i=0; i<ptCount; i++)
{
if (m_RANSACStatus[i] == 0) // 狀態為0表示野點
{
OutlinerCount++;
}
}
int InlinerCount = ptCount - OutlinerCount; // 計算內點
cout<<"內點數為:"<<InlinerCount<<endl;

// 這三個變數用於保存內點和匹配關系
vector<Point2f> m_LeftInlier;
vector<Point2f> m_RightInlier;
vector<DMatch> m_InlierMatches;

m_InlierMatches.resize(InlinerCount);
m_LeftInlier.resize(InlinerCount);
m_RightInlier.resize(InlinerCount);
InlinerCount=0;
float inlier_minRx=img1.cols; //用於存儲內點中右圖最小橫坐標,以便後續融合

for (int i=0; i<ptCount; i++)
{
if (m_RANSACStatus[i] != 0)
{
m_LeftInlier[InlinerCount].x = p1.at<float>(i, 0);
m_LeftInlier[InlinerCount].y = p1.at<float>(i, 1);
m_RightInlier[InlinerCount].x = p2.at<float>(i, 0);
m_RightInlier[InlinerCount].y = p2.at<float>(i, 1);
m_InlierMatches[InlinerCount].queryIdx = InlinerCount;
m_InlierMatches[InlinerCount].trainIdx = InlinerCount;

if(m_RightInlier[InlinerCount].x<inlier_minRx) inlier_minRx=m_RightInlier[InlinerCount].x; //存儲內點中右圖最小橫坐標

InlinerCount++;
}
}

// 把內點轉換為drawMatches可以使用的格式
vector<KeyPoint> key1(InlinerCount);
vector<KeyPoint> key2(InlinerCount);
KeyPoint::convert(m_LeftInlier, key1);
KeyPoint::convert(m_RightInlier, key2);

// 顯示計算F過後的內點匹配
Mat OutImage;
drawMatches(img1, key1, img2, key2, m_InlierMatches, OutImage);
cvNamedWindow( "Match features", 1);
cvShowImage("Match features", &IplImage(OutImage));
waitKey(0);

cvDestroyAllWindows();

//矩陣H用以存儲RANSAC得到的單應矩陣
Mat H = findHomography( m_LeftInlier, m_RightInlier, RANSAC );

//存儲左圖四角,及其變換到右圖位置
std::vector<Point2f> obj_corners(4);
obj_corners[0] = Point(0,0); obj_corners[1] = Point( img1.cols, 0 );
obj_corners[2] = Point( img1.cols, img1.rows ); obj_corners[3] = Point( 0, img1.rows );
std::vector<Point2f> scene_corners(4);
perspectiveTransform( obj_corners, scene_corners, H);

//畫出變換後圖像位置
Point2f offset( (float)img1.cols, 0);
line( OutImage, scene_corners[0]+offset, scene_corners[1]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[1]+offset, scene_corners[2]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[2]+offset, scene_corners[3]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[3]+offset, scene_corners[0]+offset, Scalar( 0, 255, 0), 4 );
imshow( "Good Matches & Object detection", OutImage );

waitKey(0);
imwrite("warp_position.jpg",OutImage);

int drift = scene_corners[1].x; //儲存偏移量

『貳』 opencv 中對於surf 演算法有個函數cvExtractSURF 對於sift有同樣的函數能得到 kepoint關鍵點,和 descriptors

和 descriptors

『叄』 基於opencv的紙張表面質量檢測演算法中

opencv裡面是沒有那種演算法的,它只是提供一些常用的計算函數。具體的演算法,由於你的需求比較特殊,相信應該沒有現成的瑕疵檢測演算法,好在你的需求難度應該不大,通過常用的圖像識別演算法,比如紋理演算法(Gabor演算法)、SURF演算法就可以找到白紙上瑕疵,這些瑕疵都是相當於一張白紙的特徵點嘛!基本思想就是借用圖像識別、匹配過程的思想——找圖像上的特徵點。白紙一般是提取不出特徵點的,要是提取出來了,那就說明白紙上有東西(洞、褶皺或者異物)。

『肆』 surf演算法C語言編寫,要做嵌入式開發,不要C++和基於OPENCV的

surf借鑒了sift中簡化近似的思想,將DOH中的高斯二階微分模板進行了近似簡化,使得模板對圖像的濾波只需要進行幾個簡單的加減法運算,並且,這種運算與濾波模板的尺寸有關。實驗證明surf演算法較sift演算法在運算速度上要快3倍左右。
1積分圖像
surf演算法中要用到積分圖像的概念。藉助積分圖像,圖像與高斯二階微分模板的濾波轉化為對積分圖像的加減運算。積分圖像(IntegralImage)的概念是由viola和Jones提出來的,而將類似積分圖像用於盒子濾波是由Simard等人提出。
積分圖像中任意一點(i,j)的值為ii(i,j)為原圖像左上角到任意點(i,j)相應的對角線區域灰度值的總和即:
公式中,I(x`,y`)表示原圖像中點(i`,j`)的灰度值,ii(x,y)可以由下面兩公式迭代計算得到:
公式中,S(x,y)表示一列的積分,且S(i,-1)=0,ii(-1,j)=0.求積分圖像,只需對原圖像的所有像素素進行一遍掃描。下面的代碼為c++語言的實現
pOutImage[0][0]=pInImage[0][0];
for(intx=1,x<nWidth;i++)
{
pOutImage[x][0]=pInImage[x-1][0]+pInImage[x][0];
}
for(inty=1;y<nHeight;y++)
{
intnSum=0;
for(intx=0;x<nWidth;x++)
{
nSum=pInImage[x][y];
pOutImage[x][y]=pInImage[x][y-1]+nSum;
}
}
如圖表示,在求取窗口w內的像元灰度和時,不管窗口W的大小如何,均可利用積分圖像的4個對應點(i1,j1)(i2,j2)(i3,j3)(i4,j4)的值計算的到。也就是說,求取窗口W內的像元灰度和與窗口的尺寸是無關的。窗口W內的像元的灰度和為
Sum(W)=ii(i4,j4)-ii(i2,j2)-ii(i3,j3)+ii(i1,j1)
下面看以截圖,相信都可以看懂
關於矩形區域內像素點的求和應該是一種簡單重復性運算,採用這種思路總體上提高了效率。為什麼這么說呢?假設一幅圖片共有n個像素點,則計算n個位置的積分圖總共的加法運算有n-1次(注意:可不是次哦,要充分利用遞推思想),將這些結果保存在一個跟原圖對應的矩陣M中。當需要計算圖像中某個矩形區域內的所有像素之和是直接像查表一樣,調出A,B,C,D四點的積分圖值,簡單的加減法(注意只需要三次哦)即可得到結果。反之,如果採用naive的方式直接在原圖像中的某個矩形區域內求和,你想想,總共可能的矩形組合有多少?!!且對於一幅圖像n那是相當大啊,所以2^n
那可是天文數字,而且這裡面絕大部分的矩形有重疊,重疊意味著什麼?在算求和的時候有重復性的工作,其實我們是可以有效的利用已經計算過的信息的。這就是積分圖法的內在思想:它實際上是先計算n個互不重疊(專業點說是不相交)的矩形區域內的像素點求和,充分利用這些值(已有值)計算未知值,有點類似遞推的味道...這就完全避免了重復求和運算。
這樣就可以進行2種運算:
(1)任意矩形區域內像素積分。由圖像的積分圖可方便快速地計算圖像中任意矩形內所有像素灰度積分。如下圖2.3所示,點1的積分圖像ii1的值為(其中Sum為求和):
ii1=Sum(A)

同理,點2、點3、點4的積分圖像分別為:
ii2=Sum(A)+Sum(B);ii3=Sum(A)+Sum(C);ii4=Sum(A)+Sum(B)+Sum(C)+Sum(D);
矩形區域D內的所有像素灰度積分可由矩形端點的積分圖像值得到:
Sum(D)=ii1+ii4-(ii2+ii3)(1)
(2)特徵值計算
矩形特徵的特徵值是兩個不同的矩形區域像素和之差,由(1)式可以計算任意矩形特徵的特徵值,下面以圖2.1中特徵原型A為例說明特徵值的計算。

如圖2.4所示,該特徵原型的特徵值定義為:

Sum(A)-Sum(B)

根據(1)式則有:Sum(A)=ii4+ii1-(ii2+ii3);Sum(B)=ii6+ii3-(ii4+ii5);

所以此類特徵原型的特徵值為:

(ii4-ii3)-(ii2-ii1)+(ii4-ii3)-(ii6-ii5)

另示:運用積分圖可以快速計算給定的矩形之所有象素值之和Sum(r)。假設r=(x,y,w,h),那麼此矩形內部所有元素之和等價於下面積分圖中下面這個式子:

Sum(r)=ii(x+w,y+h)+ii(x-1,y-1)-ii(x+w,y-1)-ii(x-1,y+h)

由此可見,矩形特徵特徵值計算只與此特徵端點的積分圖有關,而與圖像坐標值無關。對於同一類型的矩形特徵,不管特徵的尺度和位置如何,特徵值的計算所耗費的時間都是常量,而且都只是簡單的加減運算。其它類型的特徵值計算方法類似。

『伍』 opencv檢測缺陷用哪些演算法

根據不同的需求來進行不同的處理
1 空洞 這個肯定是像素顏色和周邊的不同 建議用閾值分割 然後輪廓檢測
2 褶皺 這個褶皺肯定會有梯度的變化 建議檢測邊緣 再計算褶皺的梯度信息
3 劃痕 這個和上一個問題相似 但是也有不同 應該是梯度的方向和強度不同(一個是凹一個是凸)
4 斑點 如果只是點點星星的 opencv里也有很多角點檢測演算法 比如 surf fast ORB等

『陸』 關於opencv SURF演算法 特徵點匹配率

surf演算法對圖片提取特徵點以後是可以獲得到提取的數量的。但是匹配完成後雖然能夠獲得匹配成功的數量,但是是不是真的准確就無法保證了。比如兩張完全不相關圖片,特徵點匹配也可能會有幾個能夠匹配成功的,但是在物理意義上,這兩張圖片並不相同,特徵點雖然距離很近但是並不正確。

『柒』 OpenCV+python特徵提取演算法與圖像描述符之SIFT / SURF / ORB

演算法效果比較博文

用於表示和量化圖像的數字列表,簡單理解成將圖片轉化為一個數字列表表示。特徵向量中用來描述圖片的各種屬性的向量稱為特徵矢量。

參考
是一種演算法和方法,輸入1個圖像,返回多個特徵向量(主要用來處理圖像的局部,往往會把多個特徵向量組成一個一維的向量)。主要用於圖像匹配(視覺檢測),匹配圖像中的物品。

SIFT論文
原理
opencv官網解釋
實質是在不同的尺度空間上查找關鍵點(特徵點),並計算出關鍵點的方向。SIFT所查找到的關鍵點是一些十分突出,不會因光照,仿射變換和噪音等因素而變化的點,如角點、邊緣點、暗區的亮點及亮區的暗點等。

尺度不變特徵轉換(Scale-invariant feature transform或SIFT)是一種電腦視覺的演算法用來偵測與描述影像中的局部性特徵,它在空間尺度中尋找極值點,並提取出其位置、尺度、旋轉不變數。
其應用范圍包含物體辨識、機器人地圖感知與導航、影像縫合、3D模型建立、手勢辨識、影像追蹤和動作比對。

對現實中物體的描述一定要在一個十分重要的前提下進行,這個前提就是對自然界建模時的尺度。當用一個機器視覺系統分析未知場景時,計算機沒有辦法預先知道圖像中物體的尺度,因此我們需要同時考慮圖像在多尺度下的描述,獲知感興趣物體的最佳尺度。圖像的尺度空間表達指的是圖像的所有尺度下的描述。

KeyPoint數據結構解析

SURF論文
原理
opencv官網解釋
SURF是SIFT的加速版,它善於處理具有模糊和旋轉的圖像,但是不善於處理視角變化和光照變化。在SIFT中使用DoG對LoG進行近似,而在SURF中使用盒子濾波器對LoG進行近似,這樣就可以使用積分圖像了(計算圖像中某個窗口內所有像素和時,計算量的大小與窗口大小無關)。總之,SURF最大的特點在於採用了Haar特徵以及積分圖像的概念,大大加快了程序的運行效率。

因為專利原因,OpenCV3.3開始不再免費開放SIFT\SURF,需要免費的請使用ORB演算法

ORB演算法綜合了FAST角點檢測演算法和BRIEFF描述符。

演算法原理
opencv官方文檔
FAST只是一種特徵點檢測演算法,並不涉及特徵點的特徵描述。

論文
opencv官方文檔
中文版
Brief是Binary Robust Independent Elementary Features的縮寫。這個特徵描述子是由EPFL的Calonder在ECCV2010上提出的。主要思路就是在特徵點附近隨機選取若干點對,將這些點對的灰度值的大小,組合成一個二進制串,並將這個二進制串作為該特徵點的特徵描述子。文章同樣提到,在此之前,需要選取合適的gaussian kernel對圖像做平滑處理。

1:不具備旋轉不變性。
2:對雜訊敏感
3:不具備尺度不變性。

ORB論文
OpenCV官方文檔

ORB採用了FAST作為特徵點檢測運算元,特徵點的主方向是通過矩(moment)計算而來解決了BRIEF不具備旋轉不變性的問題。
ORB還做了這樣的改進,不再使用pixel-pair,而是使用9×9的patch-pair,也就是說,對比patch的像素值之和,解決了BRIEF對雜訊敏感的問題。
關於計算速度:
ORB是sift的100倍,是surf的10倍。

對圖片數據、特徵分布的一種統計
對數據空間(bin)進行量化

Kmeans

邊緣:尺度問題->不同的標准差 捕捉到不同尺度的邊緣
斑點 Blob:二階高斯導數濾波LoG

關鍵點(keypoint):不同視角圖片之間的映射,圖片配准、拼接、運動跟蹤、物體識別、機器人導航、3D重建

SIFT\SURF

『捌』 surf orb 哪個好 opencv

surf演算法准確一些、但是運算量比orb演算法要大,所以稍慢;orb演算法速度更快,但是結果就沒有那麼准確了。

『玖』 opencv 用python 使用surf演算法計算出了最後的結果,繪出了圖像,之後怎麼找出目標位置

這個用不著SURF。只需要聚色彩就可以了。芬達主要由橙色與黑色組成。只需要按橙色與黑色設計兩個向量指標,立刻就可以看出來,只有芬達同時符合這兩個峰值。

你顯然沒有做過數據處理的經驗。這個東西。甚至用不著opencv的核心功能。只需要用它的圖像採集然後處理一下圖像就可以了。

當然芬達是一個對象。你還需要將對象與背景分享出來。這個時候,可以使用一些類似人臉識別的演算法。

但是換作是我自己。顯然不會這樣做。我只需要計算顏色距離相似度。把相似的顏色自動分成區域。然後計算區域的重心與離散度。就可以輕松分離出哪些區域是背景,哪些是對象。

熱點內容
手機存儲卡不能寫入 發布:2025-08-02 14:01:11 瀏覽:26
weblogiclinux安裝 發布:2025-08-02 13:59:41 瀏覽:567
vivo手機為什麼不能設置鎖屏密碼 發布:2025-08-02 13:52:05 瀏覽:645
php二進制加密 發布:2025-08-02 13:51:04 瀏覽:280
水強行壓縮 發布:2025-08-02 13:37:23 瀏覽:988
nginx內網訪問 發布:2025-08-02 13:35:06 瀏覽:31
如何用解壓密碼解壓手機文件 發布:2025-08-02 13:32:56 瀏覽:217
lex製作編譯器 發布:2025-08-02 13:31:52 瀏覽:6
php把數組寫入文件 發布:2025-08-02 13:25:51 瀏覽:281
網頁升級訪問狼 發布:2025-08-02 13:20:37 瀏覽:753