導航:首頁 > 源碼編譯 > dlt演算法建立點雲

dlt演算法建立點雲

發布時間:2023-09-03 02:41:09

⑴ 3. 用任意一種編程語言(C/C++/Java/C#/VB.NET)寫出任意一種你所知的排序演算法(比如:冒泡排序, 歸並排

#include<stdio.h>
#include<stdlib.h>
void BubbleSort(int a[], const int first, const int last);//冒泡排序
void InsertSort(int a[], const int first, const int last);//插入排序
void SelectSort(int a[], const int first, const int last);//選擇排序
void MergeSort(int a[], const int p, const int r);//合並排序
void QuickSort(int a[],const int p,const int r);//快速排序
void ShellSort(int a[],const int p,const int r,const int dlta[],const int t);//希爾排序
void HeapSort(int a[],const int p, int r); //堆排序
void StoogeSort(int a[],const int p,const int r);//Stooge排序(不用)演算法復雜度沒算清楚

void main()
{
//插入排序演算法
int a[11] = {6,4,5,3,2,1};
int dlta[]={9,5,3,2,1};
//BubbleSort(a,0,5);
//InsertSort(a,0,5);
//SelectSort(a,0,5);
//MergeSort(a,0,5);
//QuickSort(a,0,5);
//ShellSort(a,0,5,dlta,5);
HeapSort(a,0,5);
//StoogeSort(a,0,5);

for(int i=0; i<=5;i++)
{
printf("%d ",a[i]);
}

}

/************************冒泡排序***********************/
void BubbleSort(int a[], int first, int last)
{
//實現對數組a[]中a[first]到a[last]升序的「冒泡」排序
int i,j,temp;
for(i=first; i<=last; i++)
{
for(j=first; j< last-i; j++)
{
if(a[j] > a[j+1])
{
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}

/************************插入排序***********************/
void InsertSort(int a[], int first, int last)
{
//實現對數組a[]中a[first]到a[last]升序的「插入」排序
//最壞情況為n的平方,,多用於小數組
int i,j,temp;
for(i=first+1; i<=last; i++)
{
temp = a[i];
j = i - 1;
while((j >= 0) && (a[j] > temp))
{
a[j+1] = a[j];
j--;
}
a[j+1] = temp;
}
}

/************************選擇排序***********************/
void SelectSort(int a[], int first, int last)
{
//實現對數組a[]中a[first]到a[last]升序的「選擇」排序
int i, j, temp, num;
for(i=first; i<last; i++)
{
num = i;
for(j=i+1; j<=last; j++)
{
if(a[j] < a[num])
{
num = j;
}
}
if(i != num)
{
temp = a[num];
a[num] = a[i];
a[i] = temp;
}
}
}

/************************合並排序***********************/
void Merge(int a[],const int p,const int q,const int r)
{
//合並排序演算法中的實現合並的子程序
int iLLength,iRLength;
int *L, *R, i, j, k;
iLLength = q - p + 1;
iRLength = r - q;
L = (int *)malloc(iLLength*sizeof(int)); //或者 C++中 new int[iLLength];
R = (int *)malloc(iRLength*sizeof(int)); //或者 C++中 new int[iRLength];
if(L == 0 || R== 0)
{
printf("內存分配失敗!!!");
return;
}
for(i=0; i<iLLength; i++)
{
L[i] = a[p+i];
}
for(j=0; j<iRLength; j++)
{
R[j] = a[q+j+1];
}
i = 0;
j = 0;
for(k=p; k<=r; k++)
{
if((i<iLLength) && (j<iRLength) && (L[i]<=R[j]) || (j == iRLength))
{
a[k] = L[i];
i++;
}
else if(j<iRLength)
{
a[k] = R[j];
j++;
}
}

free(R);free(L);
}
void MergeSort(int a[],const int p,const int r)
{
//合並排序演算法-主程序
//n*lg(n),系數較小
int q;
if(p<r)
{
q = (p+r)/2;
MergeSort(a,p,q);
MergeSort(a,q+1,r);
Merge(a,p,q,r);
}
}

/************************Stooge排序***********************/
void StoogeSort(int a[],const int p,const int r)
{
//Stooge演算法
int temp, k;
if(a[p]>a[r])
{
temp = a[p];
a[p] = a[r];
a[r] = temp;
}
if((p+1) >= r)
{
return;
}
k = (r-p+1)/3;
StoogeSort(a,p,r-k);
StoogeSort(a,p+k,r);
StoogeSort(a,p,r-k);
}

/************************快速排序*********************/
int QuickPartition(int a[],const int p,const int r)
{
//快速排序的(關鍵)分治過程
int temp, x, i, j;
x = a[r];
i = p - 1;
for(j=p; j<r; j++)
{
if(a[j] <= x)
{
i = i + 1;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
temp = a[i+1];
a[i+1] = a[r];
a[r] = temp;
return (i+1);
}
/*
void QuickSort(int a[],const int p,const int r)
{
//快速排序演算法-主程序
//與下面的「尾遞歸實現方法」比較,缺點:右邊數組的遞歸不是必須的,增加了運行堆棧深度和調用開銷
int q;
if(p < r)
{
q = QuickPartition(a, p, r);
QuickSort(a, p, q-1);
QuickSort(a, q+1, r);
}
}
*/
void QuickSort(int a[],int p,const int r)
{
//快速排序演算法-主程序
//「尾遞歸實現方法」是對上面的快速排序主程序實現的一種優化
//系數較小,常用大數組
int q;
while(p < r)
{
q = QuickPartition(a, p, r);
QuickSort(a, p, q-1);
p = q + 1;
}
}

/************************希爾排序**********************/
void ShellInsert(int a[],const int p,const int r, int dk)
{
//希爾排序演算法的關鍵子程序-插入排序子程序
int i, j, temp;
for(i=p+dk; i<=r; i++)
{
if(a[i] < a[i-dk])
{
temp = a[i];
for(j=i-dk; ((j>=0) && (temp < a[j])); j -= dk)
{
a[j+dk] = a[j];
}
a[j+dk] = temp;
}
}
}

void ShellSort(int a[],const int p,const int r,const int dlta[],const int t)
{
//希爾排序演算法-主程序
//按增量序列dlta[]中的前t個增量,實現對數組a[]中a[p]到a[r]的排序
//dlta[]可能取值如:1,2,3,5,9 dala[k]=2^(t-k+1)-1 其中0<=k<=t<=ld(b-1)
//增量序列的最後一個值必須是1
//增量序列中的值沒有除1以外的因子, 其精確時間復雜度:數學上尚未解決的難題
int k;
for(k=0; k<t; k++)
{
ShellInsert(a,p,r,dlta[k]);
}
}

/************************堆排序***********************/
//堆排序,不如快速排序
//但是可用其來實現「優先順序隊列」
int Parent(int i)
{
return ((i+1)/2-1);
}

int Right(int i)
{
return (2*(i+1)-1);
}

int Left(int i)
{
return (2*(i+1));
}

void Max_Heapify(int a[],const int hplast,const int i)
{
int l, r,largest,temp;
l = Left(i);
r = Right(i);
largest = ((l<=hplast) && (a[l]>a[i])) ? l:i;
if((r<=hplast) && (a[r]>a[largest]))
{
largest = r;
}
if(largest != i)
{
temp = a[i];
a[i] = a[largest];
a[largest] = temp;
Max_Heapify(a,hplast,largest);
}

}

void Build_Max_Heap(int a[],const int p, const int r)
{
int i;
for(i = (p+r)/2; i>=p; i--)
{
Max_Heapify(a,r,i);
}
}

void HeapSort(int a[],const int p, int r)
{
int i,temp;
Build_Max_Heap(a,p,r);
for(i = r; i > p; i--)
{
temp = a[p];
a[p] = a[i];
a[i] = temp;
r -= 1;
Max_Heapify(a,r,0);
}
}

⑵ 無人駕駛(三)行人跟蹤演算法

姓名:王夢妮

學號:20021210873

學院:電子工程學院

【嵌牛導讀】本文主要介紹了無人駕駛中所需的拿肢行人跟蹤演算法

【嵌牛鼻子】無人駕駛 環境感知 計算機視覺 卡爾曼濾波 粒子濾波 均值漂移

【嵌牛提問】無人駕駛中所用到的行人跟蹤演算法有哪些

【嵌牛正文】

行人跟蹤一直是視覺領域的一個難點,實際應用環境復雜、遮擋以及行人姿態變化等外界因素都影響著行人跟蹤演算法的研究。行人跟蹤演算法模型主要分為生成模型和判別模型。

(一)生成式模型

生成式模型是一種通過在線學習行人目標特徵,建立行人跟蹤模型,然後使用模型來搜索誤差最小的目標區域,從而完成對行人的跟蹤。這種演算法在構建模型只考慮了行人本身的特徵,忽略了背景信息,沒有做到有效利用圖像中的全部信息。其中比較經典的演算法主要有卡爾曼濾波,粒子濾波,mean-shift等。

(1)卡爾曼濾波演算法

卡爾曼濾波演算法是一種通過對行人構建狀態方程和觀測方程為基礎,計算最小均方誤差來實現跟蹤的最優線性遞歸濾波演算法,通過遞歸行人的運動狀態來預測行人軌跡的變化。

首先設定初始參數,讀取視頻序列。然後進行背景估計,產生初始化背景圖像。然後依次讀取視頻序列,利用Kahnan濾波演算法,根據上一幀估計的背景和當前幀數據得到當前幀的前景目標。然後對前景目標進行連通計算,檢測出運動目標的軌跡。經典的卡爾曼濾波演算法.只能對線性運動的行人實現跟蹤,之後學者改進了卡爾曼濾波演算法,能夠實現對非線性運動的行人進行跟蹤,計算量小,能實現實時跟蹤,但是跟蹤效果不理想。

(2)粒子濾波

    粒子濾波的核心就是貝葉斯推理和重要性采樣。粒子濾波可用於非線性非高斯模型,這是由於貝葉斯推理採用蒙特卡洛法,以某個時間點事件出現的頻率表示其概率。通過一組粒子消宴世對整個模型的後驗概率分布進行近似的表示,通過這個表示來估計整個非線性非高斯系統的狀態。重要性採用就是通過粒子的置信度來賦予不同的權重,置信度高的粒子,賦予較大的權重,通過權重的分布形式表示相似程度。

(3)均值漂移(mean-shift)

    Mean-shift演算法屬於核密度估計法。不必知道先驗概率,密度函數值由采樣點的特徵空間計算。通過計算當前幀目標區域的像素特徵值概率來描述目標模型,並對候選區域進行統一描述,使用相似的函數表示目標模型與候選模板之間的相似度,然後選擇在具有相似函數值最大的候選模型中,您將獲得關於目標模型的均值漂移向量,該向量表示目標從當前位置移動到下一個位置的向量。通過連續迭代地計算均值偏移矢量,行人跟蹤演算法將最終收斂到行人的實際位置,從而實現行人跟蹤。

(二) 判別式模型

判別模型與生成模型不同,行人跟蹤被視為二分類問題。提取圖像中的行人和背景信息,並用於訓練分類器。通過分類將行人從圖像背景中分離出來,以獲取行人的當前位置。以行人區域為正樣本,背景區域為負樣本,通過機器學習演算法對正樣本和負樣本進行訓練,訓練後的分類器用於在下一幀中找到相似度最高的區域,以完成行人軌跡更新。判別式模型不像生成式模型僅僅利用了行人的信息,還利用了背景信息,因此判別式模型的跟蹤效果普遍優於生成式模型。

(1)基於相關濾波的跟蹤演算法

      核相關濾波(KCF)演算法是基於相關濾波的經典跟蹤演算法,具有優良的跟蹤效果和跟蹤速度。這是由於其採用了循環移位的方式來進行樣本生產,用生成的樣本來訓練分類器,通過高斯核函數來計算當前幀行人與下一幀中所有候選目標之間的相似概率圖,找到相似概率圖最大的那個候選目標,就得到了行人的新位置。KCF演算法為了提高跟蹤精度,使用HOG特徵對行人進行描述,同時結合了離散傅里葉變換來降低計算量。

(2)基於深度學習的跟蹤演算法

    近年來,深度學習在圖像和語音方面取得了較大的成果,因此有許多科研人員將深度學習與行人跟蹤相結合,取得了比傳統跟蹤演算法更好的性能。DLT就是一個基於深度學習的行人跟蹤演算法,利用深度模型自動編碼器通過離線訓練的方式,在大規模行人數據集上得到一個行人模型,然後在線對行人進行跟蹤來微調模型。首先通過粒子濾波獲取候選行人目標,然後利用自動編碼器進行預測,最終得到行人的預測位置即最大輸出值的候選行人目標位置。2015年提出的MDNet演算法採用了分域訓練的方式祥森。對於每個類別,一個單獨的全連接層用於分類,並且全連接層前面的所有層都是共享,用於特徵提取。2017年提出的HCFT演算法使用深度學習對大量標定數據進行訓練,得到強有力的特徵表達模型,結合基於相關濾波的跟蹤演算法,用於解決在線進行跟蹤過程中行人樣本少、網路訓練不充分的問題。此外,通過深度學習提取特徵,利用數據關聯的方法來實現跟蹤的演算法,其中最為著名的就JPDAF與MHT這兩種方法。

⑶ 區塊鏈行業應用有哪些

區塊鏈技術有廣泛的應用領域,以下是一些主要的行業應用:1. 加密貨幣:比特幣、以太幣等數字貨幣的發行與交易。2. 金融:用於交易結算、證券交易、銀行貸款、交易融資等業務。3. 物流和供租並啟應鏈管理: 用於優化物流過程和減少物流成本。4. 物聯網:與物聯網相關的數據、應用和通信,保證數據的安全和一致性。5. 版權管理: 用於版權信息的打包、存儲、管理和交易。6. 選舉: 用於公開、透明、安全的虛擬選舉。7. 公共服弊如務:政府的文件和數據集的管理,例如出生證明、死蔽擾亡證明等。8. 醫療:用於管理醫療檔案和提供更好的醫療服務。9. 慈善事業:用於捐贈和籌款。10. 游戲:游戲虛擬貨幣的發行管理。

⑷ 編寫程序用直接插入排序的演算法進行排序。

#include<stdio.h>
#include<time.h>
#include<math.h>
#include<malloc.h>

void BubbleSort(int *L,int N)
{ //冒泡
int i,j;
int t;

for(i=1;i<=N;i++)
{
for(j=N;j>i;j--)
if(L[j]<L[j-1])
{
t=L[j];
L[j]=L[j-1];
L[j-1]=t;
}
}
}

int SelectMinKey(int *L,int N,int n)
{
int i,min=n;

for(i=n+1;i<=N;i++)
if(L[i]<L[min])
min=i;

return min;
}

void SelectSort(int *L,int N)
{ //選擇
int i,j;
int t;

for(i=1;i<N;i++)
{
j=SelectMinKey(L,N,i);
if(i!=j)
{
t=L[i];
L[i]=L[j];
L[j]=t;
}
}
}

void InsertSort(int *L,int N)
{ //插入
int i,j;

for(i=2;i<=N;i++)
{
if(L[i]<L[i-1])
{
L[0]=L[i];
L[i]=L[i-1];
for(j=i-2;L[0]<L[j];j--)
L[j+1]=L[j];
L[j+1]=L[0];
}
}
}

void ShellInsert(int *L,int N, int dk)
{ // 對順序表L作一趟希爾插入排序。本演算法對演算法10.1作了以下修改:
// 1. 前後記錄位置的增量是dk,而不是1;
// 2. r[0]只是暫存單元,不是哨兵。當j<=0時,插入位置已找到。
int i,j;
for(i=dk+1;i<=N;++i)
if(L[i]<L[i-dk])
{ // 需將L.r[i]插入有序增量子表
L[0]=L[i]; // 暫存在L.r[0]
for(j=i-dk;(j>0&&L[0]<L[j]);j-=dk)
L[j+dk]=L[j]; // 記錄後移,查找插入位置
L[j+dk]=L[0]; // 插入
}
} // ShellInsert

void ShellSt(int *L,int N, int dlta[], int t)
{ // 演算法10.5
// 按增量序列dlta[0..t-1]對順序表L作希爾排序。
for(int k=0;k<t;++k)
ShellInsert(L,N, dlta[k]); // 一趟增量為dlta[k]的插入排序
} // ShellSort

void ShellSort(int *L,int N)
{ //希爾
int t=(int)log(N);
int k,*dlta;

dlta=(int*)malloc(t*4); //產生增量序列
for(k=0;k<t;k++)
dlta[k]=(int)pow(2,t-k)-1;

ShellSt(L,N,dlta,t);
}

int main()
{
int N=250;
int i,j,k;
int t;
int ti[16];
int *L;

srand(time(NULL));

printf("長度\t|冒泡\t|選擇\t|插入\t|希爾\n");
printf("--------+-------------------------------------------------------------");
for(j=0;N<100000;j++)
{
L=(int *)malloc((N+1)*4);

t=0;

for(i=1;i<=N;i++)
L[i]=rand();
ti[t++]=clock();
BubbleSort(L,N);
ti[t++]=clock();

for(i=1;i<=N;i++)
L[i]=rand();
ti[t++]=clock();
SelectSort(L,N);
ti[t++]=clock();

for(i=1;i<=N;i++)
L[i]=rand();
ti[t++]=clock();
InsertSort(L,N);
ti[t++]=clock();

for(i=1;i<=N;i++)
L[i]=rand();
ti[t++]=clock();
ShellSort(L,N);
ti[t++]=clock();

printf("\n%d\t",N);
for(k=0;k<4;k++)
printf("| %d\t",(ti[2*k+1]-ti[2*k]));

N*=5;
}
printf("\n\n");
}

//這是我們當年學數據結構時我自己寫的,給你改了一下,輸出是對隨機產生一些數,對四種演算法進行比較,有問題可以hi我啊

⑸ 全局視覺定位系統研究的意義

全局視覺定位

1. 引言
自主機器人是機器人研究的重點方向,定位和導航是自主機器人研究的核心問題。機器人在執行任務過程中需要確定自身當前位置,根據目標位置和當前位置之間的關系計算如何到達目的地完成任務,其中前者要解決的是自定位問題,後者是導航問題,本文主要研究前者。基於視覺的定位技術還能幫助盲人、視弱以至普通人確定自身位置。 環境模型是定位的基礎。基於模型的定位方法包括基於環境三維模型和基於拓撲地圖的定位方法。環境三維模型的建模過程非常復雜,特別是在室外的場景中建模可能遇到極大的困難。拓撲定位用圖的形式來表示環境模型,其中圖中的節點表示環境中的地點,連接節點的邊表示地點之間的聯系,拓撲定位目的是確定機器人當前的位置與地圖中的哪個節點最近,也就是機器人處於哪個地點。

在無人駕駛中,感知、定位、規劃決策、控制是四個基本的系統模塊。由於當前演算法還無法實現絕對的智能,因此依然需要大量的先驗知識來提高模塊性能、魯棒性,以實現安全的自動駕駛。其中,高精地圖是對道路及周邊環境先驗知識的集成。而建立在地圖之上的准確定位,是判斷行車狀況的重要依據,為後續的感知、規劃決策提供有力支撐。
用於定位的主要數據源目前主要有 GPS、激光雷達、視覺、毫米波雷達。對於視覺而言,雖然目前還沒有一套產業內公認的足夠可靠的定位方案,但是在這方面探索從未停止過,主要原因如下:
安全性是無人駕駛系統最重要的指標,因此大部分功能的實現,都是多源數據、不同演算法結果的耦合。沒有哪種感測器方案是完美的,比如 GPS RTK 作為廣泛使用的方案,容易受衛星狀況、天氣狀況、 數據鏈傳輸狀況影響,在隧道內、室內和高樓密集區無法使用。再者,激光雷達雖然具有運算量小,提供深度信息,不受光照影響等優點,但信息稀疏,造價目前還十分昂貴,還不具備大批量車輛裝配能力。相比較而言,攝像頭提供的視覺信息,雖然會受到光照、天氣影響,但是成本低,內容豐富,是目前輔助駕駛方案主要數據源,在地圖定位方面也具有很大潛力。

由於主流基於視覺定位演算法的核心思想一脈相承,所以本文僅從一系列重要演算法框架組件角度,介紹了目前實踐中最常用的、基於特徵點的全局定位演算法,即在地圖坐標系下進行定位。本文省略了其中涉及到的優化、幾何約束公式推導,旨在給同學們一個定位演算法的宏觀介紹,具體細節可以參考相關文獻和書籍。

2. 基於特徵點的全局定位演算法視覺全局定位,指的是根據當前圖像,求出相機在地圖坐標系中的 6 個自由度 (Degree of freedom, DoF) 位姿 (Pose) , 即 (x, y, z) 坐標,以及環繞三個坐標軸的角度偏轉 (yaw, pitch, roll) 。目前主要可以分類為基於 3D 結構的方法、基於 2D 圖像的方法、基於序列圖像的方法、基於深度學習的方法。其中,基於深度學習的方法屬於端到端 (End-to-end) 的方法,而其它多階段 (Multi-stage) 非端到端方法雖然流程有所差別,但演算法思路大都如 Fig. 1 所示:
Figure 1: 根據查詢圖像,計算 2D-3D 轉換矩陣,求解相機位姿
基於已建的地圖,匹配歷史中最相似的地圖子集(圖像/點雲/特徵點),根據匹配到的地圖子集所提供的歷史位姿真值、特徵點坐標真值,計算點對間的變換矩陣,求解當前相機位姿。

所以,其核心包含圖像描述、建圖查詢、特徵匹配,位姿計算四個方面。這里僅僅是技術層面的宏觀分類,實際演算法框架不一定按照此順序執行,而學者在研究中主要針對這些技術進行改進。整體而言,基於特徵點的圖像描述基本成熟,發展較少。而位姿計算由於是基於幾何約束的優化問題,所以方法也較為固定。相對地,建圖查詢和特徵匹配中改進技術較多。根據數據源不同,建圖查詢、匹配可以是2D-2D,2D-3D,3D-3D。2D 圖像由相機得到,3D 點雲可以由提供深度的雙目相機、RGB-D 相機產生。

2.1 特徵點提取
2D 圖像本身是一個由亮度、色彩組成的矩陣,對視角、光照、色調變化等很敏感,直接使用十分困難。所以,一般會使用具有代表性的點進行相關計算。人們希望這樣的點具有旋轉、平移、尺度、光照不變性等優點。這些點稱為圖像的特徵 (Feature) 點,包含關鍵點(Key-points) 和描述子 (Descriptor) 兩部分。關鍵點表達了特徵點的位置,而描述子則是對於特徵點視覺特性的描述,大多為向量形式。一般而言,描述子主要是以某種模式,統計關鍵點周圍的灰度/色彩梯度變化。一種魯棒的描述子,在不同圖像 的不同情況下,同一特徵點的描述子的距離 (Distance) 應當較小。

描述子一般是人為手工設計的 (Hand-crafted features) 。經典的描述如 HOG(Histogram of oriented gradients)[1],SIFT(Scale-invariant feature transform)[2],SURF(Speeded up robust features)[3],AKAZE(Accelerated KAZE)[4] 等。

為了實時性的要求,一些計算速度更快的二值模式描述子被設計出來,如 LBP(Local binary patterns)[5],BRIEF(Binary robust independent elementary features),ORB(Oriented FAST and rotated BRIEF)[6],BRISK(Binary robust invariant scalable key-point)[7],FREAK(Fast retina key-point)[8] 等。

在深度學習流行之前,這些手工特徵一直引領著整個計算視覺產業,直到今天,這些特徵在那些缺少標注數據、約束較多的場景下,依然被廣泛應用。下面簡單介紹兩類常用的描述子。

2.1.1 SIFTSIFT 描述子可以算是 CV 界最具影響力的技術之一。從關鍵點檢測層面,主要使用高斯差分 (Difference of Gaussian, DoG) 方法檢測多尺度空間上的極值點,作為關鍵點。而 Babaud 等人 [9] 證明了高斯平滑是唯一的能用多尺度空間平滑濾波核,為相關方法提供了充足的理論支持。
那麼為什麼這樣的方法可以找到特徵關鍵點呢?
由於高斯核可以通過模糊的方式把圖像縮放到不同尺度空間,而梯度變化較小的平滑區域在不同尺度空間的值差距較小。相反,邊緣、點、角、紋理等區域則差距較大。這樣通過對相鄰尺度的圖像做差分,最終可以算得多尺度空間的極值點。但是,不同的圖像細節本身就處於不同的尺度中。比如一副人物畫像中,人臉可能經過較小的模糊就會被平滑為一片,而畫框的角則可能需要更大尺度的平滑才會體現出局部「極值」。
因此,如 Fig. 2 所示,首先利用圖像金字塔將圖像先分組 (Octave) ,每組中再使用不同尺度的高斯核,形成一系列的層。這種方式比單純地使用更多尺度的高斯核效果更好,可以檢測到更多的特徵點。需要注意的是,雖然 SIFT 使用了 DoG 進行關鍵點檢測,但是其它檢測方法也是可行的,並不影響 SIFT 描述子的建立。
Figure 2: 高斯差分方法

SIFT 特徵點的描述子,可以理解為一種簡單統計版的 HOG。如 Fig. 3所示,以檢測到的關鍵點為中心,選取周圍 16 × 16 的區域,將區域再組織為 4 個 4 × 4 的塊(Patch)。對每一個塊,使用 8-bins 的直方圖對梯度進行統計,梯度方向決定落入哪個 bin,而梯度的模決定值的大小。為了保證尺度一致性,梯度大小需要進行歸一化。為了保證旋轉不變性,會根據 16 × 16 的區域內的所有梯度計算出一個主方向, 所有梯度按照主方向進行旋轉。最終形成 4 × 4 × 8 的 128 維向量。
Figure 3: 基於梯度分塊統計的 SIFT 描述子
2.1.2 二值描述子雖然在 SIFT 提出後,又產生了一些改進演算法如 SURF、AKAZE 等,但是即使放在 2019 年的今天, 依然難以保證一些場景對演算法實時性的要求。例如,手持設備一般算力有限。而無人駕駛中,CPU、GPU資源需要被多個計算密集型模塊同時調度。因此,效率是考察演算法實用性的重要指標。

為了提高效率,一些二值描述子被學者們提出。一般地,這些方法都是在特徵關鍵點周圍進行點采 樣。然後比較一對點的灰度大小,結果以 0/1 表示,形成 N 維的二進制描述向量,構成特徵點的二值模式。而不同二值描述子最大的差別,主要在於特徵采樣模式不同、點對選取方法不同。
Figure 4: LBP 描述子采樣模式

如 Fig. 4所示,LBP 描述子採用對關鍵點周圍,進行環形采樣,並與中心關鍵點的灰度進行比較的方案。圓環上展示了灰度比較結果,黑色的點是 0,白色的點是 1。LBP 是二值描述子最簡單的形式,而 ORB 改進了 BRIEF 特徵,是目前比較常用的二值描述子。如 Fig. 5所示,在點對選取上,與單純使用中心點不同,ORB 採用了隨機的方式,更全面地描述局部細節。但點對的相關性會比較大,從而降低描述子的判別性(Discriminative)。ORB 直接採用了貪婪法、窮舉法解決這一問題,尋找相關性低的隨機點對。
Figure 5: ORB 描述子點對選取模式

以上二值描述子的采樣方式和點對選取方式符合人們一般直覺,而 BRISK、FREAK 等描述子則提供了更加規則化、自帶尺度信息的二值模式構建方法。例如,FREAK 描述子模仿了人眼的視覺采樣模式。如 Fig. 6所示,每個采樣點的值是紅色圓圈范圍內的灰度均值,藍線則表示點對選取方案。
Figure 6: FREAK 描述子采樣、點對選取摸式

二值描述子的高效率,主要體現在三個方面。

(1)二值描述子使用二進制向量作為特徵描述,只需要 比較點對大小而不需要計算具體梯度。(2)兩個描述子之間比較可以使用計算更快,更容易優化的漢明距離 (Hamming distance)。(3)由於每個二進制向量都對應一個十進制數,所以其本身也代了表一種模 式,而不需要像 SIFT 一樣使用直方圖進行表示。

二值描述子一般判別性不如 SIFT 家族描述子,但在特定場景下,配合並行化編程,可以在保證相似判別能力的同時,效率高出幾十甚至百倍。
2.2 資料庫建立與查詢資料庫可以理解為於地圖 + 索引的集成。地圖可以是由單純的 2D 圖像組成,也可以是由 3D 點雲地圖組成,也可以是 2D 圖像和 3D 點雲的結合。3D 點雲地圖生成主要使用三維重建的方法 SfM(Structure from motion),從時間序列的 2D 圖像中推算 3D 信息。如果有雙目、RGB-D 相機提供深度,可以獲得 更准確的 3D 點信息。其中也包含了一些諸如關鍵幀(Key-frame)的選取策略,具體方法超出了本文的討論范圍,有興趣的同學可以自行查閱相關資料。資料庫的作用在於:

對於一張輸入的觀測圖像,通過資料庫,查詢建圖歷史(圖像/點雲/特徵點),得到當前圖像最可能觀測到的地圖子集(圖像/點雲/特徵點),將地圖與觀測信息進行匹配,計算變換矩陣,得到觀測相機的位姿。

索引則是加速這一過程的關鍵。資料庫本身往往是巨大的。以美團的小袋機器人在北京朝陽大悅城二層試運營為例,安裝有 3 個深度相機,即使經過篩選,也使用了將近 8 萬張 900 × 600 的圖片。考慮到定位所需要的實時性,查詢時不可能每次都和 8 萬張圖片一一對比,所以要使用索引技術加速整個演算法。這方面技術與 SLAM 中的回環測試,視覺中的圖像檢索、位置識別等高度重合,以下僅介紹一般方法。

一張圖像內有若干特徵點,需要先對特徵點進行編碼,如 VLAD(Vector of locally aggregated descriptors) 編碼,用局部描述子形成圖像的全局描述。再使用索引,如 kd-tree,進行圖像級查詢。當然,編碼和索引也可以同時進行,如層次化詞袋模型(Bag-of-words,BoW)+ 正向索引 + 逆向索引的方法。
2.2.1 VLAD 編碼VLAD(Vector of locally aggregated descriptors)[10],如 Fig. 7所示,是一種通過聚合局部描述子形成碼本 (Codebook) ,通過累加計算描述子與碼詞 (Word) 的距離,進行全局編碼的簡單方法。一個 d 維描述子 x 通過 k 個碼詞的碼本進行編碼,可以形成一個 d*k 維的描述向量,向量中的值是描述子與第

k個碼詞在第 d 維的差。之後進行 L2 歸一化,形成最後的 VLAD 向量。
Figure 7: VLAD 通過描述子與碼詞的距離進行編碼
這里要特別提介紹一下 DenseVLAD[11] 和 NetVLAD[12] 。Torii 等人證明,DenseSIFT 在查詢、匹配上都優於標准 SIFT。DenseVLAD 在四個尺度,以 2 個像素間隔的網格狀采樣模式,提取 SIFT 點。在全局隨機采樣 25M 個描述子,用 k-means 演算法生成 128 個碼詞的碼本。VLAD 向量在歸一化後使用 PCA(Principal component analysis) 降維,形成最後 4096 維的 DenseVLAD 向量。如 Fig. 8所示,使用DenseSIFT 匹配後的內點(綠)數量更多。
Figure 8: DenseSIFT 和標准 SIFT 特徵點,匹配後內點(綠)對比

而 NetVLAD,將 VLAD 中加入了監督信息,加強 VLAD 編碼的判別性。如 Fig. 9所示,假設紅、綠兩個描述子來源於不應匹配到一起的兩張圖片。由於它們都離 VLAD 中心(×)半徑較大且距離相似,經過 L2 歸一化,它們編碼後值也會很相似。而加入了紅、綠描述子所對應圖片不匹配的監督信息後,NetVLAD 生成的中心點(★)則可以更好地區分兩個描述子,增加他們編碼後的距離(半徑)差。
Figure 9: NetVLAD 聚類中心(×)與 VLAD 聚類中心(★)對比。
2.2.2 BoW 編碼 + 索引基於詞袋模型 BoW[13, 14] 的特徵編碼及其設計思想在計算機視覺發展中具有舉足輕重的地位,這里不再展開介紹。本文以 2D 查詢圖像匹配 2D 圖像資料庫為例,介紹一種常見的 BoW 編碼、索引一體化的模型。如 Fig. 10所示,詞典 (Vocabulary) 生成採用層次化方法,對於數據集中的所有描述子,按樹狀結構進行空間劃分,每一層都是由 k-means 聚類計算。最終葉子節點就相當於碼詞(Fig. 10中有 9個碼詞)。
Figure 10: 帶正向索引、逆向索引的層次化 BoW 模型
樹的構造過程,實際上就是將原始圖像編碼的過程。但是編碼本身並不能加快搜索過程,與 VLAD 相似,還是需要與資料庫中的圖像逐一比較。因此,這里設計了一種逆向索引(Inverse index) ,不需要比較編碼後的向量。其原理如 Fig. 11所示,對於一張查詢圖像 (Query image) ,將提取的描述子輸入到 BoW 中,最終會落入碼詞葉子結點 (Visual word) k 中。而每個碼詞對應一個索引,記錄碼詞 k
對於資料庫中第 i
張圖的權重
(Fig.10)。這里權重使用 TF-IDF(Term frequency–inverse document frequency) 計算。即如果一個詞 k
在某個圖像 i
中出現頻率高,在其它圖像出現頻率低,則這個詞對於圖像判別性較好,權重值
較高。最終通過投票 (Voting) 機制,選出匹配圖像。同樣需要注意的是,逆向索引不一定建立在樹形結構的 BoW 上,它僅僅是提供一種快速查詢的方法。
Figure 11: 通過逆向索引 + 投票機制,直接查詢圖像
而正向索引 (Direct Index) 的作用主要是記錄構造 BoW 時,資料庫圖片的特徵點都落入了哪些結點中,這樣當查詢到圖像後,不需要計算特徵點,可以直接通過索引提取特徵點。

2.2.3 3D 點雲查詢2D 圖像查詢中,是先從語意層面查詢圖像,因此可以通過圖像對特徵點的空間范圍進行約束。3D 點雲查詢沒有這樣的約束,所以具諸多難點。如需要考慮空間連續性,查詢到的點是否都在可觀測范圍內等。這里僅介紹 Sattler 在 TPAMI 2016 上發表的方法 [15],經過多年的打磨,這套方法框架相對簡潔、完善。由於其中的詞典編碼搜索步驟與上節內容有所重疊,這里僅介紹 Active Search 和 Visbility Filtering 兩種機制。

Active Search 主要是為了使得匹配到的 3D 點盡可能空間中臨近、有幾何意義。如 Fig. 12所示,紅 色的點通過一系列編碼、精化過程(紅線),匹配到了點雲中一個點。根據所提出優先排序(Prioritization) 框架,從點雲中找到一個概率最大的 3D 點,並反向(藍線)匹配查詢圖像中的一個對應的 2D 點。
Figure 12: Active Search
Figure 13: Visbility Filtering
Visbility Filtering 主要是為了讓匹配到的點盡可能可以被相機觀測到(定位是無監督的,並不能知道所匹配到的點是否正確)。這里採用的方法是在使用 SfM 建立 3D 點雲地圖時,同時建立一個雙向可見圖 (Bipartite visibility graph) 。如 Fig. 13(左)所示,當一個點可以同時被兩個相機觀測時,則建立拓撲關系。Fig. 13(中)里,藍色的點為匹配到的點,它們從觀測視角上存在沖突。通過在已有拓撲上進 行圖聚類,將相機兩兩分組,如 Fig. 13(右)。這樣就可以生成新的圖拓撲關系。之後通過判斷每個子圖(Sub-graph)間的重合情況,過濾掉那些那大概率不可見的點。

需要說明的是,雖然雙目相機和 RGB-D 相機可以獲取深度,查詢 2D 圖像也可以獲得限定范圍內的 3D 特徵點坐標,但是由於目前技術限制,在室內材質復雜,室外大尺度場景下,深度並不可靠。所以 2D圖像點和 3D 點雲地圖的匹配依然是一種重要的方法。

2.3 特徵點匹配特徵點匹配過程可以是在資料庫查詢中自適應完成的,這多見於基於 3D 結構的查詢。匹配也可以是在查詢後單獨進行,多見於基於 2D 圖像查詢。特徵匹配的目的是,為後續的變換矩陣計算提供匹配的點對集,實現位姿的解算。

2.3.1 經典 RANSAC隨機抽樣一致演算法 (Random sample consensus,RANSAC)[16] 是一種經典的數據過濾、參數擬合演算法。它假設數據(內點,Inliers)分布符合一定的數學模型,通過迭代計算,去除外點 (Outliers) 、雜訊點, 同時獲取概率上最佳的模型參數。在全局定位中,內點指正確的匹配,外點指錯誤的匹配,參數模型指匹配點對的空間變換矩陣。如 Fig. 14所示,經過 RANSAC 演算法優化後,匹配更加合理。RANSAC 所期望找到的匹配子集需要滿足兩個指標:內點重投影誤差盡可能小;內點數量盡可能多。所以基本流程如下:

· ①采樣初始子集。

· ②計算變換矩陣。

· ③ 根據變換矩陣計算匹配點的重投影誤差。

· ④ 去除誤差較大的點

· ⑤ 循環①-④,保留最滿足指標的匹配方案。
Figure 14: (上)原始特徵匹配;(下)經過 RANSAC 演算法優化後的匹配

其中,初始候選匹配是根據描述子之間的距離產生的,但重投影誤差則只和關鍵點的空間位置有關, 與描述子本身無關。具體投影矩陣方法請參考「2.4 位姿計算」。需要指出的是,RANSAC 演算法受到原始匹 配誤差和參數選擇的影響,只能保證演算法有足夠高的概率合理,不一定得到最優的結果。演算法參數主要包括閾值和迭代次數。RANSAC 得到可信模型的概率與迭代次數成正比,所得到的匹配數量和閾值成反比。因此實際使用時,可能需要反復嘗試不同的參數設置才能得到較優的結果。

學者們對經典 RANSAC 演算法進行了很多改進,如 Fig. 15所示,提出了全局 RANSAC(Universal- RANSAC)[17] 的結構圖,形成了具有普適性的 RANSAC 架構,涵蓋了幾乎所有的 RANSAC 的改進方 面,如預濾波、最小子集采樣、由最小子集生成可靠模型、參數校驗、模型精化。
Figure 15: Universal-RANSAC 通用演算法框架

2.3.3 可微分 RANSAC由於手工描述子在定位領域依然表現出較高的性能,所以一些學者開始探索使用深度學習代替演算法框架中的某些部分,而不是直接使用端到端的位姿估計模型完全代替傳統方法。可微分 RANSAC(Differentiable RANSAC,DSAC)[18] 旨在用概率假說選擇代替確定性假說選擇,使得 RANSAC 過程可以被求導,流程如 Fig. 16所示,其中「Scoring」步驟依然採用重投影誤差作為指標,所不同的是,誤差是基於整張圖像而不是特徵點,而原先篩選特徵點匹配的過程被換為了直接以概率篩選相機位姿假設 h 的過程。雖然目 前方法局限性比較大,但 DSAC 為如何在當前無監督為主的定位演算法框架中加入先驗知識,提供了一種可行的思路。
Figure 16: 差分 RANSAC 演算法框架

P3P 法可以看作是 PnP 法的特殊解法,如 Fig. 17所示,利用三角形相似性質增加更多約束,只需要 3 對點就可以求解。其它解法還有直接線性變換法 (Direct linear transformation,DLT),EPnP(Efficient PnP) 法,和 UPnP(Uncalibrated PnP)等。相對於以上線性優化方法,非線性優化方法如Bundle Adjustment(BA) 也有著廣泛的應用。BA 方法在視覺 SLAM 中是一種「萬金油」的存在,可以同時優化多個變數,這樣可以一定程度緩解局部誤差帶來的系統不魯棒,感興趣的同學可以翻閱相關資料更深入地進行了解。
Figure 17: 2D-3D 變換矩陣計算中的 P3P 方法

3. 總結與展望

本文從圖像描述、建圖查詢、特徵匹配,位姿計算四個方面介紹了基於特徵點的位姿估計演算法。雖然傳統視覺全局定位方法目前依然是實際應用中的首選,但是,傳統方法是建立在特徵點被正確定義、正確提取、正確匹配、正確觀測的前提下進行的,這一前提對於視覺本身而言就是巨大的挑戰。其次,由於傳統方法是 multi-stage 框架,而非 end-to-end,所以中間每個環節,環節之間的交互,都需要眾多參數調整,每個環節的技術都可以作為一個單獨的研究方向。實際應用時,也需要加入對應具體場景的大量tricks,工程上比較復雜。

而人們對 end-to-end 方法的期望催生出了如 PoseNet,VLocNet,HourglassNet 等網路,在 benchmark上取得了不錯的成績。筆者認為目前 end-to-end 的方法還存在很多問題,主要有 loss function 缺少幾何 約束,建圖時位姿的 6 自由度空間並不連續,與輸入空間難以形成良好映射,而且缺少相應的位姿回歸、 精化機制等。不能否認,作為非線性空間最有力的建模工具,深度學習在未來會更多地出現在定位領域中。

回歸到視覺定位本身,由於視覺最重要的優勢就是成本低、語意豐富、使用場景限制少。因此,以視覺為主,其它低成本感測器為輔的定位融合方案在未來也將會是一個重要的課題。

參考資料

[1] Dalal, N., and B. Triggs. 」Histograms of oriented gradients for human detection.」 CVPR, 2005.

[2] Lowe, David G. 」Distinctive Image Features from Scale-Invariant Keypoints.」 IJCV, 2004.

[3] Bay, Herbert, T. Tuytelaars, and L. V. Gool. 」SURF: Speeded Up Robust Features.」 ECCV, 2006.[4] P.F.Alcantarilla,J.Nuevo,andA.Bartoli.Fast explicit diffusion for accelerated features in nonlinear scale spaces. BMVC, 2013.

[5] Ojala, Timo. 」Gray Scale and Rotation Invariant Texture Classification with Local Binary Patterns.」 ECCV, 2000.

[6] Rublee, Ethan , et al. 」ORB: An efficient alternative to SIFT or SURF.」 ICCV, 2011.

[7] Leutenegger, Stefan , M. Chli , and R. Y. Siegwart . 」BRISK: Binary Robust invariant scalable keypoints.」 ICCV, 2011

[8] Alahi, Alexandre , R. Ortiz , and P. Vandergheynst . 」FREAK: Fast retina keypoint.」 CVPR, 2012.

[9] Witkin, A P, M. Baudin, and R. O. Duda. 」Uniqueness of the Gaussian Kernel for Scale-Space Filtering.」 TPAMI, 1986.

[10] Jegou, Herve , et al. 」Aggregating local descriptors into a compact image representation.」 CVPR, 2010.

[11] Torii, Akihiko , et al. 」24/7 place recognition by view synthesis.」 CVPR, 2015.

[12] Arandjelovic, Relja, et al. 」NetVLAD: CNN architecture for weakly supervised place recognition.」 TPAMI, 2017.

[13] Li, Fei Fei . 」A Bayesian Hierarchical Model for Learning Natural Scene Categories. CVPR, 2005.
[14] Galvez-Lopez, D. , and J. D. Tardos . 」Bags of Binary Words for Fast Place Recognition in Image Sequences.」 TRO, 2012.

[15] Sattler, Torsten , B. Leibe , and L. Kobbelt . 」Efficient & Effective Prioritized Matching for Large- Scale Image-Based Localization.」 TPAMI, 2016.

[16] Fischler, Martin A., and R. C. Bolles. 」Random sample consensus: a paradigm for model fitting with applications to image analysis and automated cartography.」 Communications of the ACM, 1981.

[17] Raguram, Rahul , et al. 」USAC: A Universal Framework for Random Sample Consensus.」 TPAMI, 2013.

[18] Brachmann, Eric, et al. 」DSAC —Differentiable RANSAC for Camera Localization.」 CVPR, 2017.

閱讀全文

與dlt演算法建立點雲相關的資料

熱點內容
光遇安卓與ios什麼時候互通 瀏覽:596
js如何運行時編譯 瀏覽:915
引力app在哪裡下載 瀏覽:607
編寫app如何得到錢 瀏覽:800
吉利汽車軟體放哪個文件夾安裝 瀏覽:223
多文件編譯c 瀏覽:541
頭頂加密後為什麼反而更稀疏 瀏覽:793
離心機壓縮機揚程高 瀏覽:658
xshell連接linux命令 瀏覽:5
把多個文件夾的內容合並在一起 瀏覽:483
基於單片機的澆花系統設計ppt 瀏覽:685
卷積碼編解碼及糾錯性能驗證實驗 瀏覽:354
請在刪除驅動器之前暫停加密什麼意思 瀏覽:787
光催化pdf 瀏覽:98
java字元串包含某字元 瀏覽:528
ssm身份認證源碼 瀏覽:466
預排序遍歷樹演算法 瀏覽:671
加密裝置如何打開ping功能 瀏覽:480
python下載372 瀏覽:903
u盤子文件夾隱藏 瀏覽:297