news 2026/5/5 2:20:58

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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%。最终方案需要根据具体硬件性能和应用场景进行权衡。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 2:20:55

Pytorch图像去噪实战(三十一):断点续训完整方案,解决训练中断、权重丢失和实验不可复现问题

Pytorch图像去噪实战(三十一):断点续训完整方案,解决训练中断、权重丢失和实验不可复现问题 一、问题场景:训练跑了18小时,服务器断了 做图像去噪模型训练时,我最怕遇到的不是 loss 不下降,而是训练中途突然中断。 真实情况里很常见: 云服务器自动重启 SSH连接断开 …

作者头像 李华
网站建设 2026/5/5 2:13:38

ai赋能java学习:快马平台辅助生成数据结构代码与智能讲解

最近在自学Java数据结构时&#xff0c;发现很多抽象概念理解起来特别费劲。比如链表的指针操作、二叉树的遍历方式&#xff0c;光看文字说明总感觉隔靴搔痒。后来尝试用InsCode(快马)平台的AI辅助功能&#xff0c;意外发现了一条高效学习路径。 智能代码生成 选择平台上的Java模…

作者头像 李华
网站建设 2026/5/5 2:11:51

告别踩坑!用Visual Studio 2022从零开发CobaltStrike BOF的保姆级教程

Visual Studio 2022实战&#xff1a;CobaltStrike BOF开发避坑指南 在红队行动和内网渗透测试中&#xff0c;CobaltStrike的Beacon Object File&#xff08;BOF&#xff09;功能已经成为扩展能力的利器。不同于传统DLL注入&#xff0c;BOF直接在内存中执行&#xff0c;无需落地…

作者头像 李华
网站建设 2026/5/5 2:10:59

32串口连接多设备出现的问题

问题现象问题表现为&#xff1a;F1主控用一个 UART 去接一个或多个步进电机控制器时&#xff0c;发送命令正常&#xff0c;但接收回包异常。如果是多个电机&#xff0c;主控 TX 广播给多个电机 RX 通常能正常工作&#xff0c;因为协议里有电机编号&#xff0c;目标电机能识别命…

作者头像 李华