OpenCV學習筆記二:OpenCV中的圖像處理
1 人贊了文章
1 顏色空間轉換
1.1. OpenCV有超過150種進行顏色空間轉換的方法,最常用BGR與GRAY/HSV轉換
1.2. HSV:Hue色調,Saturation飽和度,Value明度,HSV比GBR更容易表示特定顏色
1.3. 函數:cv2.cvtColor()
1.4. cv2.inRange()可根據閾值,生成特定顏色的掩模
2 幾何變換
2.1. 擴展縮放:cv2.resize()
2.2. 平移/旋轉:cv2.warpAffine() + 2x3移動矩陣
2.3. 旋轉矩陣:cv2.getRotationMatrix2D()=>構建旋轉矩陣
2.4. 仿射變換矩陣:cv2.getAffineTransform()=>構建仿射變換矩陣2x3
2.5. 透視變換矩陣:cv2.getPerspectiveTransform()=>3x3透視變換矩陣
2.6. 透視變換:cv2.warpPerspective()+ 3x3移動矩陣,常用於圖像矯正
2.7. 仿射變換可保證物體形狀平直性和平行性,透視不能保證平行性,仿射是透視特例
3 圖像閾值
3.1. 簡單閾值:cv2.threshold()
3.2. 自適應閾值:cv2.adaptiveThreshold()
3.3. Otsu』s二值化:大津法,最大類間方差法,該演算法返回最優閾值,不適合非雙峰圖像
4 圖像平滑
4.1. 與一維信號一樣,我們也可以對2D圖像實施低通濾波器(LPF)來去除雜訊、模糊圖像,使用高通濾波器(HPF)找到圖像的邊緣。
4.2. 卷積操作:cv2.filter2D() + 卷積核
4.3. 圖像模糊(圖像平滑)使用LPF來實現。OpenCV提供了四種模糊技術:
4.3.1 平均:平均值代替中心元素=》cv2.blur() 和cv2.boxFilter()
4.3.2 高斯模糊:卷積核換成高斯核=》cv2.GaussianBlur(),自己也可以構造高斯核: cv2.getGaussianKernel()
4.3.3 中值模糊:中值代替中心元素=》cv2.medianBlur()
4.3.4 雙邊濾波:同時考慮空間高斯權重(確保鄰域像素對中心點有影響)和灰度值 相似權重(確保只有與中心點灰度值相近的才會用來做模糊運算),邊界處灰 度值變化大,不會被模糊掉,保持邊界清晰=》cv2.bilateralFilter()
5 形態學轉換
5.1. 前景為白色,背景為黑色。兩個基本形態學操作為:腐蝕和膨脹
5.2. 腐蝕:卷積核沿圖像滑動,若卷積核對應圖像所有像素為1,則中心元素就保持原像素值,否則變為0(白色變少,黑色變多)=》cv2.erode()
5.3. 膨脹:與腐蝕相反,與卷積核對應的原圖像的像素值只要一個為1,則中心元素值就是1,否則為0.(白色變多,黑色變少)=>cv2.dilate()
5.4. 開運算:先腐蝕再膨脹,可消除雜訊=》cv2.morphologyEx()
5.5. 閉運算:先膨脹再腐蝕,可填小黑洞=》cv2.morphologyEx()
5.6. 形態學梯度:膨脹與腐蝕之差=》cv2.morphologyEx()
5.7. 頂帽(Top Hat):原圖與開運算之差
5.8. 黑帽:閉運算與原圖之差
5.9. 結構化元素:告訴核的形狀核大小=>cv2.getStructuringElement()==》生成核
6 圖像梯度
6.1. 梯度濾波器也就是HPF,Sobel,Scharr其實就是求一階或者二階導數,Laplacian求二階導數。Scharr是使用小卷積核求解梯度角度時,對Sobel的優化。梯度也為圖像
6.2. Sobel運算元:高斯平滑與微分操作的結合體,可設置求導方向和階數,ksize=-1時會使用Scharr濾波器,效果比Sobel好。
6.3. Laplacian運算元:OpenCV在計算拉普拉斯運算元時直接調用Sobel運算元
6.4. 圖像深度:指存儲每個像素所用的位數,也用於度量圖像色彩的解析度.
6.5. 圖像求導可能有負數,原深度圖為np.uint8時,負數會截斷為0,邊界丟失.因此需要將數據類型設置成更高的,然後取其絕對值轉換回來.
7 Canny邊緣檢測
7.1. 1986年 John提出
7.2. 原理由很多步組成:
7.2.1 雜訊去除:邊緣檢測易受雜訊影響,高斯濾波器去雜訊
7.2.2 計算圖像梯度:Sobel計算水平及豎直方向一階導數(圖像梯度Gx,Gy)
梯度一般總與邊界垂直,分四類:豎直,水平,兩對角線(?這個地方沒理解)
7.2.3非極大值抑制:對整幅圖掃描,去除非邊界上的點,看這個點的梯度是否是周圍同梯度方向的點中最大的.
7.2.4 滯後閾值:設置兩個閾值,灰度值高於最大的被認為是真的邊界,低於最小值的直 接被拋棄,介於兩者之間的,若與真正邊界相連,則為邊界,否則拋棄
7.3. 函數:cv2.Canny()
8 圖像金字塔
8.1. 有時需要對同一圖像不同解析度的子圖像進行處理,最大的放底部,最小的放頂部,依次形成金字塔,共有兩類:高斯金字塔和拉普拉斯金字塔.
8.2. 下採樣: cv2.pyrDown()從高解析度大尺寸的圖像向上構建金子塔,尺寸變小解析度變低, 會縮小圖像丟失圖像信息,過程為:
8.2.1 與高斯模板進行卷積
8.2.2 去除偶數行和偶數列
8.3. 上採樣:cv2.pyrUp()從低解析度小尺寸圖像向下構建金字塔,尺寸變大但是解析度不會增加, 會放大圖像也會丟失信息,過程為:
8.3.1在每個方向上擴大為原來的兩倍,新增行列用0填充
8.3.2 使用同樣的高斯模板(數值上乘以4)與新的圖像進行卷積
8.4. 拉普拉斯金字塔由高斯金字塔計算而來,公式為:
,通過原圖像減去先縮小後放大的圖像的一些列圖像構成的.配合高斯金字塔使用,可以預測殘差,對圖像最大程度還原.
8.5. 圖像金字塔的一個應用就是圖像融合.
9 OpenCV中的輪廓
9.1. 輪廓:將連續的點連在一起的曲線,具有相同的顏色和灰度.
9.2. 輪廓在形狀分析和物體的檢測和識別中很有用
9.3. 為了更準確,需要二值化圖像.在尋找之前,需要閾值化處理或者Canny邊界檢測. 查找輪廓的函數會修改原始圖片,請注意保存,白色為前景
9.4. 查找輪廓: cv2.findContours() 繪製輪廓:cv2.drawContours()=>第三個參數為輪廓索引
9.5. 輪廓特徵:矩, 輪廓面積, 輪廓周長, 輪廓近似, 凸包, 邊界矩形,最小外接圓等
9.6. 輪廓性質:長寬比, Extent,Solidity,等效直徑,方向,掩模,最大最小位置,平均顏色/灰度等
9.7. 更多函數:
9.7.1 凸缺陷: cv.2convexHull()=>找凸包, cv2.convexityDefect()=>判斷
9.7.2 點到對象輪廓最短距離:cv2.pointPolygonTest()
9.7.3 形狀匹配: cv2.matchShape()
9.8. 輪廓的層次結構==>知道其層次結構
10 直方圖(Histogram)
10.1. 直方圖是對圖像的另一種解釋.x是灰度值,y是圖像中具有同一灰度值的點個數
10.2. BINS:將x軸分為很多小組,每個小組稱為BIN; DIMS:收集數據的參數個數;RANGE:要統計的灰度值的範圍
10.3. 函數:cv2.calcHist()
10.4. ravel()方法,flatten方法都是將數據轉化成一維,前者返回view,後者返回copy
10.5. 直方圖均勻化:一副高質量的圖像的像素值分布應該很廣泛,cv2.equalizeHist()
10.6. 當圖像集中在某一個灰度值範圍內時,直方圖均勻化很有用.當像素變化很大,分布很廣時,查看專門的調整對比度和亮度的文章(教程中給出鏈接了)
10.7. 直方圖均衡化會改變圖像的對比度,但很多時候效果不好.原因在於圖像並不集中在某一個區域,為此我們需要自適應的直方圖均衡化,即將圖像分成很多小塊,對於每一小塊,像素比較集中;但是有雜訊就會被放大,就需要使用對比度限制;為了去除每小塊間」人造」邊界,使用雙線性插值, cv2.createCLACHE()
10.8. 2D直方圖:只考慮灰度值,使用1.10中的一維直方圖,2D直方圖我們就考慮兩個圖像特徵,對於彩色圖片,我們通常考慮每個顏色的顏色(Hue)和飽和度(Saturation)
10.8.1函數同一維:cv2.calcHist(),參數變成二維channels=[0,1],bins=[180,256]
10.8.2 注意,顏色Hue的取值為0到180
10.9. 直方圖反向投影
10.9.1 用途:圖像分割,尋找感興趣區域
10.9.2 輸出:與輸入圖像(待搜索)同樣大小的圖像,輸出圖像的每一像素代表輸入圖像中的對應點在目標圖像中出現的概率,用頻數來表示。經常與camshift演算法等一起使用。
10.9.3 實現:首先創建查找目標直方圖,目標盡量佔滿這張圖像,最好使用顏色圖,因為物體的顏色比它的灰度更好地用於圖像分割和對象識別;將這個直方圖投影到輸入圖像中,即找出輸入圖像的每一像素在目標直方圖中的概率,得到與輸入同大小的概率圖像;設置適當閾值對概率圖進行二值化。
10.9.4 函數:cv2.calcBackProject() 參數與cv2.calcHist基本相同。在做反向投影之前需要對目標直方圖進行歸一化處理,使之值在0~255之間,因為直方圖中的值可能超過255!
11 圖像變換
11.1. 傅里葉變換:經常用來分析不同濾波器的頻率特性。2D離散傅里葉變換(DFT)分析圖像的頻域特性,實現DFT的一個快速演算法稱為快速傅里葉變換(FFT)。
11.2. 對圖像同時進行X方向和Y方向的傅里葉變換,我們會得到這幅圖像的頻域表示(頻譜圖),如果變化非常快稱為高頻信號,變換慢稱為低頻信號。在圖像中邊界和雜訊是圖像中的高頻分量(指的是快而非多)。
11.3. 函數:cv2.dft()和cv2.idft()
11.4. DFT性能優化:當數據大小是2的指數時效率高,2,3,4的倍數時也高,當圖像大小不是這些數據的時候可以手動補0以加快速度(註:Numpy裡面函數會自動加)
12 模板匹配
12.1. 模板匹配:在一副大圖中搜索查找模板圖像位置的方法。和2D卷積一樣,用模板圖像在輸入圖像(大圖)上滑動,在每一位置比較模板圖和在大圖中對應的子區域,返回灰度圖像,像素值表示此區域與模板的匹配程度。
12.2. 函數:cv2.matchTemplate()匹配; cv2.minMaxLoc()返回最小最大位置(左上角的點)
12.3. 多對象匹配:不用cv2.minMaxLoc(),而是使用閾值自己來找匹配位置
13 Hough直線變換
13.1. 霍夫變換在檢測各種形狀的技術中非常流行。要檢測的形狀可以用數學表達式寫出,就可以使用霍夫變換檢測它,即使要檢測的形狀存在一點破壞或扭曲。
13.2. 過程:每條直線可以用 來表示,首先需要建立一個二維數組(累加器),行表示 ,列表示 ,數組大小決定結果的準確性,數組越大說明分得越細。取直線上的某一個點,然後遍歷所有的 ,得到不同的 ,形成 點對,如果點對在累加器中,則累加器相應位置加1,不斷更新累加器,搜索累加器的最大值,找出其位置,就找到了直線。
13.3. 在獲取變化前需要對圖像二值化或者進行Canny邊緣檢測,累加器中的值高於某一閾值時,才會被認為是一條直線,可看做檢測到的直線的最短長度(像素值)。
13.4. 函數:cv2.HoughLines()=>返回
13.5. 霍夫變換優化:Probabilistic Hough Transform,不是對每一點計算,而是隨機選取,但是這種變換我們必須降低閾值。
13.6. 函數cv2.HoughLinesP()返回值是直線的起點和終點。參數MaxLineGap表示最大間隔,如果小於此值,則兩條直線可以看成是一條直線。
14 Hough圓環變換
14.1. 一個圓環需要三個參數確定:圓心坐標和半徑,所以累加器必須是三維的,但這樣做效率低,Opencv用比較巧妙的辦法:霍夫梯度法,可使用邊界的梯度信息。
14.2. 函數:cv2.HoughCircles()
15 分水嶺演算法圖像分割
15.1. 原理:灰度圖可看成拓撲平面,灰度值高看成峰,低看成谷。往山谷裡面灌不同顏色的水,隨著水位上升,山谷會彙集,為防止彙集,就做一個堤壩,不停灌水並且不停修建堤壩直到所有山峰被水淹沒,構建的堤壩就是對圖像的分割。
15.2. 上述方法會出現過分割,這是由於雜訊和圖像中的其他不規律因素造成的,為減少影響,OpenCV採用基於掩模的分水嶺演算法,這種演算法需要設置哪些山谷點會匯合,哪些不會,我們要做的就是對已知對象打上不同標籤:某區域一定是前景或對象則使用某個顏色(灰度值)標記,某區域肯定不是對象而是背景,則用另一種顏色標記,剩下不確定的就為0,然後再實施分水嶺演算法,每一次灌水,就更新一下標籤,不同顏色標籤相遇,則構成堤壩,直到所有山峰淹沒,邊界對象(堤壩)值為-1
15.3. 距離變換:計算圖像中非零點像素到最近零像素點的距離,演算法通過連續腐蝕實現
15.4. 使用連通域函數:cv2.connectedComponents()可以對不同區域進行標記,需要注意的是,此函數將背景標記為0,其他對象從1開始正整數標記,分水嶺演算法中0表示不確定,可將連通域函數結果整體加1來處理。
15.5. 函數:cv2.watershed()
16 使用GrabCut演算法進行互動式前景提取
16.1. 一種互動式程序用於提取前景
16.2. 高斯混合模型(GMM):多個高斯分布函數的線性組合理論上可擬合出任意類型,通常由於解決同一集合下的數據包含多個不同的分布的情況。
16.3. 過程:用戶輸入矩形框,框外為背景,框內為未知;計算機對輸入圖形進行標記;使用GMM對前景和背景建模,學習並創建新的像素分布;根據像素分布創建一幅圖:像素點為節點,另加Source_node和Sink_node,前景跟前者相連,背景跟後者相連;像素與Source_node和Sink_node的連接權重由同屬於一類(同屬於前景或背景)的概率決定,像素點間的權重由相似性決定;使用mincut演算法,對上面所得圖像進行分割。
16.4. 函數:cv2.grabCut()
推薦閱讀:
TAG:計算機視覺 | 機器學習 | 深度學習DeepLearning |