圖像學習之如何理解方向梯度直方圖(Histogram Of Gradient)

2020-11-30 雷鋒網

雷鋒網(公眾號:雷鋒網)按:本文作者Slyne_D,原文載於作者的簡書主頁,雷鋒網經授權發布。

本文主要翻譯了Histogram of Oriented Gradients一文。

特徵描述子(Feature Descriptor)

特徵描述子就是圖像的表示,抽取了有用的信息,丟掉了不相關的信息。通常特徵描述子會把一個w*h*3(寬高3,3個channel)的圖像轉換成一個長度為n的向量/矩陣。比如一副64*128*3的圖像,經過轉換後輸出的圖像向量長度可以是3780。

什麼樣子的特徵是有用的呢?假設我們想要預測一張圖片裡面衣服上面的扣子,扣子通常是圓的,而且上面有幾個洞,那你就可以用邊緣檢測(edge detector),把圖片變成只有邊緣的圖像,然後就可以很容易的分辨了,那麼對於這張圖邊緣信息就是有用的,顏色信息就是沒有用的。而且好的特徵應該能夠區分紐扣和其它圓形的東西的區別。

方向梯度直方圖(HOG)中,梯度的方向分布被用作特徵。沿著一張圖片X和Y軸的方向上的梯度是很有用的,因為在邊緣和角點的梯度值是很大的,我們知道邊緣和角點包含了很多物體的形狀信息。

(HOG特徵描述子可以不局限於一個長度,也可以用很多其他的長度,這裡只記錄一種計算方法。)

怎麼計算方向梯度直方圖呢?

我們會先用圖像的一個patch來解釋。

第一步:預處理

Patch可以是任意的尺寸,但是有一個固定的比例,比如當patch長寬比1:2,那patch大小可以是100*200, 128*256或者1000*2000但不可以是101*205。

這裡有張圖是720*475的,我們選100*200大小的patch來計算HOG特徵,把這個patch從圖片裡面摳出來,然後再把大小調整成64*128。


hog_preprocess

第二步:計算梯度圖像

首先我們計算水平和垂直方向的梯度,再來計算梯度的直方圖。可以用下面的兩個kernel來計算,也可以直接用OpenCV裡面的kernel大小為1的Sobel算子來計算。


horizontal_vertical_gradient_kernel

調用OpenCV代碼如下:

// C++ gradient calculation.
// Read image
Mat img = imread("bolt.png");
img.convertTo(img, CV_32F, 1/255.0);

// Calculate gradients gx, gy
Mat gx, gy;
Sobel(img, gx, CV_32F, 1, 0, 1);
Sobel(img, gy, CV_32F, 0, 1, 1);

# Python gradient calculation 

# Read imageim = cv2.imread('bolt.png')
im = np.float32(im) / 255.0

# Calculate gradient
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)

接著,用下面的公式來計算梯度的幅值g和方向theta:


gradient_direction_formula

可以用OpenCV的cartToPolar函數來計算:

// C++ Calculate gradient magnitude and direction (in degrees)
Mat mag, angle;
cartToPolar(gx, gy, mag, angle, 1);

# Python Calculate gradient magnitude and direction ( in degrees )
mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)

計算得到的gradient圖如下:


左邊:x軸的梯度絕對值 中間:y軸的梯度絕對值 右邊:梯度幅值

從上面的圖像中可以看到x軸方向的梯度主要凸顯了垂直方向的線條,y軸方向的梯度凸顯了水平方向的梯度,梯度幅值凸顯了像素值有劇烈變化的地方。(注意:圖像的原點是圖片的左上角,x軸是水平的,y軸是垂直的)

圖像的梯度去掉了很多不必要的信息(比如不變的背景色),加重了輪廓。換句話說,你可以從梯度的圖像中輕而易舉的發現有個人。

在每個像素點,都有一個幅值(magnitude)和方向,對於有顏色的圖片,會在三個channel上都計算梯度。那麼相應的幅值就是三個channel上最大的幅值,角度(方向)是最大幅值所對應的角。

第三步:在8*8的網格中計算梯度直方圖

在這一步,上面的patch圖像會被分割成8*8大小的網格(如下圖),每個網格都會計算一個梯度直方圖。那為什麼要分成8*8的呢?用特徵描述子的一個主要原因是它提供了一個緊湊(compact)/壓縮的表示。一個8*8的圖像有8*8*3=192個像素值,每個像素有兩個值(幅值magnitude和方向direction,三個channel取最大magnitude那個),加起來就是8*8*2=128,後面我們會看到這128個數如何用一個9個bin的直方圖來表示成9個數的數組。不僅僅是可以有緊湊的表示,用直方圖來表示一個patch也可以更加抗噪,一個gradient可能會有噪音,但是用直方圖來表示後就不會對噪音那麼敏感了。


這個patch的大小是64*128,分割成8*8的cell,那麼一共有64/8 * 128/8 = 8*16=128個網格

對於64*128的這幅patch來說,8*8的網格已經足夠大來表示有趣的特徵比如臉,頭等等。

直方圖是有9個bin的向量,代表的是角度0,20,40,60.....160。

我們先來看看每個8*8的cell的梯度都是什麼樣子:


中間: 一個網格用箭頭表示梯度 右邊: 這個網格用數字表示的梯度

中間這個圖的箭頭是梯度的方向,長度是梯度的大小,可以發現箭頭的指向方向是像素強度變化方向,幅值是強度變化的大小。

右邊的梯度方向矩陣中可以看到角度是0-180度,不是0-360度,這種被稱之為"無符號"梯度("unsigned" gradients),因為一個梯度和它的負數是用同一個數字表示的,也就是說一個梯度的箭頭以及它旋轉180度之後的箭頭方向被認為是一樣的。那為什麼不用0-360度的表示呢?在事件中發現unsigned gradients比signed gradients在行人檢測任務中效果更好。一些HOG的實現中可以讓你指定signed gradients。

下一步就是為這些8*8的網格創建直方圖,直方圖包含了9個bin來對應0,20,40,...160這些角度。

下面這張圖解釋了這個過程。我們用了上一張圖裡面的那個網格的梯度幅值和方向。根據方向選擇用哪個bin, 根據副值來確定這個bin的大小。先來看藍色圓圈圈出來的像素點,它的角度是80,副值是2,所以它在第五個bin裡面加了2,再來看紅色的圈圓圈圈出來的像素點,它的角度是10,副值是4,因為角度10介於0-20度的中間(正好一半),所以把幅值一分為二地放到0和20兩個bin裡面去。


梯度直方圖

這裡有個細節要注意,如果一個角度大於160度,也就是在160-180度之間,我們知道這裡角度0,180度是一樣的,所以在下面這個例子裡,像素的角度為165度的時候,要把幅值按照比例放到0和160的bin裡面去。


角度大於160的情況

把這8*8的cell裡面所有的像素點都分別加到這9個bin裡面去,就構建了一個9-bin的直方圖,上面的網格對應的直方圖如下:


8*8網格直方圖

這裡,在我們的表示中,Y軸是0度(從上往下)。你可以看到有很多值分布在0,180的bin裡面,這其實也就是說明這個網格中的梯度方向很多都是要麼朝上,要麼朝下。

第四步: 16*16塊歸一化

上面的步驟中,我們創建了基於圖片的梯度直方圖,但是一個圖片的梯度對於整張圖片的光線會很敏感。如果你把所有的像素點都除以2,那麼梯度的幅值也會減半,那麼直方圖裡面的值也會減半,所以這樣並不能消除光線的影響。所以理想情況下,我們希望我們的特徵描述子可以和光線變換無關,所以我們就想讓我們的直方圖歸一化從而不受光線變化影響。

先考慮對向量用l2歸一化的步驟是:
v = [128, 64, 32]
[(128^2) + (64^2) + (32^2) ]^0.5=146.64
把v中每一個元素除以146.64得到[0.87,0.43,0.22]
考慮另一個向量2*v,歸一化後可以得到向量依舊是[0.87, 0.43, 0.22]。你可以明白歸一化是把scale給移除了。

你也許想到直接在我們得到的9*1的直方圖上面做歸一化,這也可以,但是更好的方法是從一個16*16的塊上做歸一化,也就是4個9*1的直方圖組合成一個36*1的向量,然後做歸一化,接著,窗口再朝後面挪8個像素(看動圖)。重複這個過程把整張圖遍歷一遍。


hog-16x16-block-normalization

第五步:計算HOG特徵向量

為了計算這整個patch的特徵向量,需要把36*1的向量全部合併組成一個巨大的向量。向量的大小可以這麼計算:

  1. 我們有多少個16*16的塊?水平7個,垂直15個,總共有7*15=105次移動。

  2. 每個16*16的塊代表了36*1的向量。所以把他們放在一起也就是36*105=3780維向量。

可視化HOG

通常HOG特徵描述子是畫出8*8網格中9*1歸一化的直方圖,見下圖。你可以發現直方圖的主要方向捕捉了這個人的外形,特別是軀幹和腿。


visualizing_histogram

雷鋒網版權文章,未經授權禁止轉載。詳情見轉載須知。

相關焦點

  • 人工智慧人臉探測原理--方向梯度直方圖
    我們將用的方法----方向梯度直方圖(Histogram of Oriented Gradients, HOG, 2005). 首先將照片轉成黑白照片,因為色彩的信息我們不需要.然後,我們依次關注照片中的每一個像素點. 對每個像素點, 我們想看看那些直接包圍著它的像素點. 我們的目標:計算出當前像素相對於其周圍的像素有多暗.
  • OpenCL 學習step by step (7) 灰度圖Histogram計算(1)
    histogram翻譯成中文就是直方圖,在計算機圖像處理和視覺技術中,通常用histogram來進行圖像匹配,從而完成track,比如meanshift跟蹤算法中,經常要用到圖像的直方圖。灰度圖的histogram計算,首先要選擇bin(中文可以稱作槽)的數量,對於灰度圖,像素的範圍通常是[0-255],所以bin的數目就是256,然後我們循環整幅圖像,統計出每種像素值出現的次數,放到對應的bin中。
  • OpenCV-Python 直方圖-3:二維直方圖|二十八
    目標在本章中,我們將學習查找和繪製2D直方圖。這將在以後的章節中有所幫助。介紹在第一篇文章中,我們計算並繪製了一維直方圖。 之所以稱為一維,是因為我們僅考慮一個特徵,即像素的灰度強度值。 但是在二維直方圖中,您要考慮兩個特徵。
  • 用Keras和「直方圖均衡」為深度學習實現「圖像擴充」
    在本文中,我們將討論一些常見的、富有創意的方法,這些方法也是Keras深度學習庫為擴充圖像數據所提供的。之後我們將討論如何轉換keras預處理圖像文件,以啟用直方圖均衡法。我們將使用Keras附帶的cifar10數據集,但是為了使任務小到能夠順利在CPU上執行,我們將只會使用其中的貓和狗的圖像。首先,我們需要加載cifar10數據集並格式化其中的圖像,為卷積神經網絡做好準備。
  • OpenCV-Python 直方圖-2:直方圖均衡|二十七
    目標在本節中,我們將學習直方圖均衡化的概念,並利用它來提高圖像的對比度。理論考慮這樣一個圖像,它的像素值僅局限於某個特定的值範圍。例如,較亮的圖像將把所有像素限制在高值上。但是一幅好的圖像會有來自圖像所有區域的像素。
  • 圖像特徵工程:HOG特徵描述子介紹
    我們可以將此技術擴展到非結構化數據(例如圖像)嗎?對於計算機視覺愛好者來說,這是一個有趣的問題,我們將在本文中解決這個問題。準備好對圖像數據進行特徵提取形式的特徵工程吧!在本文中,我將向你介紹一種流行的圖像特徵提取技術——方向梯度直方圖(Histogram of Oriented Gradients),或俗稱的HOG。
  • OpenCV-Python 直方圖-1:查找、繪製和分析|二十六
    目標學會使用OpenCV和Numpy函數查找直方圖使用OpenCV和Matplotlib函數繪製直方圖你將看到以下函數:cv.calcHist(),np.histogram理論那麼直方圖是什麼?您可以將直方圖視為圖形或繪圖,從而可以總體了解圖像的強度分布。它是在X軸上具有像素值(不總是從0到255的範圍),在Y軸上具有圖像中相應像素數的圖。這只是理解圖像的另一種方式。通過查看圖像的直方圖,您可以直觀地了解該圖像的對比度,亮度,強度分布等。
  • 基於直方圖的圖像增強算法(HE、CLAHE、Retinex)之(一)
    直方圖是圖像色彩統計特徵的抽象表述。基於直方圖可以實現很多有趣的算法。例如,圖像增強中利用直方圖來調整圖像的對比度、有人利用直方圖來進行大規模無損數據隱藏、還有人利用梯度直方圖HOG來構建圖像特徵進而實現目標檢測。
  • 如何理解圖像定位和跟蹤技術
    如何理解圖像定位和跟蹤技術 與非網 發表於 2019-10-12 15:25:41 在科學技術日新月異的今天,人們對機器設備的智能性、自主性要求也越來越高,希望其完全替代人的角色
  • OpenCV-Python 直方圖-4:直方圖反投影|二十九
    目標在本章中,我們將學習直方圖反投影。理論這是由Michael J. Swain和Dana H. Ballard在他們的論文《通過顏色直方圖索引》中提出的。它用於圖像分割或在圖像中查找感興趣的對象。簡而言之,它創建的圖像大小與輸入圖像相同(但只有一個通道),其中每個像素對應於該像素屬於我們物體的概率。用更簡單的話來說,與其餘部分相比,輸出圖像將在可能有對象的區域具有更多的白色值。好吧,這是一個直觀的解釋。(我無法使其更簡單)。直方圖反投影與camshift算法等配合使用。
  • Python學習第89課-數據可視化之直方圖繪製
    假設你想投資某一個城市的房地產,你肯定需要對這個城市的人口分布、增長潛力做一個調查,這時我們就需要做一個直方圖(histogram plot)。所以我們引入一個bin,就像垃圾分類一樣,我們給這些數據分類,相當於我們設定不同的年齡段,0-9歲裝到一個桶裡,10-19歲裝到一個桶裡,...,90-99歲裝到一個桶裡,即以10歲的間隔設置年齡段,以每一個年齡段為坐標畫一個柱狀圖,這些柱狀圖組合到一起,形成了直方圖。因此,我們大概可以這樣理解:直方圖就是把數據劃分區域後,以數據區域為節點繪製的柱狀圖的集合。
  • 【圖像基礎教程】直方圖均衡化
    一、直方圖均衡化概述  直方圖均衡化(Histogram Equalization
  • MedCalc16: 4.3.1分布圖: 直方圖
    4.3 分布圖MedCalc的分布圖包括直方圖(histogram)、累積頻率分布圖(cumulative frequency distribution
  • 如何直觀形象的理解方向導數與梯度以及它們之間的關係?
    下面我一開始不提梯度的概念,完全根據自己的理解進行下文的梳理,一步一步推出梯度的來歷:導數
  • CLAHE算法實現圖像增強「AI工程論」
    ,主要用在醫學圖像上面。CLAHE起到的作用簡單來說就是增強圖像的對比度的同時可以抑制噪聲CLAHE的英文是Contrast Limited Adaptive Histogram Equalization 限制對比度的自適應直方圖均衡。在
  • 教你快速看懂直方圖
    提到照片的直方圖,我們肯定有印象,在相機或軟體中預覽每張照片時都在圖像信息欄見到過這樣一個數軸狀的圖表與照片一一對應。這就是代表圖片中各色調分配比例的直方圖67(histogram)。而這些色調,是由通過鏡頭的光線而決定的,因此我們要把直方圖和曝光聯繫起來討論。一、什麼是直方圖。
  • 強化學習基礎-對偶梯度上升
    of deep reinforcement-learning-Dual Gradient Descent 作者 |Jonathan Hui 翻譯 | 史蒂芬•二狗子 校對 | 史蒂芬•二狗子 審核| 莫青悠 整理 | 菠蘿妹 原文連結: https://medium.com/@jonathan_hui/rl-dual-gradient-descent-fac524c1f049
  • 圖像算法工程師必備:灰度直方圖
    圖像的灰度直方圖,大概是數字圖像處理專業課接觸到的第一節講圖像具體算法的一堂課了。所謂的灰度直方圖,就是統計一個8比特的灰度圖像,其灰度等級從0到255的像素的分布情況。我們很容易就能想到,一幅圖像對應唯一的直方圖,而同一直方圖肯定會對應很多不同的圖像。
  • 視頻圖像中文本的檢測、定位與提取
    只有通過挖掘構成視頻的各種媒質所表達的豐富語義信息,克服單純的視覺特徵語義表達能力較弱這一缺點,充分提取視頻中的高層語義,才能符合人們對視頻信息的理解習慣,實現實用的基於內容的視頻檢索系統。梯度grad(f*θs)(x,y)在點(x,y)處的方向表示在圖像平面(x,y)上f(x,y)的方向導數的絕對值取極大值的方向。即計算一個光滑函數的導數沿梯度方向的模極大值等價於計算其小波變換的模極大值。