图像特征提取之Hog特征提取

HOG全称(histogram of oriented gradients),方向梯度直方图,可以用来提取表示图像的特征,本质就是一行高维特征。

HOG特征提取步骤

  • 图像预处理(gamma校正和灰度化)【option】

  • 计算每一个像素点的梯度值,得到梯度图(尺寸与原图一致)

sobel计算水平和竖直梯度,并通过公式求得梯度的方向(边缘方向与梯度方向垂直)

梯度方向取绝对值,梯度方向取值范围为[0,180]
  • 统计每个cell的梯度直方图(不同梯度的个数),形成每个cell的descriptor

  • 将每几个cell组成一个block(3*3),一个block内所有cell的特征串联起来得到该block的HOG特征descripitor

  • 将图像image内所有block的HOG特征descripitor串联起来得到该image的HOG特征descripitor,即最终分类的特征向量

HOG特征提取python实现


import cv2
import numpy as np
import math
import matplotlib.pyplot as pltclass Hog_descriptor():def __init__(self, img, cell_size=16, bin_size=8):self.img = imgself.img = np.sqrt(img / float(np.max(img)))self.img = self.img * 255self.cell_size = cell_sizeself.bin_size = bin_sizeself.angle_unit = 360 / self.bin_sizeassert type(self.bin_size) == int, "bin_size should be integer,"assert type(self.cell_size) == int, "cell_size should be integer,"assert type(self.angle_unit) == int, "bin_size should be divisible by 360"def extract(self):height, width = self.img.shapegradient_magnitude, gradient_angle = self.global_gradient()gradient_magnitude = abs(gradient_magnitude)cell_gradient_vector = np.zeros((height / self.cell_size, width / self.cell_size, self.bin_size))for i in range(cell_gradient_vector.shape[0]):for j in range(cell_gradient_vector.shape[1]):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_image = self.render_gradient(np.zeros([height, width]), cell_gradient_vector)hog_vector = []for i in range(cell_gradient_vector.shape[0] - 1):for j in range(cell_gradient_vector.shape[1] - 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_imagedef 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_angledef cell_gradient(self, cell_magnitude, cell_angle):orientation_centers = [0] * self.bin_sizefor 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_centersdef get_closest_bins(self, gradient_angle):idx = int(gradient_angle / self.angle_unit)mod = gradient_angle % self.angle_unitif idx == self.bin_size:return idx - 1, (idx) % self.bin_size, modreturn idx, (idx + 1) % self.bin_size, moddef render_gradient(self, image, cell_gradient):cell_width = self.cell_size / 2max_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_magangle = 0angle_gap = self.angle_unitfor 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_gapreturn imageimg = cv2.imread('data/picture1.png', cv2.IMREAD_GRAYSCALE)
hog = Hog_descriptor(img, cell_size=8, bin_size=8)
vector, image = hog.extract()
plt.imshow(image, cmap=plt.cm.gray)
plt.show()

HOG+SVM实现行人检测

数据集地址: ftp://ftp.inrialpes.fr/pub/lear/douze/data/INRIAPerson.ta


import cv2
import numpy as np
import randomdef load_images(dirname, amout = 9999):img_list = []file = open(dirname)img_name = file.readline()while img_name != '':  # 文件尾img_name = dirname.rsplit(r'/', 1)[0] + r'/' + img_name.split('/', 1)[1].strip('\n')img_list.append(cv2.imread(img_name))img_name = file.readline()amout -= 1if amout <= 0: # 控制读取图片的数量breakreturn img_list# 从每一张没有人的原始图片中随机裁出10张64*128的图片作为负样本
def sample_neg(full_neg_lst, neg_list, size):random.seed(1)width, height = size[1], size[0]for i in range(len(full_neg_lst)):for j in range(10):y = int(random.random() * (len(full_neg_lst[i]) - height))x = int(random.random() * (len(full_neg_lst[i][0]) - width))neg_list.append(full_neg_lst[i][y:y + height, x:x + width])return neg_list# wsize: 处理图片大小,通常64*128; 输入图片尺寸>= wsize
def computeHOGs(img_lst, gradient_lst, wsize=(128, 64)):hog = cv2.HOGDescriptor()# hog.winSize = wsizefor i in range(len(img_lst)):if img_lst[i].shape[1] >= wsize[1] and img_lst[i].shape[0] >= wsize[0]:roi = img_lst[i][(img_lst[i].shape[0] - wsize[0]) // 2: (img_lst[i].shape[0] - wsize[0]) // 2 + wsize[0], \(img_lst[i].shape[1] - wsize[1]) // 2: (img_lst[i].shape[1] - wsize[1]) // 2 + wsize[1]]gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)gradient_lst.append(hog.compute(gray))# return gradient_lstdef get_svm_detector(svm):sv = svm.getSupportVectors()rho, _, _ = svm.getDecisionFunction(0)sv = np.transpose(sv)return np.append(sv, [[-rho]], 0)# 主程序
# 第一步:计算HOG特征
neg_list = []
pos_list = []
gradient_lst = []
labels = []
hard_neg_list = []
svm = cv2.ml.SVM_create()
pos_list = load_images(r'G:/python_project/INRIAPerson/96X160H96/Train/pos.lst')
full_neg_lst = load_images(r'G:/python_project/INRIAPerson/train_64x128_H96/neg.lst')
sample_neg(full_neg_lst, neg_list, [128, 64])
print(len(neg_list))
computeHOGs(pos_list, gradient_lst)
[labels.append(+1) for _ in range(len(pos_list))]
computeHOGs(neg_list, gradient_lst)
[labels.append(-1) for _ in range(len(neg_list))]# 第二步:训练SVM
svm.setCoef0(0)
svm.setCoef0(0.0)
svm.setDegree(3)
criteria = (cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS, 1000, 1e-3)
svm.setTermCriteria(criteria)
svm.setGamma(0)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setNu(0.5)
svm.setP(0.1)  # for EPSILON_SVR, epsilon in loss function?
svm.setC(0.01)  # From paper, soft classifier
svm.setType(cv2.ml.SVM_EPS_SVR)  # C_SVC # EPSILON_SVR # may be also NU_SVR # do regression task
svm.train(np.array(gradient_lst), cv2.ml.ROW_SAMPLE, np.array(labels))# 第三步:加入识别错误的样本,进行第二轮训练
# 参考 http://masikkk.com/article/SVM-HOG-HardExample/
hog = cv2.HOGDescriptor()
hard_neg_list.clear()
hog.setSVMDetector(get_svm_detector(svm))
for i in range(len(full_neg_lst)):rects, wei = hog.detectMultiScale(full_neg_lst[i], winStride=(4, 4),padding=(8, 8), scale=1.05)for (x,y,w,h) in rects:hardExample = full_neg_lst[i][y:y+h, x:x+w]hard_neg_list.append(cv2.resize(hardExample,(64,128)))
computeHOGs(hard_neg_list, gradient_lst)
[labels.append(-1) for _ in range(len(hard_neg_list))]
svm.train(np.array(gradient_lst), cv2.ml.ROW_SAMPLE, np.array(labels))# 第四步:保存训练结果
hog.setSVMDetector(get_svm_detector(svm))
hog.save('myHogDector.bin')

test代码


import cv2
import numpy as nphog = cv2.HOGDescriptor()
hog.load('myHogDector.bin')
cap = cv2.VideoCapture(0)
while True:ok, img = cap.read()rects, wei = hog.detectMultiScale(img, winStride=(4, 4),padding=(8, 8), scale=1.05)for (x, y, w, h) in rects:cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)cv2.imshow('a', img)if cv2.waitKey(1)&0xff == 27:    # esc键break
cv2.destroyAllWindows()
代码参考:
https://github.com/PENGZhaoqing/Hog-feature/blob/master/hog.py
博客参考:
80行Python实现-HOG梯度特征提取_hog特征 python代码-CSDN博客
HOG特征 - 知乎
【计算机视觉】INRIA 行人数据集 (INRIA Person Dataset)_inria数据集-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/314036.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

00-开篇导读:学习分库分表开源框架的正确方法

1 前言 互联网高速发展带来海量的信息化数据&#xff0c;也带来更多的技术挑战。各种智能终端设备&#xff08;比如摄像头或车载设备等&#xff09;以每天千万级的数据量上报业务数据&#xff0c;电商、社交等互联网行业更不必说。这样量级的数据处理&#xff0c;已经远不是传…

Note: An Interesting Festival

An Interesting Festival 一个有趣的节日。 festival The Agricultural Feast takes place after the independence Day. 农业盛会在独立日后举行 takes place independence feast agricultural It is not a worldwide celebration. 它不是一个全球的庆典。 worldwide ce…

【模拟电路】门电路-逻辑门

一、逻辑门 二、与门 三、或门 四、非门 五、异或门 六、与非门 七、或非门 一、逻辑门 逻辑门是数字电子电路中的基本构建块&#xff0c;用于执行不同的逻辑运算。每种逻辑门都有特定的输入和输出关系&#xff0c;实现了基本的逻辑功能。以下是一些常见的逻辑门&#xff1a; …

基于深度卷积神经网络的垃圾分类识别系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文详细介绍了一基于深度卷积神经网络的垃圾分类识别系统。采用TensorFlow和Keras框架&#xff0c;通过卷积神经网络&#xff08;CNN&#xff09;进行模型训练和预测。引入迁移学习中的VGG16模型…

用html,js和layui写一个简单的点击打怪小游戏

介绍&#xff1a; 一个简单的打怪小游戏&#xff0c;点击开始游戏后&#xff0c;出现攻击按钮&#xff0c;击败怪物后可以选择继续下一关和结束游戏。 继续下一个怪兽的血量会增加5点&#xff0c;攻击按钮会随机变色。 效果图&#xff1a; html代码&#xff1a; <!DOCTYPE…

小兔鲜儿 uniapp - SKU 模块

目录 存货单位&#xff08;SKU&#xff09;​ 插件市场​ 下载 SKU 插件​ 使用 SKU 插件​ 插件类型问题​ 核心业务​ 渲染商品规格​ 打开弹窗交互​ 渲染被选中的值​ 存货单位&#xff08;SKU&#xff09;​ SKU 概念 存货单位&#xff08;Stock Keeping Unit&a…

使用docker轻量化部署snmp agent(SNMPv2访问)

文章目录 服务器环境说明单机部署&#xff08;非挂载conf文件版&#xff09;debian:buster-slim容器简介实现步骤创建Dockerfile创建SNMP配置文件 (snmpd.conf)构建Docker镜像运行Docker容器 注意补充复制容器文件到本地容器、镜像操作 单机部署&#xff08;挂载conf文件版&…

会员案例库 | 零赛云:一站式工业数字化转型解决方案提供商

1.案例应用领域及行业 能源行业、机械设备等离散制造业 2.案例描述 新奥动力是新奥集团旗下专注于微、小型燃气轮机研发及产业化的高科技创新型企业&#xff0c;是专业的分布式能源系统核心能源装备供应商和解决方案提供商。通过多年累积&#xff0c;已建立从市场到研发&…

Python+Django 构建实验室药品管理和预警系统【源码】

人生苦短&#xff0c;我用 Python。 今天给大家分享一个完整的实战案例&#xff1a;Python实现实验室药品管理和预警系统&#xff0c;文末附完整代码! 在线演示环境 项目演示地址&#xff1a;http://101.34.18.118:8002/ &#xff08;图片未压缩&#xff0c;所以加载有点慢&…

PS制作淘宝主图

PS制作淘宝主图 1.制作主图主页1.1新建800x800画板1.2填充前景色&#xff1a;altdel1.3选择圆角矩形&#xff0c;半径501.4按住ALT&#xff0c;往下投复制 2.调色 1.制作主图主页 1.1新建800x800画板 1.2填充前景色&#xff1a;altdel 1.3选择圆角矩形&#xff0c;半径50 居中对…

力扣刷题记录(21)LeetCode:121、123、188、309

目录 121. 买卖股票的最佳时机 123. 买卖股票的最佳时机 III 188. 买卖股票的最佳时机 IV 309. 买卖股票的最佳时机含冷冻期 如果某一天出售股票可以得到最大利润&#xff0c;那么股票买入的价格一定是这天之前股票的最低价格。 所以我们可以在遍历股票价格的时候不断更新股…

[嵌入式AI从0开始到入土]9_yolov5在昇腾上推理

[嵌入式AI从0开始到入土]嵌入式AI系列教程 注&#xff1a;等我摸完鱼再把链接补上 可以关注我的B站号工具人呵呵的个人空间&#xff0c;后期会考虑出视频教程&#xff0c;务必催更&#xff0c;以防我变身鸽王。 第一章 昇腾Altas 200 DK上手 第二章 下载昇腾案例并运行 第三章…