計算機視覺系列:學習筆記(一)
一. 影象基礎:畫素
畫素是影象最基礎的構成要素,每一張影象都是由畫素集合組成。
如果我們將影象當作一個網格,則每一小塊是由單個畫素組成,如下圖:
上圖的解析度為1000 * 750,意味著有1000畫素寬,750畫素高。可以將一張影象看作一個多維矩陣,此時矩陣為1000列(寬)* 750行(高),在影象中一共有1000 * 750 = 750,000個畫素組成。
大多數畫素在兩種情況作為表示:
1.灰度/單通道
2.顏色
在灰度圖中,每個畫素的值在【0,255】的範圍之間,其中0對應黑色,而255當作白色。在0到255之間的值是不同程度的灰色,靠近0越來越黑,靠近255的越來越白。如下圖:
在RGB的顏色通道中,畫素則代表了3個值的列表,一個對應紅色,一個對應綠色,一個對應藍色。同樣的,每個顏色通道取值也在範圍【0,255】中,0代表不表示當前顏色,255代表全部表示當前顏色。
給定紅綠藍三種顏色的值,可以將他們以(紅,綠,藍)的格式組合成一個元組,這個元組代表著RGB通道中的圖片。
在運用中,我們可以用矩陣表示法將RGB圖片組成3個獨立的W * H的矩陣,通過將RGB三個通道的W * H矩陣結合,可以得到一個多維矩陣(W * H * D),其中D代表深度或者通道的個數(對於RGB通道,D = 3)。
例如,使用OpenCV庫和cv2的imread函式來讀取圖片,並展示它的維度:
import cv2
image = cv2.imread("example.png")
print(image.shape)
cv2.imshow("Image", image)
cv2.waitKey(0)
利用上面一段程式碼可以得到輸入圖片的維度(W * H * D):
(731, 1024, 3)
同樣我們可以指定圖片中某一維度的座標,得到RGB的值,如下:
1 (b, g, r) = image[20, 100] # accesses pixel at x=100, y=20
2 (b, g, r) = image[75, 25] # accesses pixel at x=25, y=75
3 (b, g, r) = image[90, 85] # accesses pixel at x=85, y=90
注意:實際在OpenCV中取出的並非RGB而是BGR(由於歷史原因),另外座標第一維通常是Y,第二維時X。
關於影象的尺寸變換:
通常在影象處理中,會對影象加以壓縮或者伸展,但是影象本身具有長寬比,如果不以影象本身的長寬比處理,會造成影象畸變或者扭曲。對於卷積神經網路而言,通常以固定尺寸作為輸入,如:32*32,64*64,224*224,227*227,256*256。這就要求我們要對影象進行預處理,將尺寸變換為合適大小。
此時有兩種方案:1,不考慮影象本身的長寬比,直接進行尺寸變換;
2,根據影象本身的長寬比變換到最小維度,取影象中心區域的需要識別的一塊。實際在應用中,視情況而定,對於一些資料集可以忽視長寬比。而在另外的一些資料集中,第二種會表現出較好的效果。
二.影象分類基礎
影象分類的核心是將一個標籤分配給一個預定義的影象的任務,目標就是獲取這個輸入影象並從我們類別中給它分配一個標籤,即給一個W * H的RGB三通道影象,根據這W * H * 3 = N 個畫素得出如何正確分類影象的內容。
資料集:一組圖片
資料點:每張圖片
影象分類面臨的挑戰
1.視角變化
2.尺度變化
3.遮擋變化
4.變形(曲變等)
5.光照變化
6.背景噪聲
7.同類間變化(如沙發椅、藝術椅和辦公椅等同類之間的變化)
由於影象分類中存在以上並不止以上的挑戰,所以影象分類的關鍵是:
要始終考慮分類器的範圍
除非你是有多年經驗的影象分類專家,你也不一定有能力構建能把“整個廚房裡所有的物體”準確識別的分類器。但是如果把問題框定在某一範圍內,比如識別火爐和冰箱,還是很有可能完成的。
ImageNet是影象分類演算法的事實上的標準基準資料集,它包含了我們日常生活中遇到的1000個物件,而這個資料集仍然被研究者們積極地使用,試圖將最先進的技術推向深入學習的前沿。
影象分類步驟
1.獲取資料集
構建深度學習網路的第一個元件是收集我們的初始資料集。我們需要影象本身以及與每個影象相關的標籤。這些標籤應該來自有限的類別,例如:類別=狗,貓,熊貓。
此外,每個類別的影象數量應該近似一致(即:,每個類別的例子數量相同)。如果我們的貓影象數量是狗影象的兩倍,而熊貓影象的數量是貓影象的五倍,那麼我們的分類器就會自然地偏向於過度擬合這些重量級的類別。
2.資料集劃分
一般分為:訓練集和測試集,兩者保持獨立。
在機器學習中常見交叉驗證。訓練和測試集的常見分割大小包括66:6%和33:3%、75%和25%以及90%和10%。
對於網路中超引數的調節,可以設定驗證集來對網路超引數進行調節。
3.訓練網路
考慮到我們的訓練集,我們現在可以訓練我們的網路。這裡的目標是讓我們的網路學習如何識別標籤資料中的每一個類別。當模型出錯時,它會從錯誤中吸取教訓並自我完善。
4.評估
最後,我們需要評估我們經過訓練的網路。對於我們測試集中的每一個影象,我們將它們呈現給網路,並要求它預測影象的標籤是什麼。然後,我們對測試集中的影象的模型進行對比。
最後,將這些模型預測與我們測試集的地面真相標籤進行比較。從那裡,我們可以計算出我們的分類器得到正確的預測的數量,並計算諸如precision、recall和f-measure這樣的聚合報告,這些報告用於量化我們整個網路的效能。
需要注意的是:
在傳統的基於特徵的影象分類方法中,實際上在步驟2和步驟3之間插入了一個步驟,這一步就是特徵提取。在這一階段,我們應用諸如HOG、LBPs等手工工程演算法來量化基於我們想要編碼的影象的某一特定元件的影象的內容(形狀、顏色、紋理)。考慮到這些特徵,我們接著訓練分類器並對其進行評估。
在構建卷積神經網路時,我們實際上可以跳過特徵提取步驟。這是因為CNNs是端到端的模型。我們將原始輸入資料(畫素)呈現給網路。然後,網路在其隱藏層中學習過濾器,可以用來區分物件類。然後,網路的輸出是在類標籤上的概率分佈。
影象分類最重要的指標:泛化能力。即一個網路對一個不作為其訓練或測試資料一部分的影象的類標籤進行一般化和正確預測的能力。
三.基本的影象處理
機器學習演算法,如k-NN, SVMs,甚至卷積神經網路都要求資料集中的所有影象具有固定的特徵向量大小。在影象的情況下,這個要求意味著我們的影象必須經過預處理和縮放,以達到相同的寬度和高度。
有許多方法可以實現這種大小調整和縮放,從更高階的方法,比如尊重原始影象的寬比和縮放影象,到忽略寬高比的簡單方法,簡單地將寬度和高度壓縮到所需的尺寸。確切地說,你應該使用哪種方法取決於你的變化因素的複雜性,在某些情況下,忽略長寬比很好;在其他情況下,您將希望保持長寬比。
1.載入圖片
def load(self,imagePaths,verbose = 1):
'''
initialize the list of feat
'''
data = []
labels = []
#loop over the input images
for(i,imagePath) in enumerate(imagePaths):
'''
load the image and extract the class label assuming
that our path has the following format:
/path/to/dataset/{class}/{image}.jpg
'''
image = cv2.imread(imagePath)
label = imagePath.split(os.path.sep)[-2]
載入圖片需要用到圖片所在的路徑,其中:
enumerate()說明
enumerate()是python的內建函式
enumerate在字典上是列舉、列舉的意思
對於一個可迭代的(iterable)/可遍歷的物件(如列表、字串),enumerate將其組成一個索引序列,利用它可以同時獲得索引和值
enumerate多用於在for迴圈中得到計數
例如對於一個seq,得到:
(0, seq[0]), (1, seq[1]), (2, seq[2])