当前位置: 首页 > news >正文

OpenCV实战:用HOG+SVM从零训练一个行人检测器(附完整代码与数据集)

OpenCV实战:从零构建HOG+SVM行人检测器的工程指南

在智能监控和自动驾驶领域,行人检测一直是计算机视觉的核心任务之一。不同于传统算法原理的抽象讲解,本文将带您深入HOG特征与SVM分类器的工程实践层面,从数据集准备到模型部署,手把手构建一个可落地的检测系统。

1. 环境准备与数据集处理

1.1 开发环境配置

推荐使用Python 3.8+和OpenCV 4.5+环境,通过conda快速搭建:

conda create -n hog_svm python=3.8 conda activate hog_svm pip install opencv-python opencv-contrib-python scikit-learn matplotlib

验证安装是否成功:

import cv2 print(cv2.__version__) # 应输出4.5以上版本

1.2 INRIA数据集处理

INRIA Person数据集包含2416张正样本和1218张负样本图像,需按以下步骤预处理:

  1. 正样本裁剪:所有行人图像统一调整为64×128像素
  2. 负样本采集:从场景图中随机截取非行人区域
  3. 数据增强:通过镜像翻转增加样本多样性
import os import cv2 import numpy as np def process_pos_samples(input_dir, output_dir, target_size=(64,128)): if not os.path.exists(output_dir): os.makedirs(output_dir) for filename in os.listdir(input_dir): img = cv2.imread(os.path.join(input_dir, filename)) resized = cv2.resize(img, target_size) cv2.imwrite(os.path.join(output_dir, filename), resized) # 数据增强:水平翻转 flipped = cv2.flip(resized, 1) cv2.imwrite(os.path.join(output_dir, f"flip_{filename}"), flipped)

2. HOG特征工程实战

2.1 关键参数解析

HOG特征提取的核心参数直接影响模型性能:

参数名典型值工程意义
winSize(64,128)检测窗口大小,需匹配训练样本尺寸
blockSize(16,16)归一化块大小,影响特征鲁棒性
blockStride(8,8)块移动步长,决定特征重叠程度
cellSize(8,8)直方图计算单元,影响梯度统计精度
nbins9梯度方向分箱数,通常取9个方向

2.2 特征提取实现

使用OpenCV的HOGDescriptor进行高效计算:

def extract_hog_features(images, visualize=False): hog = cv2.HOGDescriptor( _winSize=(64,128), _blockSize=(16,16), _blockStride=(8,8), _cellSize=(8,8), _nbins=9 ) features = [] for img in images: if img.shape[:2] != (128,64): img = cv2.resize(img, (64,128)) # 转换为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 计算HOG特征 feat = hog.compute(gray) features.append(feat.flatten()) if visualize: # 可视化HOG特征 hog_vis, _ = hog.compute(gray, vis=True) cv2.imshow("HOG Visualization", hog_vis) cv2.waitKey(10) return np.array(features)

提示:在实际工程中,建议将提取的特征保存为.npy文件避免重复计算

3. SVM模型训练与调优

3.1 线性SVM实现

OpenCV提供了高效的SVM实现:

def train_svm(features, labels): svm = cv2.ml.SVM_create() svm.setType(cv2.ml.SVM_C_SVC) svm.setKernel(cv2.ml.SVM_LINEAR) svm.setC(0.01) # 正则化参数 # 转换为OpenCV需要的格式 train_data = cv2.ml.TrainData_create( features.astype(np.float32), cv2.ml.ROW_SAMPLE, labels.astype(np.int32) ) # 训练模型 svm.train(train_data) return svm

3.2 模型评估技巧

使用准确率-召回率曲线评估性能:

from sklearn.metrics import precision_recall_curve import matplotlib.pyplot as plt def evaluate_model(svm, test_features, test_labels): _, predictions = svm.predict(test_features) # 计算精确率-召回率 precisions, recalls, _ = precision_recall_curve(test_labels, predictions) plt.figure() plt.plot(recalls, precisions, linewidth=2) plt.xlabel("Recall") plt.ylabel("Precision") plt.title("Precision-Recall Curve") plt.grid(True) plt.show()

4. 模型部署与性能优化

4.1 多尺度检测实现

实际应用中需处理不同尺度的行人:

def detect_multiscale(image, hog, svm, scale_factor=1.05): detections = [] current_scale = 1.0 while True: # 缩放图像 scaled_width = int(image.shape[1] / current_scale) scaled_height = int(image.shape[0] / current_scale) if scaled_width < 64 or scaled_height < 128: break scaled_img = cv2.resize(image, (scaled_width, scaled_height)) # 滑动窗口检测 for y in range(0, scaled_img.shape[0]-128, 16): for x in range(0, scaled_img.shape[1]-64, 8): window = scaled_img[y:y+128, x:x+64] features = hog.compute(window) _, result = svm.predict(features.reshape(1,-1)) if result[0] == 1: # 正样本 orig_x = int(x * current_scale) orig_y = int(y * current_scale) orig_w = int(64 * current_scale) orig_h = int(128 * current_scale) detections.append((orig_x, orig_y, orig_w, orig_h)) current_scale *= scale_factor return detections

4.2 非极大值抑制(NMS)

解决重叠检测框问题:

def non_max_suppression(boxes, overlap_thresh=0.3): if len(boxes) == 0: return [] # 转换坐标为(x1,y1,x2,y2)格式 boxes = np.array([[x,y,x+w,y+h] for (x,y,w,h) in boxes]) pick = [] x1 = boxes[:,0] y1 = boxes[:,1] x2 = boxes[:,2] y2 = boxes[:,3] area = (x2 - x1 + 1) * (y2 - y1 + 1) idxs = np.argsort(y2) while len(idxs) > 0: last = len(idxs) - 1 i = idxs[last] pick.append(i) xx1 = np.maximum(x1[i], x1[idxs[:last]]) yy1 = np.maximum(y1[i], y1[idxs[:last]]) xx2 = np.minimum(x2[i], x2[idxs[:last]]) yy2 = np.minimum(y2[i], y2[idxs[:last]]) w = np.maximum(0, xx2 - xx1 + 1) h = np.maximum(0, yy2 - yy1 + 1) overlap = (w * h) / area[idxs[:last]] idxs = np.delete(idxs, np.concatenate(([last], np.where(overlap > overlap_thresh)[0]))) return boxes[pick].astype("int")

在真实项目中,将HOG+SVM部署到嵌入式设备时,我们发现通过调整blockStride参数可以在精度和速度之间取得平衡——当从(8,8)改为(4,4)时,检测率提升约7%,但处理速度下降40%。最终方案需要根据具体硬件性能和应用场景进行权衡。

http://www.jsqmd.com/news/754475/

相关文章:

  • 3ds Max新手必看:Gamma和LUT设置不对,你的模型导出为啥总出问题?
  • 从一颗烧掉的钽电容说起:手把手教你读懂Datasheet,避开低阻抗电路设计的那些‘坑’
  • 00华夏之光永存·(开源):黄大年茶思屋28期题目总纲
  • 为什么你的C++ DoIP客户端总在0x7F响应后静默崩溃?深度剖析UDS Negative Response解析逻辑缺陷与RAII资源泄漏链(附ASAM MCD-2D兼容补丁)
  • ARM SME指令集:矩阵运算与存储优化实战
  • 开源机器人抓取新纪元:耶鲁OpenHand如何重塑你的机器人项目
  • 2026年性价比高的WMS大对比,究竟哪家才是你的最佳之选?
  • 告别黑盒!用Qt的QWindow和WId把Windows记事本、计算器“装”进你的应用界面
  • 保姆级教程:在FPGA/嵌入式Linux上解析MIPI CSI-2 RAW图像数据流(以RAW10为例)
  • 基于GPT与向量检索构建智能技术面试模拟系统:架构、部署与实战
  • 保姆级教程:在Ubuntu 22.04上安装CUDA 12.2(含驱动分离安装与RTX 3090验证)
  • Universal Framework OS:开箱即用的开发环境操作系统设计与实践
  • WarcraftHelper 2024:魔兽争霸3终极优化完全教程
  • 宝塔搭建靶场全过程
  • Agentspec:用规范驱动智能体开发,解决LLM应用工程化难题
  • R3nzSkin国服特供版:如何在英雄联盟中安全实现皮肤个性化定制?
  • 构建自动代码执行器:从任务调度到Docker安全隔离的工程实践
  • Taotoken 的 API Key 管理与访问控制功能实践
  • 终极免费换肤方案:R3nzSkin国服零风险解锁英雄联盟全皮肤指南
  • GATK4实战:如何为多样本项目设计高效、可复现的gVCF联合分析流程?
  • Prompt Engineering——从随意提问到工程化调用
  • 为 Claude Code 配置 Taotoken 作为 AI 编程助手后端
  • 实测NRF52840低功耗电流从100uA降到1.6uA,我的SDK17外设关闭避坑清单
  • 终极HiveWE魔兽争霸III地图编辑器:从零开始的完整指南 [特殊字符]
  • 实战双核开发,用快马构建keil5下c51与stm32代码复用与混编项目框架
  • 别再纠结了!工业场景下,PREEMPT-RT与Xenomai到底怎么选?一个表格帮你搞定
  • ai辅助开发新体验:让快马智能解析并生成定制化虚拟机配置方案
  • NCMconverter终极指南:如何快速将加密NCM音频转换为通用MP3/FLAC格式
  • 避坑指南:在COMSOL或Abaqus中设置大变形时,如何正确理解并验证‘变形梯度’结果?
  • 从ls -l的第一行权限开始:手把手教你读懂Linux文件系统的‘身份证’