opencv roberts算子_图像之HOG特征描述算子-行人检测
4.1 簡介
本次任務將學習一種在深度學習之前非常流行的圖像特征提取技術——方向梯度直方圖(Histogram of Oriented Gradients),簡稱HOG特征。HOG特征是在2005年CVPR的會議發表,在圖像手工特征提取方面具有里程碑式的意義,當時在行人檢測領域獲得了極大成功。
學習HOG特征的思想也有助于我們很好地了解傳統圖像特征描述和圖像識別方法,本次任務我們將學習到HOG背后的設計原理,和opencv的實現。
4.2 內容介紹
1. HOG特征簡介
HOG特征是一種圖像局部特征,其基本思路是對圖像局部的梯度幅值和方向進行投票統計,形成基于梯度特性的直方圖,然后將局部特征拼接起來作為總特征。局部特征在這里指的是將圖像劃分為多個子塊(Block), 每個Block內的特征進行聯合以形成最終的特征。
HOG+SVM的工作流程如下:
首先對輸入的圖片進行預處理,然后計算像素點的梯度特特性,包括梯度幅值和梯度方向。然后投票統計形成梯度直方圖,然后對blocks進行normalize,最后收集到HOG feature(其實是一行多維的vector)放到SVM里進行監督學習,從而實現行人的檢測。下面我們將對上述HOG的主要步驟進行學習。
2.HOG特征的原理
圖像預處理
預處理包括灰度化和Gamma變換。
灰度處理是可選操作,因為灰度圖像和彩色圖像都可以用于計算梯度圖。對于彩色圖像,先對三通道顏色值分別計算梯度,然后取梯度值最大的那個作為該像素的梯度。
然后進行伽馬矯正,調節圖像對比度,減少光照對圖像的影響(包括光照不均和局部陰影),使過曝或者欠曝的圖像恢復正常,更接近人眼看到的圖像。
- 伽馬矯正公式:
如圖,當
取不同的值時對應的輸入輸出曲線( 時輸入輸出保持一致) : 1) 當時,輸入圖像的低灰度值區域動態范圍變大,進而圖像低灰度值區域對比度得以增強;在高灰度值區域,動態范圍變小,進而圖像高灰度值區域對比度得以降低。 最終,圖像整體的灰度變亮。2) 當
時,輸入圖像的低灰度值區域動態范圍變小,進而圖像低灰度值區域對比度得以降低;在高灰度值區域,動態范圍變大,進而圖像高灰度值區域對比度得以增強。 最終,圖像整體的灰度變暗。import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('E:/python-project/deep-learning/picture/test1.jpg', 0) img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) img2 = np.power(img/float(np.max(img)),1/2.2) plt.imshow(img2) plt.axis('off') plt.show()計算圖像梯度
為了得到梯度直方圖,那么首先需要計算圖像水平方向和垂直方向梯度。 一般使用特定的卷積核對圖像濾波實現,可選用的卷積模板有:soble算子、Prewitt算子、Roberts模板等等。
一般采用soble算子,OpenCV也是如此,利用soble水平和垂直算子與輸入圖像卷積計算
、:進一步可以得到圖像梯度的幅值:
為了簡化計算,幅值也可以作如下近似: 角度為:這里需要注意的是:梯度方向和圖像邊緣方向是互相正交的。
import cv2 import numpy as np# Read image img = cv2.imread('E:/python-project/deep-learning/picture/test1.jpg') img = np.float32(img) / 255.0 # 歸一化# 計算x和y方向的梯度 gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1) gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)# 計算合梯度的幅值和方向(角度) mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)計算梯度直方圖
經過上一步計算,每一個像素點都會有兩個值:梯度幅值/梯度方向。
在這一步中,圖像被分成若干個8×8的cell,例如我們將圖像resize至64x128的大小,那么這幅圖像就被劃分為8x16個8x8的cell單元,并為每個8×8的cell計算梯度直方圖。當然,cell的劃分也可以是其他值:16x16,8x16等,根據具體的場景確定。
在計算梯度直方圖,讓我們先了解一下為什么我們將圖像分成若干個cell?
這是因為如果對一整張梯度圖逐像素計算,其中的有效特征是非常稀疏的,不但運算量大,而且會受到一些噪聲干擾。于是我們就使用局部特征描述符來表示一個更緊湊的特征,計算這種局部cell上的梯度直方圖更具魯棒性。
以8x8的cell為例,一個8x8的cell包含了8x8x2 = 128個值,因為每個像素包括梯度的大小和方向。
在HOG中,每個8x8的cell的梯度直方圖本質是一個由9個數值組成的向量, 對應于0、20、40、60…160的梯度方向(角度)。那么原本cell中8x8x2 = 128個值就由長度為9的向量來表示,用這種梯度直方圖的表示方法,大大降低了計算量,同時又對光照等環境變化更加地魯棒。
首先,看下圖:
左圖是衣服64x128的圖像,被劃分為8x16個8x8的cell;中間的圖像表示一個cell中的梯度矢量,箭頭朝向代表梯度方向,箭頭長度代表梯度大小。
右圖是 8×8 的cell中表示梯度的原始數值,注意角度的范圍介于0到180度之間,而不是0到360度, 這被稱為“無符號”梯度,因為兩個完全相反的方向被認為是相同的。
接下來,我們來計算cell中像素的梯度直方圖,將0-180度分成9等份,稱為9個bins,分別是0,20,40...160。然后對每個bin中梯度的貢獻進行統計:
統計方法是一種加權投票統計, 如上圖所示,某像素的梯度幅值為13.6,方向為36,36度兩側的角度bin分別為20度和40度,那么就按一定加權比例分別在20度和40度對應的bin加上梯度值,加權公式為:
40度對應的bin:((40-36)/20) * 13.6,分母的20表示20等份,而不是20度; 20度對應的bin:((36-20)/20) * 13.6,分母的20表示20等份,而不是20度;
還有一個細節需要注意,如果某個像素的梯度角度大于160度,也就是在160度到180度之間,那么把這個像素對應的梯度值按比例分給0度和160度對應的bin。如左下圖綠色圓圈中的角度為165度,幅值為85,則按照同樣的加權方式將85分別加到0度和160度對應的bin中。
對整個cell進行投票統計,正是在HOG特征描述子中創建直方圖的方式,最終得到由9個數值組成的向量—梯度方向圖:
Block 歸一化 HOG特征將8×8的一個局部區域作為一個cell,再以2×2個cell作為一組,稱為一個block,也就是說一個block表示16x16的區域。
我們可能會想,為什么又需要分block呢?
這是因為,雖然我們已經為圖像的8×8單元創建了HOG特征,但是圖像的梯度對整體光照很敏感。這意味著對于特定的圖像,圖像的某些部分與其他部分相比會非常明亮。
我們不能從圖像中完全消除這個。但是我們可以通過使用16×16個塊來對梯度進行歸一化來減少這種光照變化。
由于每個cell有9個值,一個block(2×2個cell)則有36個值,HOG是通過滑動窗口的方式來得到block的.
前面已經說明,歸一化的目的是為了降低光照的影響,因為梯度對整體光照非常敏感,比如通過將所有像素值除以2來使圖像變暗,那么梯度幅值將減小一半,因此直方圖中的值也將減小一半,我們就需要將直方圖“歸一化”。
歸一化的方法有很多:L1-norm、L2-norm、max/min等等,一般選擇L2-norm。
例如對于一個[128,64,32]的三維向量來說,模長是
,這叫做向量的L2范數。將這個向量的每個元素除以146.64就得到了歸一化向量 [0.87, 0.43, 0.22]。采用同樣的方法,一個cell有一個梯度方向直方圖,包含9個數值,一個block有4個cell,那么一個block就有4個梯度方向直方圖,將這4個直方圖拼接成長度為36的向量,然后對這個向量進行歸一化。
而每一個block將按照上圖滑動的方式進行重復計算,直到整個圖像的block都計算完成。
獲得HOG描述子
每一個16 * 16大小的block將會得到一個長度為36的特征向量,并進行歸一化。 那會得到多少個特征向量呢?
例如,對于上圖被劃分8 * 16個cell ,每個block有2x2個cell的話,那么cell的個數為:(16-1)x(8-1)=105。即有7個水平block和15個豎直block。
每個block有36個值,整合所有block的特征值,最終獲得由36 * 105=3780個特征值組成的特征描述符,而這個特征描述符是一個一維的向量,長度為3780。
獲得HOG特征向量,就可以用來可視化和分類了。對于多維的HOG特征,SVM就可以排上用場了。
4.3 基于OpenCV的實現
import cv2 as cv import numpy as np from matplotlib import pyplot as pltif __name__ == '__main__':src = cv.imread("E:/python-project/deep-learning/picture/test7.jpg")cv.imshow("input", src)hog = cv.HOGDescriptor()hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector())# Detect people in the image(rects, weights) = hog.detectMultiScale(src,winStride=(2,4),padding=(8, 8),scale=1.2,useMeanshiftGrouping=False)for (x, y, w, h) in rects:cv.rectangle(src, (x, y), (x + w, y + h), (0, 255, 0), 2)cv.imshow("hog-detector", src)cv.imwrite("hog-detector.jpg",src)cv.waitKey(0)cv.destroyAllWindows()效果不咋好。。。換一個
可視化:
from skimage import feature, exposure from matplotlib import pyplot as plt import cv2 image = cv2.imread('E:/python-project/deep-learning/picture/test8.jpg') image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)fd, hog_image = feature.hog(image, orientations=9, pixels_per_cell=(8, 8),cells_per_block=(2, 4), visualise=True)# Rescale histogram for better display hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 10))cv2.namedWindow("img",cv2.WINDOW_NORMAL) cv2.imshow('img', image) cv2.namedWindow("hog",cv2.WINDOW_NORMAL) cv2.imshow('hog', hog_image_rescaled) cv2.waitKey(0)==ord('q')4.4 總結
HOG算法具有以下優點:
- HOG描述的是邊緣結構特征,可以描述物體的結構信息
- 對光照影響不敏感
- 分塊的處理可以使特征得到更為緊湊的表示
HOG算法具有以下缺點:
- 特征描述子獲取過程復雜,維數較高,導致實時性差
- 遮擋問題很難處理
- 對噪聲比較敏感
論文地址:Histograms of Oriented Gradients for Human Detection - 2005CVPR
總結
以上是生活随笔為你收集整理的opencv roberts算子_图像之HOG特征描述算子-行人检测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql中selectform_带有s
- 下一篇: java web 进程通信_RMI网络编