日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

视觉SLAM总结——视觉SLAM十四讲笔记整理

發布時間:2025/3/20 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 视觉SLAM总结——视觉SLAM十四讲笔记整理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

視覺SLAM總結——視覺SLAM十四講筆記整理

  • 說明
  • 基礎知識點
    • 1. 特征提取、特征匹配
      • (1)Harris
      • (2)SIFT
      • (3)SUFT
      • (4)ORB
      • (5)特征匹配
    • 2. 2D-2D:對極約束、基礎矩陣、本質矩陣、單應矩陣
    • 3. 3D-2D:PnP
      • (1)直接線性變換方法
      • (2)P3P方法
      • (3)Bundle Adjustment方法
    • 4. 3D-3D:ICP
      • (1)SVD方法
      • (2)非線性優化方法
    • 5. 直接法和光流法
      • (1)光流法
      • (2)直接法
    • 6. Bundle Adjustment
    • 回環檢測
  • 相關問題
    • 1. SIFT和SUFT的區別
    • 2. 相似變換、仿射變換、射影變換的區別
    • 3. Homography、Essential和Fundamental Matrix的區別
    • 4. 視差與深度的關系
    • 5. 描述PnP算法
    • 6. 閉環檢測常用方法
    • 7. 給一個二值圖,求最大連通域
    • 8. 梯度下降法、牛頓法、高斯-牛頓法的區別
    • 9. 推導一下卡爾曼濾波、描述下例子濾波
    • 10. 如何求解Ax=bAx=bAx=b的問題
    • 11. 什么是極限約束
    • 12. 單目視覺SLAM中尺寸漂移是怎么產生的
    • 10. 解釋SLAM中的綁架問題
    • 11. 描述特征點法和直接法的優缺點
    • 12. EKF和BA的區別
    • 13. 邊緣檢測算子有哪些?
    • 14. 簡單實現cv::Mat()
    • 15. 10個相機同時看到100個路標點,問BA優化的雅克比矩陣多少維
    • 16. 介紹經典的視覺SLAM框架

說明

這篇博客是我對《視覺SLAM十四講》相關基礎知識點的一個整理,沒有詳細的推導過程,僅僅相當于一個思維導圖,同時在網上搜羅了一些相關的問題進行的補充總結,本人水平有限,如果文中有誤,還請大家指出。

基礎知識點

1. 特征提取、特征匹配

這是整個SLAM系統最開始的部分,先進行特征提取,然后進行特征匹配,通過匹配的特征點才求取的相關變換矩陣,這里容易搞混的概念是特征提取,特征提取是包括特征點和特征描述子,以ORB為例,ORB是由FAST特征點和BRIEF特征描述子構成。而我們通常所說的Harris角點通常僅僅指特征點,僅僅擁有Harris角點是無法進行特征匹配的,還需要通過向量對Harris角點進行特征描述(特征描述子),兩幀之間才能進行特征的匹配。關于特征子的總結可以參看我的這篇總結博客 視覺SLAM總結——視覺特征子綜述(總結得非常詳細)

(1)Harris

Harris角點:如下圖所示,通過一個小的滑動窗口在鄰域檢測角點在任意方向上移動窗口,若窗口內的灰度值都有劇烈的變化,則窗口的中心就是角點。轉化為數學描述就是自相關矩陣兩個特征值大小。

Harris特征描述子:Harris 角點的描述子通常是由周圍圖像像素塊的灰度值,以及用于比較的歸一化互相關矩陣構成的。圖像的像素塊由以該像素點為中心的周圍矩形部分圖像構成
優點:計算簡單;提取的點特征均勻且合理;穩定,穩定Harris算子對圖像旋轉、亮度變化、噪聲影響和視點變換不敏感。
缺點:對尺度很敏感,不具有尺度不變性;提取的角點精度是像素級的;需要設計角點匹配算法

(2)SIFT

SIFT特征點:利用高斯金字塔和DOG函數進行特征點提取。高斯金字塔的當前層圖像是對其前一層圖像先進行高斯低通濾波,然后做隔行和隔列的降采樣(去除偶數行與偶數列)而生成的。DoG (Difference of Gaussian)是高斯函數的差分,具體到圖像處理來講,就是將同一幅圖像經過兩個不同高斯濾波得到兩幅濾波圖像,將這兩幅圖像相減,得到DoG圖。DOG圖上的鄰域梯度方向直方圖峰值即特征點的主方向。

SIFT特征描述子:以特征點為中心取窗口,通過高斯加權增強特征點附近像素梯度方向信息的貢獻,即在4 × 4的小塊上計算梯度方向直方圖( 取8個方向),計算梯度方向累加值,形成種子點,構成4× 4 × 8= 128維特征向量。然后進行統計。

優點:SIFT特征對旋轉、尺度縮放、亮度變化保持不變性,對視角變化、仿射變換、噪聲也保持一定程度的穩定性。

(3)SUFT

SUFT是對SIFT的改進,他們在思路上是一致的,只是采用的方法不同而已
SUFT特征點:基于Hessian矩陣構造金字塔尺度空間,利用箱式濾波器(box filter)簡化二維高斯濾波
SUFT特征描述子:通過Haar小波特征設定特征點主方向,這樣構建的特征描述子就是64維的

缺點:在求主方向階段太過于依賴局部區域像素的梯度方向;圖像金字塔的層取得不足夠緊密也會使得尺度有誤差

(4)ORB

Fast角點:如果某個像素與周圍領域內足夠多的像素相差較大,則該像素有可能為角點。直接的閾值判斷來加速角點提取簡單高效。

BRIEF特征描述子:BRIEF算法計算出來的是一個二進制串的特征描述符。它是在一個特征點的鄰域內,選擇n對像素點pi、qi(i=1,2,…,n)。然后比較每個點對的灰度值的大小。如果I(pi)> I(qi),則生成二進制串中的1,否則為0。所有的點對都進行比較,則生成長度為n的二進制串。
優點:ORB算法的速度大約是SIFT的100倍,是SURF的10倍。
以上參考 https://zhuanlan.zhihu.com/p/36382429

(5)特征匹配

特征匹配的方法有很多,就不在這里一一贅述,包括暴力匹配(Brute-Force Macher)、近似最近鄰(FLANN)等,ORB SLAM2中采用詞典加速匹配過程。



2. 2D-2D:對極約束、基礎矩陣、本質矩陣、單應矩陣

對極約束 x2Tt∧Rx1=0(p2TK?Tt∧RK?1p1=0)\bm{x_2^T t^\wedge R x_1 = 0( p_2^T K^{-T} t^\wedge R K^{-1} p_1 = 0)}x2T?tRx1?=0(p2T?K?TtRK?1p1?=0)
本質矩陣E E=t∧R\bm{E=t^\wedge R} E=tR
基本矩陣F F=K?TEK?1\bm{F=K^{-T}EK^{-1}} F=K?TEK?1
其中,p1,p2p_1,p_2p1?,p2?是像素坐標,對極約束描述的是空間中兩個匹配點的空間位置關系,本質矩陣的奇異值必定是[δ,δ,0][\delta,\delta,0][δ,δ,0],由于平移和旋轉各三個自由度,因此本質矩陣有六個自由度。但通常采用八點法進行求解。由本質矩陣恢復R,tR,tR,t的過程通過SVD分解完成。
當場景中所有特征點都落到一個平面上時就可以通過單應性來進行運動估計。通過這個關系可以推導得p2=Hp1\bm{p_2=Hp_1}p2?=Hp1?,其中HHH就是單應矩陣。可以通過四對點求解。單應性的重要性在于,當相機發生純旋轉或者特征點共面時,基礎矩陣的自由度會下降,就出現退化,這時候如果我們繼續用八點法求基礎矩陣,基礎矩陣多余出來的自由度將主要由噪聲決定。

3. 3D-2D:PnP

PnP是求解3D到2D點對運動的方法,即問題描述為,我們的已知條件是n個3D空間點以及它們作為特征點的位置(以歸一化平面齊次坐標表示),我們求解的是相機的位姿R,tR,tR,t,如果3D空間點的位置是世界坐標系的位置,那么這個R,tR,tR,t也是世界坐標系下的。特征點的3D位置可以通過三角化或者RGBD相機的深度圖確定。

(1)直接線性變換方法

根據推導,一對特征點(一個3D點加一個2D點)可以提供兩個線性約束,因此12維的齊次變換矩陣需要6對特征點。

(2)P3P方法

P3P的作用是將利用三對特征點,講空間點在世界坐標系下的坐標,轉換到像極坐標系中的坐標,將PnP問題轉化為ICP問題,推導過程是利用三角形特征完成的。

(3)Bundle Adjustment方法

其本質是一個最小化重投影誤差的問題,公式如下:
即理解為調整相機的位姿使得重投影誤差變小,而最小的重投影誤差就對應著實際的位姿。需要求這里要注意的是這里僅僅是采用了BA的方法,但是實際做BA優化的時候,是同時優化位姿和路點位置,因此有兩個相關的雅克比矩陣,但這里僅僅優化位姿,因此所求的雅克比矩陣僅僅和位姿有關,可以直接求取JJJ如下,然后就可以進行求解δξ\delta \xiδξ進行迭代




4. 3D-3D:ICP

其本質就是確定兩個點集之間的匹配關系。

(1)SVD方法

其問題構建為:

求解過程是先對每個點進行去質心坐標,然后根據優化問題計算旋轉矩陣RRR(這里會用到SVD),最后求ttt

(2)非線性優化方法

其問題構建為:

這里的推導和PnP的類似,即求位姿導數。



5. 直接法和光流法

(1)光流法

光流法的基本假設是灰度不變假設,即同一個空間點的像素灰度值,在各個圖像中是固定不變的

在LK光流中假設某一窗口內的像素具有相同的運動,因此w×ww×ww×w大小的窗口內有w2w^2w2個像素,即構成w2w^2w2個方程,然后構成關于dxdt\frac{dx}{dt}dtdx?,dydt\frac{dy}{dt}dtdy?的超定線性方程,求其最小二乘解。LK光流是得到特征點之間的對應關系,如同描述子的匹配,之后還是需要通過對極幾何、PnP等求解相機位姿。

(2)直接法

直接法之所以稱為直接法是因為它是直接獲得相機位姿,而不需要通過匹配、求解矩陣等過程,直接法的思路是根據當前相機的位姿估計值,來尋找 p2p_2p2? 的位置。但若相機位姿不夠好, p2p_2p2?的外觀和p1p_1p1?會有明顯差別, 然后通過優化光度誤差來優化相機位姿。

非常快的框架SVO就是結合了直接法和特征點法,SVO采用的是提取稀疏特征點(類似特征點法),幀間VO用圖像對齊(類似于直接法)。
直接法的缺點:1. 非凸性;2. 單個像素沒有區分度;3. 灰度值不變是很強的假設



6. Bundle Adjustment

我后來對后端進行了一個非常全面的總結,參考博客視覺SLAM總結——后端總結
首先注意目標函數如下:

其中FijF_{ij}Fij?為整個代價函數在當前狀態下對相機姿態的偏導數,EijE_{ij}Eij?表示該函數對路標點位置的偏導數。因此在非線性優化過程中獲得的HHH矩陣為

H矩陣最重要的一個特性就是它的稀疏性,其中左上角和右下角為對角陣且一般左上角較小右下角較大。左下角和右上角可能稀疏也可能稠密,矩陣的非對角線上的非零矩陣塊,表示了該處對應的兩個相機變量之間存在著共同觀測的路標點,有時候稱為共視(Co-visibility)。其對應關系如下:

其求解HΔx=g\bm{H\Delta x=g}HΔx=g的過程中消元的過程即Marginalization(邊緣化),首先消元結果如下:

先求解

將解得的Δxc\Delta \bm x_cΔxc?帶入原方程,再求解Δxp\Delta \bm x_pΔxp?,其優勢在于:

  • 在消元過程中,由于C\bm CC為對角塊,所以C?1\bm {C^{-1}}C?1容易解得。
  • 求解了 Δxc\bm{\Delta x_c}Δxc? 之后,路標部分的增量方程由Δxp=C?1(w?ETΔxc)\bm{\Delta x_p = C^{-1}(w-E^T\Delta x_c)}Δxp?=C?1(w?ETΔxc?)給出。這依然用到了C?1\bm{C^{-1}}C?1易于求解的特性。
  • 從概率角度來看,我們稱這一步為邊緣化,是因為我們實際上把求 (Δxc\Delta \bm x_cΔxc? ,Δxp\Delta \bm x_pΔxp?) 的問題,轉化成先求Δxc\Delta \bm x_cΔxc? ,再求 Δxp\Delta \bm x_pΔxp?的過程。這一步相當于做了條件概率展開:
    所謂魯棒核函數就是減小誤匹配帶來的誤差,如Huber核,其實就是改變一下目標函數的定義:

    當誤差eee大于某個閾值δ\deltaδ后,函數增長由二次形式變成了一次形式,相當于限制了梯度的最大值.



    回環檢測

    這一部分之前并沒有花很多時間去研究,主要是知道目前SLAM中用的比較多的方法是詞袋模型,詞袋模型中涉及到字典的生成和使用的問題,這一部分和機器學習的只是掛鉤比較深。
    字典的生成問題就是非監督聚類問題,可以采用K-means對特征點進行聚類,然后通過K叉樹進行表達,相似度判斷采用是TD-IDF的方法。



    相關問題

    我將更多的問題總結到了視覺SLAM面試題匯總中

    問題及部分回答來源:
    https://www.cnblogs.com/xtl9/p/8053331.html
    https://zhuanlan.zhihu.com/p/46694678
    http://www.voidcn.com/article/p-ngqfdzqe-ot.html
    https://zhuanlan.zhihu.com/p/28565563

    1. SIFT和SUFT的區別

  • 構建圖像金字塔,SIFT特征利用不同尺寸的圖像與高斯差分濾波器卷積;SURF特征利用原圖片與不同尺寸的方框濾波器卷積。
  • 特征描述子,SIFT特征有4×4×8=128維描述子,SURF特征有4×4×4=64維描述子
  • 特征點檢測方法,SIFT特征先進行非極大抑制,再去除低對比度的點,再通過Hessian矩陣去除邊緣響應過大的點;SURF特征先利用Hessian矩陣確定候選點,然后進行非極大抑制
  • 特征點主方向,SIFT特征在正方形區域內統計梯度幅值的直方圖,直方圖最大值對應主方向,可以有多個主方向;SURF特征在圓形區域內計算各個扇形范圍內x、y方向的haar小波響應,模最大的扇形方向作為主方向
  • 2. 相似變換、仿射變換、射影變換的區別

    等距變換:相當于是平移變換(t)和旋轉變換(R)的復合,等距變換前后長度,面積,線線之間的角度都不變。自由度為6(3+3)
    相似變換:等距變換和均勻縮放(S)的一個復合,類似相似三角形,體積比不變。自由度為7(6+1)
    仿射變換:一個平移變換(t)和一個非均勻變換(A)的復合,A是可逆矩陣,并不要求是正交矩陣,仿射變換的不變量是:平行線,平行線的長度的比例,面積的比例。自由度為12(9+3)
    隱射變換:當圖像中的點的齊次坐標的一般非奇異線性變換,射影變換就是把理想點(平行直線在無窮遠處相交)變換到圖像上,射影變換的不變量是:重合關系、長度的交比。自由度為15(16-1)
    參考:https://blog.csdn.net/try_again_later/article/details/81281688

    3. Homography、Essential和Fundamental Matrix的區別

    Homography Matrix可以將一個二維射影空間的點變換該另一個二維射影空間的點,如下圖所示,在不加任何限制的情況下,僅僅考慮二維射影空間中的變換,一個單應矩陣HHH可由9個參數確定,減去scale的一個自由度,自由度為8。
    Fundamental Matrix對兩幅圖像中任何一對對應點x\bm xxx′\bm x'x基礎矩陣F\bm FF都滿足條件:xTFx′=0\bm{x^T F x' = 0}xTFx=0,秩只有2,因此F的自由度為7。它自由度比本質矩陣多的原因是多了兩個內參矩陣。
    Essential matrix:本質矩是歸一化圖像坐標下的基本矩陣的特殊形式,其參數由運動的位姿決定,與相機內參無關,其自由度為6,考慮scale的話自由度為5。

    4. 視差與深度的關系

    在相機完成校正后,則有 d/b=f/zd/b=f/zd/b=f/z,其中 ddd 表示視差,bbb 表示基線,fff 是焦距,zzz 是深度

    5. 描述PnP算法

    已知空間點世界坐標系坐標和其像素投影,公式如下

    目前一共有兩種解法,直接線性變換方法(一對點能夠構造兩個線性約束,因此12個自由度一共需要6對匹配點),另外一種就是非線性優化的方法,假設空間坐標點準確,根據最小重投影誤差優化相機位姿。
    目前有兩個主要場景場景,其一是求解相機相對于某2維圖像/3維物體的位姿;其二就是SLAM算法中估計相機位姿時通常需要PnP給出相機初始位姿。
    在場景1中,我們通常輸入的是物體在世界坐標系下的3D點以及這些3D點在圖像上投影的2D點,因此求得的是相機坐標系相對于世界坐標系(Twc)的位姿
    在場景2中,通常輸入的是上一幀中的3D點(在上一幀的相機坐標系下表示的點)和這些3D點在當前幀中的投影得到的2D點,所以它求得的是當前幀相對于上一幀的位姿變換

    6. 閉環檢測常用方法

    本人知道的現在常用的就是利用詞袋模型進行閉環檢測,也有利用深度學習進行閉環檢測的方法,暫時沒有去了解過

    7. 給一個二值圖,求最大連通域

    這個之后單獨寫一篇博客來研究這個好了,二值圖的連通域應該是用基于圖論的深度優先或者廣度優先的方法,后來還接觸過基于圖的分割方法,采用的是并查集的數據結構,之后再作細致對比研究。

    8. 梯度下降法、牛頓法、高斯-牛頓法的區別

    在BA優化、PnP、直接法里面都有接觸到非線性優化問題,上面幾種方法都是針對對非線性優化問題提出的方法,將非線性最優化問題作如下展開,就可以獲得梯度下降法牛頓法

    梯度下降法是一個一階最優化算法,通常也稱為最速下降法。 要使用梯度下降法找到一個函數的局部極小值,必須向函數上當前點對應梯度(或者是近似梯度)的反方向的規定步長距離點進行迭代搜索。因此指保留一階梯度信息。缺點是過于貪心,容易走出鋸齒路線。
    牛頓法是一個二階最優化算法,基本思想是利用迭代點處的一階導數(梯度)和二階導數(Hessen矩陣)對目標函數進行二次函數近似。因此保留二階梯度信息。缺點是需要計算H\bm HH矩陣,計算量太大。
    Δx?=?JT(x)/H\Delta \bm x^* = -\bm {J^T}(\bm x)/\bm HΔx?=?JT(x)/H
    而把非線性問題,先進行一階展開,然后再作平方處理就可以得到高斯-牛頓法列文博格方法

    高斯-牛頓法對上式展開并對Δx\Delta \bm xΔx進行求導即可得高斯牛頓方程,其實其就是使用JJT\bm {JJ^T}JJT對牛頓法的H\bm HH矩陣進行替換,但是JJT\bm {JJ^T}JJT有可能為奇異矩陣或變態,Δx\Delta \bm xΔx也會造成結果不穩定,因此穩定性差

    列文博格法就是在高斯-牛頓法的基礎上對Δx\Delta \bm xΔx添加一個信賴區域,保證其只在展開點附近有效,即其優化問題變為帶有不等式約束的優化問題,利用Lagrange乘子求解

    9. 推導一下卡爾曼濾波、描述下例子濾波

    參看我的另外一個總結博客概率機器人總結——粒子濾波先實踐再推導

    10. 如何求解Ax=bAx=bAx=b的問題

    參看我的另外一個總結博客多視圖幾何總結——基礎矩陣、本質矩陣和單應矩陣的求解過程

    11. 什么是極限約束

    所謂極線約束就是說同一個點在兩幅圖像上的映射,已知左圖映射點p1,那么右圖映射點p2一定在相對于p1的極線上,這樣可以減少待匹配的點數量。如下圖:

    12. 單目視覺SLAM中尺寸漂移是怎么產生的

    用單目估計出來的位移,與真實世界相差一個比例,叫做尺度。這個比例在單目初始化時通過三角化確定,但單純靠視覺無法確定這個比例到底有多大。由于SLAM過程中噪聲的影響,這個比例還不是固定不變的。修正方式是通過回環檢測。

    10. 解釋SLAM中的綁架問題

    綁架問題就是重定位,是指機器人在缺少之前位置信息的情況下,如何去確定當前位姿。例如當機器人被安置在一個已經構建好地圖的環境中,但是并不知道它在地圖中的相對位置,或者在移動過程中,由于傳感器的暫時性功能故障或相機的快速移動,都導致機器人先前的位置信息的丟失,在這種情況下如何重新確定自己的位置。
    初始化綁架可以闡述為一種通常狀況初始化問題,可使用蒙特卡洛估計器,即粒子濾波方法,重新分散粒子到三維位形空間里面,被里程信息和隨機擾動不斷更新,初始化粒子聚集到/收斂到可解釋觀察結果的區域。追蹤丟失狀態綁架,即在綁架發生之前,系統已經保存當前狀態,則可以使用除視覺傳感器之外的其他的傳感器作為候補測量設備。

    11. 描述特征點法和直接法的優缺點

    特征點法
    優點:1. 沒有直接法的強假設,更加精確;2. 相較與直接法,可以在更快的運動下工作,魯棒性好
    缺點:1. 特征提取和特征匹配過程耗時長;2. 特征點少的場景中無法使用;3.只能構建稀疏地圖
    直接法
    優點:1.省去了特征提取和特征匹配的時間,速度較快;2. 可以用在特征缺失的場合;3. 可以構建半稠密/稠密地圖
    缺點:1. 易受光照和模糊影響;2.運動必須慢;3.非凸性,易陷入局部極小解

    12. EKF和BA的區別

    (1) EKF假設了馬爾科夫性,認為k時刻的狀態只與k-1時刻有關。BA使用所有的歷史數據,做全體的SLAM
    (2) EKF做了線性化處理,在工作點處用一階泰勒展開式近似整個函數,但在工作點較遠處不一定成立。BA每迭代一次,狀態估計發生改變,我們會重新對新的估計點做泰勒展開,可以把EKF看做只有一次迭代的BA

    13. 邊緣檢測算子有哪些?

    邊緣檢測一般分為三步,分別是濾波、增強、檢測。基本原理都是用高斯濾波器進行去噪,之后在用卷積內核尋找像素梯度。常用有三種算法:canny算子sobel算子laplacian算子
    canny算子:一種完善的邊緣檢測算法,抗噪能力強,用高斯濾波平滑圖像,用一階偏導的有限差分計算梯度的幅值和方向,對梯度幅值進行非極大值抑制,采用雙閾值檢測和連接邊緣。
    sobel算子:一階導數算子,引入局部平均運算,對噪聲具有平滑作用,抗噪聲能力強,計算量較大,但定位精度不高,得到的邊緣比較粗,適用于精度要求不高的場合。
    laplacian算子:二階微分算子,具有旋轉不變性,容易受噪聲影響,不能檢測邊緣的方向,一般不直接用于檢測邊緣,而是判斷明暗變化。

    14. 簡單實現cv::Mat()

    15. 10個相機同時看到100個路標點,問BA優化的雅克比矩陣多少維

    因為誤差對相機姿態的偏導數的維度是2×6,對路標點的偏導數是2×3,又10個相機可以同時看到100個路標點,所以一共有10×100×2行,100×3+10×6個塊。

    16. 介紹經典的視覺SLAM框架

    視覺SLAM總結——ORB SLAM2中關鍵知識點總結
    視覺SLAM總結——SVO中關鍵知識點總結
    視覺SLAM總結——LSD SLAM中關鍵知識點總結

    此外,對SLAM算法感興趣的同學可以看考我的博客SLAM算法總結——經典SLAM算法框架總結

    總結

    以上是生活随笔為你收集整理的视觉SLAM总结——视觉SLAM十四讲笔记整理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。