网站首页 > 技术文章 正文
?? HOG特征是对象识别与模式匹配中是一种常见的特征提取算法, 本文主要介绍了HOG特征以及利用其描述子加SVM方法实现检测功能,具体的内容可以参考下文~
目录
- 概述
- HOG特征描述子提取
- HOG+SVM 检测示例
- 小结
概述
?? HOG(Histogram of Oriented Gradient)特征在对象识别与模式匹配中是一种常见的特征提取算法,是基于本地像素块进行特征直方图提取的一种算法,对象局部的变形与光照影响有很好的稳定性。
HOG应用-行人检测
?? 用HOG特征来来识别人像,通过HOG特征提取+SVM训练,可以得到很好的效果,Opencv也集成了HOG进行的行人检测算法。
OpenCV函数
- hog = cv2.HOGDescriptor() :创建HOG特征描述;
- hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector()) :创建HOG+SVM行人检测器;
- 多尺度检测API:
rects, weights = hog.detectMultiScale(img, foundLocations,
hitThreshold = 0,
winStride, padding,
scale = 1.05,
finalThreshold = 2.0,
useMeanshiftGrouping = false)
输入
- Img --> 表示输入图像;
- foundLocations --> 表示发现对象矩形框;
- hitThreshold --> 表示SVM距离度量(特征与SVM分类超平面之间距离),默认0表示;
- winStride --> 表示窗口步长;
- padding --> 表示填充;
- scale --> 表示尺度空间;
- finalThreshold --> 最终阈值,默认为2.0;
- useMeanshiftGrouping --> 不建议使用,速度太慢;
PS:其中窗口步长与Scale对结果影响最大,特别是Scale,小的尺度变化有利于检出低分辨率对象,同时也会导致FP发生,高的可以避免FP但是会产生FN(对象漏检)。
行人检测代码示例
import cv2 as cv
src = cv.imread("people.png")
cv.imshow("input", src)
# hog特征描述
hog = cv.HOGDescriptor()
# 创建SVM检测器
hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector())
# 检测行人
(rects, weights) = hog.detectMultiScale(src,
winStride=(4, 4),
padding=(8, 8),
scale=1.25,
useMeanshiftGrouping=False)
for (x, y, w, h) in rects:
cv.rectangle(src, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv.imshow("hog-people", src)
cv.waitKey(0)
cv.destroyAllWindows()
HOG特征描述子提取
提取过程
1. Gamma矫正
?? 为了提高检测器对关照等干扰因素的鲁棒性,需要对图像进行Gamma矫正,完成对整个图像的归一化,调整对比度,降低噪声影响;
一般 r=1/2
2. 灰度化
3. 计算图像XY梯度和方向
使用sobel可以出水平和垂直方向的梯度:
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)
利用公式求取梯度幅值和方向:
Opencv中使用:
mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)
4. 8x8网格方向梯度权重直方图统计
?? 流程:首先将图像划分成若干个块(Block),每个块又由若干个细胞单元(cell)组成,细胞单元由更小的单位像素(Pixel)组成,然后在每个细胞单元中对内部的所有像素的梯度方向进行统计。
- 默认HOG的描述子窗口为64x128, 窗口移动步长为 8x8
- 每个窗口的cell为8x8,每个block由4个cell组成,block移动步长为一个cell,因此可以得到7x15个block
- 直方图把180度分为9个bin,每个区间为20度,如果像素落在某个区间,就把该像素的直方图累计到对应区间的直方图上
- 每个block有4个cell,每个cell有9个向量值,即每个block有36个向量,所以整个窗口有7x15x36=3780个特征描述子。
5. 块描述子和特征向量归一化
?? 每个block可以得到4个9维的向量,需要再次进行一次归一化,这样可以进一步提高泛化能力,同传使用L2-nrom进行归一化(还有L1-norm, L1-sqrt,etc.)
整体流程图
HOG+SVM 检测示例
?? 这里,我们使用前面所了解到HOG知识,结合SVM,进行一个简单的水表检测案例。
- 使用描述子特征生成样本数据
- 通过SVM进行分类学习与训练
- load模型,进行预测结果
- 数据生成
# 把目标图放在64x128的灰色图片中间,方便计算描述子
def get_hog_descriptor(image):
hog = cv.HOGDescriptor()
h, w = image.shape[:2]
rate = 64 / w
image = cv.resize(image, (64, np.int(rate*h)))
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
bg = np.zeros((128, 64), dtype=np.uint8)
bg[:,:] = 127
h, w = gray.shape
dy = (128 - h) // 2
bg[dy:h+dy,:] = gray
descriptors = hog.compute(bg, winStride=(8, 8), padding=(0, 0))
return descriptors
def get_data(train_data, labels, path, lableType):
for file_name in os.listdir(path):
img_dir = os.path.join(path, file_name)
img = cv.imread(img_dir)
hog_desc = get_hog_descriptor(img)
one_fv = np.zeros([len(hog_desc)], dtype=np.float32)
for i in range(len(hog_desc)):
one_fv[i] = hog_desc[i][0]
train_data.append(one_fv)
labels.append(lableType)
return train_data, labels
def get_dataset(pdir, ndir):
train_data = []
labels = []
# 获取正样本
train_data, labels = get_data(train_data, labels, pdir, lableType=1)
# 获取负样本
train_data, labels = get_data(train_data, labels, ndir, lableType=-1)
return np.array(train_data, dtype=np.float32), np.array(labels, dtype=np.int32)
if __name__ == '__main__':
# train_data的shape为(n, 3780), labels(n,)
# n为样本数
train_data, labels = get_dataset("pdir/", "ndir/")
- 构建SVM训练器
?? Opencv中SVM有线性分类器和非线性的径向分类器。
这里使用线性分类器:
svm.train(trainData, cv.ml.ROW_SAMPLE, responses)
- Sample --> 表示训练样本数据/HOG特征数据
- Layout --> 有两种组织方式ROW_SAMPLE与COL_SAMPLE
- Responses --> 每个输入样本的标签
训练代码
def svm_train(pdir, ndir):
# 创建SVM
svm = cv.ml.SVM_create()
# 设置相应的SVM参数
svm.setKernel(cv.ml.SVM_LINEAR)
svm.setType(cv.ml.SVM_C_SVC)
svm.setC(2.67)
svm.setGamma(5.383)
# 获取正负样本和labels
trainData, responses = get_dataset(pdir, ndir)
# reshape (n,)-->(n,1)
responses = np.reshape(responses, [-1, 1])
# 训练
svm.train(trainData, cv.ml.ROW_SAMPLE, responses)
svm.save('svm_data.dat')
- 预测目标
import cv2 as cv
import numpy as np
image = cv.imread("test_01.jpg")
# 原图太大,降低原图分辨率
test_img = cv.resize(image, (0, 0), fx=0.2, fy=0.2)
# 灰度
gray = cv.cvtColor(test_img, cv.COLOR_BGR2GRAY)
# 获取大小
h, w = test_img.shape[:2]
# 加载训练好的模型
svm = cv.ml.SVM_load('../code_104/svm_data.dat')
# 为了筛选框,记录框坐标总和以及框的个数,为了最后求出所有候选框的均值框
sum_x = 0
sum_y = 0
count = 0
# 创建hog特征描述子函数
hog = cv.HOGDescriptor()
# 为了加快计算,窗口滑动的步长为4,一个cell是8个像素
for row in range(64, h-64, 4):
for col in range(32, w-32, 4):
win_roi = gray[row-64:row+64,col-32:col+32]
hog_desc = hog.compute(win_roi, winStride=(8, 8), padding=(0, 0))
one_fv = np.zeros([len(hog_desc)], dtype=np.float32)
for i in range(len(hog_desc)):
one_fv[i] = hog_desc[i][0]
one_fv = one_fv.reshape(-1, len(hog_desc))
# 预测
result = svm.predict(one_fv)[1]
# 统计正样本
if result[0][0] > 0:
sum_x += (col-32)
sum_y += (row-64)
count += 1
# 画出所有框
cv.rectangle(test_img, (col-32, row-64), (col+32, row+64), (0, 233, 255), 1, 8, 0)
# 求取均值框
x = sum_x // count
y = sum_y // count
# 画出均值框
cv.rectangle(test_img, (x, y), (x+64, y+128), (0, 0, 255), 2, 8, 0)
如上图,类似于目标检测中NMS的作用,这里使用均值的方法获得最终的框。
小结
?? 对于简单的识别,HOG和SVM的识别效果还是很不错的,为了提高效果,可以增加正负样本进行,再次进行训练。
?? SVM不需要GPU,所以在针对一些简单的识别任务,可以采用这个方法,但是复杂问题,还是建议使用神经网络,效果会更好!
未完待续~
更多Opencv教程将持续发布!
欢迎关注哟~??????
- 上一篇: 传统特征:HOG特征原理 hog特征缺点
- 下一篇: 深入浅出理解HOG特征——梯度方向直方图
猜你喜欢
- 2024-10-12 热红外成像算法都有哪些 红外热成像dep
- 2024-10-12 「图像描述子」 SIFT特征的提取过程
- 2024-10-12 运用HOG通过Java实现面部识别比较
- 2024-10-12 「洞幺邦」COSD数据集图像分类与物体分割
- 2024-10-12 用改进的深度差分特征识别人体部位
- 2024-10-12 人脸识别技术的基本原理和主流技术介绍
- 2024-10-12 图像学习之如何理解方向梯度直方图(Histogram Of Gradient)
- 2024-10-12 密恐警告:超2000万张,全球最大的人眼图像数据集开源了
- 2024-10-12 基于HOG-LBP特征融合的头肩检测研究
- 2024-10-12 图像识别(四):图像特征选择与提取
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)