1.HOG
HOG(Histogram of Oriented Gradients)是一种用于图像处理和计算机视觉中的特征提取方法。它的基本思想是将图像分成小的连通区域,计算每个区域内梯度的方向直方图,然后将这些直方图串联起来形成一个特征向量,用于图像分类和目标检测等任务。HOG特征的提取过程包括以下步骤:
- 图像预处理:将图像转换为灰度图像,并进行归一化处理。
- 计算梯度:使用Sobel算子计算图像的水平和垂直梯度。
- 计算梯度方向和幅值:根据水平和垂直梯度计算每个像素点的梯度方向和幅值。
- 划分单元格:将图像分成小的连通区域,称为单元格。
- 统计梯度方向直方图:对于每个单元格,统计其内部像素点的梯度方向直方图。
- 归一化:对于每个块(由多个单元格组成),将其内部所有直方图进行归一化处理。
- 拼接特征向量:将所有块内的特征向量拼接起来,形成最终的特征向量。
代码
import cv2
import numpy as np
import math
import matplotlib.pyplot as plt
class Hog_descriptor():
#---------------------------#
# 初始化
# cell_size每个细胞单元的像素数
# bin_size表示把360分为多少边
#---------------------------#
def __init__(self, img, cell_size=16, bin_size=8):
self.img = img
self.img = np.sqrt(img / np.max(img))
self.img = img * 255
self.cell_size = cell_size
self.bin_size = bin_size
self.angle_unit = 360 / self.bin_size
#---------------------------#
# 获取hog向量和图片
#---------------------------#
def extract(self):
# 获得原图的shape
height, width = self.img.shape
# 计算原图的梯度大小
gradient_magnitude, gradient_angle = self.global_gradient()
gradient_magnitude = abs(gradient_magnitude)
# cell_gradient_vector用来保存每个细胞的梯度向量
cell_gradient_vector = np.zeros((int(height / self.cell_size), int(width / self.cell_size), self.bin_size))
height_cell,width_cell,_ = np.shape(cell_gradient_vector)
#---------------------------#
# 计算每个细胞的梯度直方图
#---------------------------#
for i in range(height_cell):
for j in range(width_cell):
# 获取这个细胞内的梯度大小
cell_magnitude = gradient_magnitude[i * self.cell_size:(i + 1) * self.cell_size,
j * self.cell_size:(j + 1) * self.cell_size]
# 获得这个细胞内的角度大小
cell_angle = gradient_angle[i * self.cell_size:(i + 1) * self.cell_size,
j * self.cell_size:(j + 1) * self.cell_size]
# 转化为梯度直方图格式
cell_gradient_vector[i][j] = self.cell_gradient(cell_magnitude, cell_angle)
# hog图像
hog_image = self.render_gradient(np.zeros([height, width]), cell_gradient_vector)
hog_vector = []
# block为2x2
for i in range(height_cell - 1):
for j in range(width_cell - 1):
block_vector = []
block_vector.extend(cell_gradient_vector[i][j])
block_vector.extend(cell_gradient_vector[i][j + 1])
block_vector.extend(cell_gradient_vector[i + 1][j])
block_vector.extend(cell_gradient_vector[i + 1][j + 1])
mag = lambda vector: math.sqrt(sum(i ** 2 for i in vector))
magnitude = mag(block_vector)
if magnitude != 0:
normalize = lambda block_vector, magnitude: [element / magnitude for element in block_vector]
block_vector = normalize(block_vector, magnitude)
hog_vector.append(block_vector)
return hog_vector, hog_image
#---------------------------#
# 计算原图的梯度大小
# 角度大小
#---------------------------#
def global_gradient(self):
gradient_values_x = cv2.Sobel(self.img, cv2.CV_64F, 1, 0, ksize=5)
gradient_values_y = cv2.Sobel(self.img, cv2.CV_64F, 0, 1, ksize=5)
gradient_magnitude = cv2.addWeighted(gradient_values_x, 0.5, gradient_values_y, 0.5, 0)
gradient_angle = cv2.phase(gradient_values_x, gradient_values_y, angleInDegrees=True)
return gradient_magnitude, gradient_angle
#---------------------------#
# 分解角度信息到
# 不同角度的直方图上
#---------------------------#
def cell_gradient(self, cell_magnitude, cell_angle):
orientation_centers = [0] * self.bin_size
for i in range(cell_magnitude.shape[0]):
for j in range(cell_magnitude.shape[1]):
gradient_strength = cell_magnitude[i][j]
gradient_angle = cell_angle[i][j]
min_angle, max_angle, mod = self.get_closest_bins(gradient_angle)
orientation_centers[min_angle] += (gradient_strength * (1 - (mod / self.angle_unit)))
orientation_centers[max_angle] += (gradient_strength * (mod / self.angle_unit))
return orientation_centers
#---------------------------#
# 计算每个像素点所属的角度
#---------------------------#
def get_closest_bins(self, gradient_angle):
idx = int(gradient_angle / self.angle_unit)
mod = gradient_angle % self.angle_unit
return idx, (idx + 1) % self.bin_size, mod
#---------------------------#
# 将梯度直方图进行绘图
#---------------------------#
def render_gradient(self, image, cell_gradient):
cell_width = self.cell_size / 2
max_mag = np.array(cell_gradient).max()
for x in range(cell_gradient.shape[0]):
for y in range(cell_gradient.shape[1]):
cell_grad = cell_gradient[x][y]
cell_grad /= max_mag
angle = 0
angle_gap = self.angle_unit
for magnitude in cell_grad:
angle_radian = math.radians(angle)
x1 = int(x * self.cell_size + magnitude * cell_width * math.cos(angle_radian))
y1 = int(y * self.cell_size + magnitude * cell_width * math.sin(angle_radian))
x2 = int(x * self.cell_size - magnitude * cell_width * math.cos(angle_radian))
y2 = int(y * self.cell_size - magnitude * cell_width * math.sin(angle_radian))
cv2.line(image, (y1, x1), (y2, x2), int(255 * math.sqrt(magnitude)))
angle += angle_gap
return image
img = cv2.imread(R'D:\papercode\experiment\2\deep-learning-for-image-processing-master\deep-learning-for-image-processing-master\amusement_0037.jpg', cv2.IMREAD_GRAYSCALE)
hog = Hog_descriptor(img, cell_size=20, bin_size=12)
vector, image = hog.extract()
plt.imshow(image, cmap=plt.cm.gray)
plt.show()
2.MHOG
多尺度HOG特征是指在不同尺度下提取图像的HOG特征,以便于检测不同大小的目标物体。具体步骤如下:
- 对图像进行金字塔缩放,得到不同尺度的图像。
- 对每个尺度的图像进行颜色空间归一化,梯度计算和梯度方向直方图计算。
- 将每个尺度的梯度方向直方图进行插值,得到更加精细的梯度方向直方图。
- 将每个尺度的梯度方向直方图进行重叠块直方图归一化,得到HOG特征。
代码
import cv2
import numpy as np
# 读取图像
img = cv2.imread('test.jpg')
# 构建图像金字塔
pyramid = []
for i in range(3):
scale = 1 / (2 ** i)
img_scale = cv2.resize(img, None, fx=scale, fy=scale, interpolation=cv2.INTER_LINEAR)
pyramid.append(img_scale)
# 提取HOG特征
winSize = (64, 128)
blockSize = (16, 16)
blockStride = (8, 8)
cellSize = (8, 8)
nbins = 9
hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins)
features = []
for img_scale in pyramid:
hog_feature = hog.compute(img_scale)
features.append(hog_feature)
# 将不同尺度的HOG特征拼接在一起
feature = np.concatenate(features, axis=0)
3. HOG-LBP
HOG(Histogram of Oriented Gradient)特征是一种用于图像处理的特征提取方法,它可以有效地描述图像的边缘和纹理信息。LBP(Local Binary Pattern)特征是一种用于图像处理的局部纹理特征描述子,它可以有效地描述图像的纹理信息。HOG-LBP特征是将HOG和LBP特征进行融合,以得到更有效的图像特征。在人体头肩检测中,HOG-LBP特征融合可以提取出更有效的人体头肩的边缘轮廓和纹理特征,从而提高检测的准确率。
代码
import cv2
# 读取图像
img = cv2.imread('test.jpg')
# 提取HOG特征
hog = cv2.HOGDescriptor()
hog_feature = hog.compute(img)
# 提取LBP特征
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
lbp = cv2.LBP()
lbp_feature = lbp.compute(gray)
# 将HOG和LBP特征进行融合
feature = cv2.hconcat([hog_feature, lbp_feature])
# 输出融合后的特征
print(feature)
4.HOG-SIFT
SIFT算法的特征点稳定性很好,而HOG算法则可以提取出图像的纹理特征。因此,将两种算法的特征结合起来可以得到更加丰富的特征描述子,提高图像识别的准确率。
代码
import cv2
import numpy as np
# 读取图像
img = cv2.imread('image.jpg')
# 初始化SIFT特征提取器
sift = cv2.xfeatures2d.SIFT_create()
# 提取SIFT特征点和描述子
kp, des = sift.detectAndCompute(img, None)
# 初始化HOG特征提取器
hog = cv2.HOGDescriptor()
# 计算HOG特征
hist = hog.compute(img)
# 将SIFT和HOG特征描述子拼接在一起
features = np.concatenate((des, hist), axis=1)
# 输出特征向量的维度
print(features.shape)
5.HOG-PCA
HOG-PCA特征是一种常用的图像特征提取方法,主要用于目标检测和识别。其主要步骤如下:
1.方向梯度直方图(HOG)特征提取:将图像分成小的单元格,计算每个单元格内像素的梯度方向和大小,然后将其投影到一个直方图中,得到每个单元格的特征向量。
2.特征白化:对特征向量进行白化处理,即将其转换为零均值和单位方差。
3.尺度统一:对特征向量进行随机下采样,使其具有相同的尺度。
4.主成分分析(PCA)特征映射:将特征向量映射到一个低维空间中,以减少特征向量的维度。
5.最近邻分类:使用最小二阶范数判定进行最近邻分类,即将待分类的特征向量与训练集中的特征向量进行比较,找到最相似的特征向量,并将其分类标签作为待分类样本的标签。
代码
import cv2
import numpy as np
# 读取图像
img = cv2.imread('test.jpg')
# HOG特征提取
winSize = (64, 128)
blockSize = (16, 16)
blockStride = (8, 8)
cellSize = (8, 8)
nbins = 9
hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins)
features = hog.compute(img)
# 特征白化
mean, std = cv2.meanStdDev(features)
features -= mean
features /= std
# 尺度统一
features = cv2.resize(features, (64, 128))
# PCA特征映射
pca = cv2.PCA(features, cv2.PCA_DATA_AS_ROW)
features = pca.project(features)
# 最近邻分类
trainData = np.load('trainData.npy')
labels = np.load('labels.npy')
knn = cv2.ml.KNearest_create()
knn.train(trainData, cv2.ml.ROW_SAMPLE, labels)
ret, result, neighbours, dist = knn.findNearest(features, 1)
# 输出分类结果
print('分类结果:', result[0][0])
参考: