HOG圖像特征提取及其SK-imgae實(shí)現(xiàn)

前言


hog(image, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(3, 3),
        block_norm='L2-Hys', visualize=False, transform_sqrt=False,
        feature_vector=True, multichannel=None)

圖像標(biāo)準(zhǔn)化

在這一步怯邪,我們的主要目的是為了預(yù)處理圖像,減少光照等帶來(lái)的影響花墩。
f(I) = I^{ \gamma }

  • 此處我們選擇\gamma值小于1便會(huì)使圖像整體灰度變大悬秉,如果我們選擇\gamma值大于1便會(huì)使圖像整體灰度變小”ⅲ灰度的大小某種程度上決定了圖片的亮暗和泌,灰度越小,圖片越發(fā)昏暗祠肥,反之亦然武氓。

if transform_sqrt:
    image = np.sqrt(image)
  • skimage在此處的實(shí)現(xiàn)極為簡(jiǎn)潔,直接使用了開方來(lái)對(duì)圖片進(jìn)行處理仇箱。

圖像平滑

  • 去除灰度圖像的噪點(diǎn)县恕,一般選取離散高斯平滑模板進(jìn)行平滑,高斯函數(shù)在不同平滑的尺度下進(jìn)行對(duì)灰度圖像進(jìn)行平滑操作剂桥。Dalal的實(shí)驗(yàn)中moving from σ=0 to σ=2 reduces the recall rate from 89% to 80% at FPPW忠烛,反應(yīng)給出做了圖像平滑之后HOG效果反而變差。我們?cè)趯?shí)驗(yàn)過(guò)程中也得出了相似的結(jié)論权逗,很容易讓人想到美尸,HOG是基于圖像邊緣梯度的算法,但平滑過(guò)程有可能破壞邊緣的梯度信息旬迹,從而影響HOG的效果火惊。

梯度計(jì)算

  • 首先是像素點(diǎn)梯度的計(jì)算,我們使用I(x, y)來(lái)表示圖像上(x, y)像素點(diǎn)的像素值奔垦。那么每個(gè)像素點(diǎn)的水平和豎直方向的梯度(Gradient)可以分別被表示為:
    G_{x}(x, y)=I(x+1, y)-I(x-1, y)

G_{y}(x, y)=I(x, y+1)-I(x, y-1)

橫縱梯度表示

  • 那么顯然,作為兩個(gè)梯度矢量尸疆,它們的幅度值和角度\alpha也可以分別表示為:
    \begin{aligned} G(x, y) &=\sqrt{G_{x}(x, y)^{2}+G_{y}(x, y)^{2}} \\ \alpha &=\arctan \frac{G_{y}(x, y)}{G_{x}(x, y)} \end{aligned}

    if image.dtype.kind == 'u':
        # convert uint image to float
        # to avoid problems with subtracting unsigned numbers
        image = image.astype('float')

    if multichannel:
        g_row_by_ch = np.empty_like(image, dtype=np.double)
        g_col_by_ch = np.empty_like(image, dtype=np.double)
        g_magn = np.empty_like(image, dtype=np.double)

        for idx_ch in range(image.shape[2]):
            g_row_by_ch[:, :, idx_ch], g_col_by_ch[:, :, idx_ch] = \
                _hog_channel_gradient(image[:, :, idx_ch])
            g_magn[:, :, idx_ch] = np.hypot(g_row_by_ch[:, :, idx_ch],
                                            g_col_by_ch[:, :, idx_ch])

        # For each pixel select the channel with the highest gradient magnitude
        idcs_max = g_magn.argmax(axis=2)
        rr, cc = np.meshgrid(np.arange(image.shape[0]),
                             np.arange(image.shape[1]),
                             indexing='ij',
                             sparse=True)
        g_row = g_row_by_ch[rr, cc, idcs_max]
        g_col = g_col_by_ch[rr, cc, idcs_max]
    else:
        g_row, g_col = _hog_channel_gradient(image)
  • 從HOG的實(shí)現(xiàn)中我們可以看到椿猎,這里是先將圖片以float的形式讀入,防止出現(xiàn)uint(小) - uint(大) 越界出現(xiàn)正數(shù)的情況寿弱。
  • 接著是對(duì)于多信道的一個(gè)判斷犯眠,如果圖像是多信道的話,我們會(huì)分信道進(jìn)行梯度統(tǒng)計(jì)症革,如果是灰度圖片筐咧,會(huì)直接只進(jìn)行一次梯度統(tǒng)計(jì)處理。梯度統(tǒng)計(jì)的代碼如下:
def _hog_channel_gradient(channel):
    """Compute unnormalized gradient image along `row` and `col` axes.

    Parameters
    ----------
    channel : (M, N) ndarray
        Grayscale image or one of image channel.

    Returns
    -------
    g_row, g_col : channel gradient along `row` and `col` axes correspondingly.
    """
    g_row = np.empty(channel.shape, dtype=np.double)
    g_row[0, :] = 0
    g_row[-1, :] = 0
    g_row[1:-1, :] = channel[2:, :] - channel[:-2, :]
    g_col = np.empty(channel.shape, dtype=np.double)
    g_col[:, 0] = 0
    g_col[:, -1] = 0
    g_col[:, 1:-1] = channel[:, 2:] - channel[:, :-2]

    return g_row, g_col

  • 接著,我們要將這些像素點(diǎn)整合為一個(gè)個(gè)的cell量蕊,選取的方式有正方形取點(diǎn)R-HOG铺罢,圓形取點(diǎn)C-HOG,和中心切割型取點(diǎn)Single centre C-HOG残炮,而Dadel的論文指出:

We evaluated two variants of the C-HOG geometry, ones with a single circular central cell (similar to the GLOH feature), and ones whose cen-tralcellis divided into angular sectors as in shape contexts.We present results only for the circular-centrevariants, as these have fewer spatial cells than the divided centre ones and give the same per-formance in practice.

  • 由于中心切割型要消耗更多的4cell韭赘,但效果卻基本與圓形取點(diǎn)C-HOG相吻合,所以我們通常選用R-HOG和C-HOG二者之一势就。此處我們選擇R-HOG這一常用的HOG結(jié)構(gòu)泉瞻。

  • 下一步便是pixels per cell參數(shù)的選取,此處我們?nèi)绻x擇(4x4)作為參數(shù)苞冯,那么就代表由4x4個(gè)像素構(gòu)成一個(gè)cell袖牙,這時(shí)要對(duì)每一個(gè)cell當(dāng)中的各個(gè)像素進(jìn)行梯度向量的統(tǒng)計(jì),此處我們選擇使用直方圖來(lái)進(jìn)行統(tǒng)計(jì)舅锄,對(duì)應(yīng)的橫軸坐標(biāo)就是向量的角度贼陶。這里簡(jiǎn)單起見會(huì)考慮用若干個(gè)區(qū)間來(lái)覆蓋向量角度,Dadal論文當(dāng)中采用的是9份巧娱,skimage官方的demo中采用的是8份碉怔,這里我們不妨選取9份作為例子。

orientation選取為8舉例
  • 這樣一來(lái)從0°到180°(如果是0°到360°則需考慮方向的正負(fù))即可以分為20°的每份來(lái)作為梯度向量統(tǒng)計(jì)直方圖的橫軸禁添,對(duì)應(yīng)的縱軸方向則填充像素點(diǎn)對(duì)應(yīng)的梯度的幅度值撮胧。

  • 同理,我們選擇cell per block參數(shù)老翘,例如也選取(4x4)芹啥。那么對(duì)于每一個(gè)block,都由對(duì)應(yīng)數(shù)量的cell合成铺峭。此時(shí)我們得到的塊特征向量長(zhǎng)度應(yīng)該是4x4x9

C-HOG示意圖墓怀,ppc=cpb=(4, 4)

s_row, s_col = image.shape[:2]
    c_row, c_col = pixels_per_cell
    b_row, b_col = cells_per_block

    n_cells_row = int(s_row // c_row)  # number of cells along row-axis
    n_cells_col = int(s_col // c_col)  # number of cells along col-axis

    # compute orientations integral images
    orientation_histogram = np.zeros((n_cells_row, n_cells_col, orientations))

    _hoghistogram.hog_histograms(g_col, g_row, c_col, c_row, s_col, s_row,
                                 n_cells_col, n_cells_row,
                                 orientations, orientation_histogram)

    # now compute the histogram for each cell
    hog_image = None

    if visualize:
        from .. import draw

        radius = min(c_row, c_col) // 2 - 1
        orientations_arr = np.arange(orientations)
        # set dr_arr, dc_arr to correspond to midpoints of orientation bins
        orientation_bin_midpoints = (
            np.pi * (orientations_arr + .5) / orientations)
        dr_arr = radius * np.sin(orientation_bin_midpoints)
        dc_arr = radius * np.cos(orientation_bin_midpoints)
        hog_image = np.zeros((s_row, s_col), dtype=float)
        for r in range(n_cells_row):
            for c in range(n_cells_col):
                for o, dr, dc in zip(orientations_arr, dr_arr, dc_arr):
                    centre = tuple([r * c_row + c_row // 2,
                                    c * c_col + c_col // 2])
                    rr, cc = draw.line(int(centre[0] - dc),
                                       int(centre[1] + dr),
                                       int(centre[0] + dc),
                                       int(centre[1] - dr))
                    hog_image[rr, cc] += orientation_histogram[r, c, o]
  • 這里我們可以看到hog_histograms是一個(gè)bultins的函數(shù),我們無(wú)法看到它內(nèi)部的實(shí)現(xiàn)卫键,但我們猜測(cè)應(yīng)該是通過(guò)移動(dòng)掃描窗口來(lái)實(shí)現(xiàn)直方圖的cell統(tǒng)計(jì)傀履。為了保證效率,采取了c實(shí)現(xiàn)莉炉。
  • 這里還有一個(gè)visualize的實(shí)現(xiàn)钓账,是在之前詢問(wèn)我們是否返回一個(gè)hog的可視圖。如果選擇是是絮宁,這里就會(huì)根據(jù)之前統(tǒng)計(jì)值引入draw作圖梆暮。

歸一化

  • 使局部光照對(duì)比度歸一化,壓縮光照绍昂,明暗啦粹,邊緣對(duì)比度對(duì)圖片帶來(lái)的影響偿荷。這一步是基于block進(jìn)行的,也就是說(shuō)每一個(gè)cell唠椭,可能同時(shí)屬于不同的block跳纳,那么它就會(huì)在不同的block被分別均一化。
  • 設(shè)v為沒有歸一化的feature vector泪蔫,此處的均一化棒旗,我們通常有以下四種方式可選:
    • L_{1}-norm: v \leftarrow \frac{v}{|v|_{1}+\xi}
    • L_{1}-sqrt: v \leftarrow \sqrt{\frac{v}{\|v\|_{1}+\xi}}
    • L_{2}-norm: v \leftarrow \frac{v}{\sqrt{\|v\|_{12}^{2}+\xi^{2}}}:加一個(gè)極小的\xi以防止分母為0
    • L_{2}-H y s:在L_{2}的基礎(chǔ)上限制v的最大值為0.2,再歸一化撩荣。

  • 這里的塊均一化方法同時(shí)支持了我們上面所描述的四種方法铣揉。
def _hog_normalize_block(block, method, eps=1e-5):
    if method == 'L1':
        out = block / (np.sum(np.abs(block)) + eps)
    elif method == 'L1-sqrt':
        out = np.sqrt(block / (np.sum(np.abs(block)) + eps))
    elif method == 'L2':
        out = block / np.sqrt(np.sum(block ** 2) + eps ** 2)
    elif method == 'L2-Hys':
        out = block / np.sqrt(np.sum(block ** 2) + eps ** 2)
        out = np.minimum(out, 0.2)
        out = out / np.sqrt(np.sum(out ** 2) + eps ** 2)
    else:
        raise ValueError('Selected block normalization method is invalid.')

    return out
  • 再來(lái)看一下具體的實(shí)現(xiàn)過(guò)程,n_blocks_row 對(duì)應(yīng)的是block的行數(shù)餐曹,需要對(duì)應(yīng)的cell在行上平均分布開的數(shù)目減去對(duì)應(yīng)的cells_per_block的行數(shù)再加上1逛拱。列的計(jì)算依然。由此台猴,我們可以推斷出對(duì)應(yīng)的特征向量維數(shù)應(yīng)該是之前每一個(gè)block對(duì)應(yīng)的維數(shù)4x4x9再乘上對(duì)應(yīng)的block數(shù)目(8-4+1)x(8-4+1)朽合,最終等于3600維。選取了不同的參數(shù)也可以根據(jù)此判據(jù)來(lái)進(jìn)行計(jì)算饱狂。
    n_blocks_row = (n_cells_row - b_row) + 1
    n_blocks_col = (n_cells_col - b_col) + 1
    normalized_blocks = np.zeros((n_blocks_row, n_blocks_col,
                                  b_row, b_col, orientations))

    for r in range(n_blocks_row):
        for c in range(n_blocks_col):
            block = orientation_histogram[r:r + b_row, c:c + b_col, :]
            normalized_blocks[r, c, :] = \
                _hog_normalize_block(block, method=block_norm)

參考文章

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末曹步,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子休讳,更是在濱河造成了極大的恐慌讲婚,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俊柔,死亡現(xiàn)場(chǎng)離奇詭異筹麸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)雏婶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門物赶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人留晚,你說(shuō)我怎么就攤上這事酵紫。” “怎么了倔丈?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵憨闰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我需五,道長(zhǎng),這世上最難降的妖魔是什么轧坎? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任宏邮,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蜜氨。我一直安慰自己械筛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布飒炎。 她就那樣靜靜地躺著埋哟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪郎汪。 梳的紋絲不亂的頭發(fā)上赤赊,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音煞赢,去河邊找鬼抛计。 笑死,一個(gè)胖子當(dāng)著我的面吹牛照筑,可吹牛的內(nèi)容都是我干的吹截。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼凝危,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼波俄!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蛾默,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤懦铺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后趴生,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阀趴,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年苍匆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刘急。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浸踩,死狀恐怖叔汁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情检碗,我是刑警寧澤据块,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站折剃,受9級(jí)特大地震影響另假,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜怕犁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一边篮、第九天 我趴在偏房一處隱蔽的房頂上張望己莺。 院中可真熱鬧,春花似錦戈轿、人聲如沸凌受。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胜蛉。三九已至,卻和暖如春色乾,著一層夾襖步出監(jiān)牢的瞬間誊册,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工杈湾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留解虱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓漆撞,卻偏偏與公主長(zhǎng)得像殴泰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浮驳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容