梯度直方图(HOG)用于图像多分类和图像推荐( 二 )
现在让我们考虑下面的图像 ,
文章插图
让我们假设红色的方框用8x8矩阵表示 , 每个单元格中都有数字 。 在进行图像特征工程之前 , 建议做以下几件事:
1. Resize:将所有图像调整为统一形状 , 以避免任何与计算相关的隐患 。 在本例中 , 所有图像的形状统一(60x80) 。 如果您想执行调整大小操作 , 请参阅以下内容:
def resize_image(img,ids):return cv.resize(img, (60, 80),interpolation =cv.INTER_LINEAR)all_images_resized = [[resize_image(x,y),y] for x,y in all_images]len(all_images_resized)
1. Normalize :以避免亮度、对比度或其他照明效果造成的影响 。
1. Filtering:考虑几个相邻像素 , 而不是单一像素值作为像素的真实值 。 高斯滤波对中心像素权重最大 , 对相邻像素权重按w、r、t递减 , 即根据窗口大小确定与中心像素的距离 。
【梯度直方图(HOG)用于图像多分类和图像推荐】最后对滤波后的图像进行如下计算:
文章插图
将整个图像分成若干块(b) 。 一个典型的块是上面提到的红框 。 此外 , 其他块可以看作是黑盒中提到的单元格(c)的集合 。 上图中 , b的尺寸是8x8, c的尺寸是4x4
接下来 , 对于每个单元格 , 计算单元格中每个点的梯度大小和方向(为了简单起见 , 梯度大小可以简单地假设为Sobel导数或任意两个连续的x和y像素值之间的差) 。 然后形成大小为n的直方图 , 将梯度量级值从w.r.t梯度方向进行处理 。 最后根据规则对直方图进行归一化 , 形成一个n维向量 。
对于一个单元格 , 我们得到一个n维向量 。 接下来的操作是通过向右移动50%重叠的图像块和向下移50%重叠的图像块来覆盖整个图像 。
最后 , 将所有这些直方图串联起来 , 形成一个一维向量 , 称为HOG特征描述符 。
HOG可以通过下面的代码段进行实现 。
##HOG Descriptor#Returns a 1D vector for an imageppcr = 8ppcc = 8hog_images = []hog_features = []for image in tqdm(train_images): blur = cv.GaussianBlur(image,(5,5),0) #Gaussian Filtering fd,hog_image = hog(blur, orientations=8, pixels_per_cell=(ppcr,ppcc),cells_per_block=(2,2),block_norm= ‘L2’,visualize=True) hog_images.append(hog_image) hog_features.append(fd)hog_features = np.array(hog_features)hog_features.shape
参数
对这个问题:-块大小为16x16
-单元格大小为8x8
这使得pixelpercell = (8x8)并且cellsperblock = (2x2)
-orientations(=8)是每个单元格的直方图容器的数量 。 在这8个容器中将放置16个梯度值 , 并将它们添加到每个容器中以表示该方向容器的梯度大小 。 当两个连续箱子之间的梯度分配发生冲突时 , 通常通过梯度插值来对梯度值进行投票 。
-block_norm ="L1" 。 其他参数有L1归一化或L2-Hys(Hysteresis) 。 L2-Hys在某些情况下可以减少噪音 。 它使用l2 -范数来完成 , 然后将最大值限制为0.2 , 并使用l2 -范数来重新归一化 。
#normalization by '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)
当实际图像形状为60x80 , 块大小为16x16时 , 总共将创建6x9 = 54个块(考虑到x,y中任意一步50%的重叠) , 而在每个块中我们将有4个单元格 , 每个单元格有8个直方图 。 因此 , 特征向量的长度为54x4x8 = 1728