[pythonと画像処理]Pythonは画像HOGの特徴を抽出する

23167 ワード

Python、numpyライブラリを用いて画像HOGの特徴の抽出を実現し、主にHOGの特徴を分析する具体的なアルゴリズムフローに用いられる.参照リンク:https://blog.csdn.net/qq_37141382/article/details/89342081参考資料:HOGの経典論文:Dalal N,Triggs B.Histograms of oriented gradients for human detection[C]//Computer Vision and Pattern Recognition,2005.CVPR 2005. IEEE Computer Society Conference on. IEEE, 2005, 1: 886-893.(2016:Google Citation: 14046)
HOG特徴抽出アルゴリズムの全実現過程は大体以下の通りである:1、必要な画像を読み込む;2、RGB画像を階調画像に変換する(入力されたカラーの画像のr,g,b値を特定の数式で階調値に変換する).3、入力画像をGamma補正法で色空間の標準化(正規化)する.4、画像の各画素の勾配(大小と方向を含む)を計算し、輪郭情報を取得する.5、各cellを統計する(88例)勾配ヒストグラム(異なる勾配方向の振幅値)、各cellのfeature descriptorを形成する;6、4つのcellを1つのblockに構成する(22を例として)、1つのブロック内の4つのcellの特徴を直列に接続してそのブロックのHOG特徴descriptorを得る;7、画像内のすべてのブロックのHOG特徴descriptorを直列に接続してその画像のHOG特徴descriptorを得る、これが最終分類の特徴ベクトルである.
Pythonコードは、必要に応じてcellのサイズを変更し、blockのサイズを変更します.
#coding:utf-8
#*********************************************************************************************************
'''
  :  python/numpy/opencv    HOG     
    :
    :
        1)           ,resize (128,64);
        2)    gamma  ;
		3)        Sobel  ,         X   Y        /    ,       
            (X         Y        ),                    gradient_magnitude、
              gradient_angle
		4)  (cell_x = 128/8 =16, cell_y= 64/8 =8)   cell  ----     grad_cell  ,     ang_cell  ,
          cell   8*8 = 64  ;
		5)   cell     (0-180)  9 bin,     cell         ,  cell 9  ;
		6) (2*2) cell   block,  15*7 block,    block        ,        ,  block  9*4=36  ;
		7)              HOG:         Block HOG                           
           :15*7*36 = 3780,
                              ,       SVM  。
'''
import cv2
import numpy as np
import matplotlib.pyplot as plt

#    gamma  
def gamma(img):
    #      gamma  
    # img1 = img.copy()
    # img2 = img.copy()
    # img1 = np.power( img1 / 255.0, 0.5 )
    # img2 = np.power( img2 / 255.0, 2.2 )
    return np.power( img / 255.0, 1 )    

#     cell  ,    cell  
def div( img, cell_x, cell_y, cell_w ):
    cell = np.zeros( shape = ( cell_x, cell_y, cell_w, cell_w ) )
    img_x = np.split( img, cell_x, axis = 0 )
    for i in range( cell_x ):
        img_y = np.split( img_x[i], cell_y, axis = 1 )
        for j in range( cell_y ):
            cell[i][j] = img_y [j]
    return cell

#           ,      9  
def get_bins( grad_cell, ang_cell ):
    bins = np.zeros( shape = ( grad_cell.shape[0], grad_cell.shape[1], 9 ) )
    for i in range( grad_cell.shape[0] ):
        for j in range( grad_cell.shape[1] ):
            binn = np.zeros(9)
            grad_list = np.int8( grad_cell[i,j].flatten() )#  cell  64      ,     
            ang_list = ang_cell[i,j].flatten()#  cell  64       )
            ang_list = np.int8( ang_list / 20.0 )#0-9
            ang_list[ ang_list >=9 ] = 0
            for m in range(len(ang_list)):
                binn[ang_list[m]] += int( grad_list[m] )#            ,       
          #  cell           
            # N = 9
            # x = np.arange( N )
            # str1 = ( '0-20', '20-40', '40-60', '60-80', '80-100', '100-120', '120-140', '140-160', '160-180' )
            # plt.bar( x, height = binn, width = 0.8, label = 'cell histogram', tick_label = str1 )
            # for a, b in zip(x, binn):
                # plt.text( a, b+0.05, '{}'.format(b), ha = 'center', va = 'bottom', fontsize = 10 )
            # plt.show()
            bins[i][j] = binn
    return bins

#    HOG    ,    15*7*36 = 3780   
def hog( img, cell_x, cell_y, cell_w ):
    height, width = img.shape
    gradient_values_x = cv2.Sobel( img, cv2.CV_64F, 1, 0, ksize = 5 )#x    
    gradient_values_y = cv2.Sobel( img, cv2.CV_64F, 0, 1, ksize = 5 )#y    
    gradient_magnitude = np.sqrt( np.power( gradient_values_x, 2 ) + np.power( gradient_values_y, 2 ) )
    gradient_angle = np.arctan2( gradient_values_x, gradient_values_y )
    print( gradient_magnitude.shape, gradient_angle.shape )
    # plt.figure()
    # plt.subplot( 1, 2, 1 )
    # plt.imshow(gradient_angle)
    #     (0-180)
    gradient_angle[ gradient_angle > 0 ] *= 180 / 3.14
    gradient_angle[ gradient_angle < 0 ] = ( gradient_angle[ gradient_angle < 0 ] + 3.14 ) *180 / 3.14
    # plt.subplot( 1, 2, 2 )
    # plt.imshow( gradient_angle )
    # plt.show()

    grad_cell = div( gradient_magnitude, cell_x, cell_y, cell_w )
    ang_cell = div( gradient_angle, cell_x, cell_y, cell_w )
    bins = get_bins ( grad_cell, ang_cell )
    feature = []
    for i in range( cell_x - 1 ):
        for j in range( cell_y - 1 ):
            tmp = []
            tmp.append( bins[i,j] )
            tmp.append( bins[i+1,j] )
            tmp.append( bins[i,j+1] )
            tmp.append( bins[i+1,j+1] )
            tmp -= np.mean( tmp )
            feature.append( tmp.flatten() )
    return np.array( feature ).flatten()
                
if __name__ == '__main__':
    img = cv2.imread( './data/basketball1.png', cv2.IMREAD_GRAYSCALE )
    if( img is None ):
        print( 'Not read image.' )
    print( img.shape )
    resizeimg = cv2.resize( img, ( 128, 64 ), interpolation = cv2.INTER_CUBIC )
    cell_w = 8
    cell_x = int( resizeimg.shape[0] / cell_w )#cell  
    cell_y = int( resizeimg.shape[1] / cell_w )#cell  
    print( 'The size of cellmap is {}*{} '.format( cell_x, cell_y ) )
    gammaimg = gamma( resizeimg )*255    
    feature = hog( gammaimg, cell_x, cell_y, cell_w )
    print( feature.shape )