HOG梯度直方图python实现
我一点点写,一点点更新
Histograms of Oriented Gradients for Human Detection - Navneet Dalal, Bill Triggs
Normalization
首先需要对这个图片像素进行归一化
img = cv.imread('elev2.jpeg')
img = np.float32(img) / 255.0 # 归一化
Guassian smoothing
高斯这里我掉了个opencv的包,sigma是0,因为是文章里说的。
import cv2 as cv
def gaussian():
img = cv.imread('elev2.jpeg')
# 高斯滤波
img = np.float32(img) / 255.0 # 归一化
img_Guassian = cv.GaussianBlur(img, (5, 5), 0)
return img_Guassian
Gradient Computation with mask[-1,0,1],sigma=0
这里我是自己实现的一维算子[-1,0,1]计算梯度,计算梯度通用的方法还有sobel,laplacian,canny算子。但他们的本质其实是一样的。都是对像素按照算子的系数进行计算。
分别求出x,y方向的梯度。
def conv1D(img, mask1D):
width = img.shape[1]
height = img.shape[0]
# ximg,yimg表示x,y方向梯度图
# 此处的变量赋值不能简单的等于,那样只会全部指向img
ximg = copy.deepcopy(img)
yimg = copy.deepcopy(img)
# 计算x,y方向梯度
for i in range(1, height - 2):
for j in range(1, width - 2):
left = img[i][j - 1]
right = img[i][j + 1]
uper = img[i + 1][j]
lower = img[i - 1][j]
# 如果用灰度图的话,此处int(right)应该加上,彩色图片不用加
ximg[i][j] = right - left
yimg[i][j] = lower - uper
return ximg, yimg
以下代码调用opencv的sobel函数,看别人的帖子说依然可以达到类似效果。我自己练练手写逻辑,就没调以下这个包。
# 求梯度也可以用以下sobel
gx = cv.Sobel(img_guassian, cv.CV_32F, 1, 0, ksize=1)
以下,把梯度结合,变成梯度向量。按文中的说法,我理解是把3色通道中最大范数值保留为最终该像素点的梯度。
def convertXYGradToVec(ximg, yimg):
# 这个是最大范数的颜色角标
maxIndex = 0
width = ximg.shape[1]
height = ximg.shape[0]
vecImg = np.zeros((height,width,2))
grayImg = np.zeros((height, width))
for i in range(1, height - 2):
for j in range(1, width - 2):
bnorm = np.linalg.norm([ximg[i][j][0], yimg[i][j][0]])
gnorm = np.linalg.norm([ximg[i][j][1], yimg[i][j][1]])
rnorm = np.linalg.norm([ximg[i][j][2], yimg[i][j][2]])
maxIndex = findMaxIn3(bnorm, gnorm, rnorm)
vecImg[i][j]=[ximg[i][j][maxIndex], yimg[i][j][maxIndex]]
return vecImg
# 求三通道那个最大?返回通道下标b,g,r
def findMaxIn3(a, b, c):
max = -255
index = 0
if a > max:
max = a
index = 0
if b > max:
max = b
index = 1
if c > max:
max = c
index = 2
return index