OpenCV计算机视觉实战(23)------目标检测详解
0. 前言
在现代视觉系统中,从监控安防到智能驾驶,准确且高效地识别并定位图像中的目标对象是核心能力。本文在介绍经典的 HOG + SVM
行人检测、Haar
级联分类器以及自定义 HOG + SVM
分类器训练的基础上,深入探讨了非极大值抑制、ROI
加速、级联细化、硬负样本挖掘等实战优化技巧。
1. HOG + SVM 行人检测
使用 OpenCV
内置的 HOG
描述符与预训练的线性 SVM
,对图像或视频流中的行人进行实时检测。
1.1 实现过程
- 创建
HOG
描述符并加载默认行人SVM
权重 - 读取图像/视频帧
- 调用
detectMultiScale
执行滑窗检测,返回一系列候选行人矩形框 - 绘制检测结果 并显示
python
import cv2
# 功能:在摄像头或视频中实时检测行人
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
cap = cv2.VideoCapture('r2.mp4')
while True:
ret, frame = cap.read()
if not ret:
break
# 可选:调整尺寸加快检测
frame_resized = cv2.resize(frame, (860, 480))
# 多尺度检测
rects, weights = hog.detectMultiScale(
frame_resized,
winStride=(8, 8),
padding=(8, 8),
scale=1.05
)
# 绘制检测框
for (x, y, w, h) in rects:
cv2.rectangle(frame_resized, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.imshow('HOG + SVM Pedestrian Detection', frame_resized)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()

关键函数解析:
cv2.HOGDescriptor()
:创建HOG
特征提取器hog.setSVMDetector(...)
:加载预训练的行人检测SVM
权重detectMultiScale(image, winStride, padding, scale)
:滑窗+图像金字塔检测目标winStride
:滑窗步长padding
:检测窗口周围填充scale
:金字塔缩放因子
1.2 优化思路
HOG + SVM
很适合行人检测,但默认 detectMultiScale
经常返回大量重叠框。加入非极大值抑制 (Non-Maximum Suppression
, NMS
) 能显著提高精度,并减少冗余框。若检测场景单一,可先定义感兴趣区域 (Region of Interest
, ROI
) 加速检测。
python
import cv2
import numpy as np
# 功能:HOG+SVM 行人检测,加入 ROI 限定与 NMS
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
def non_max_suppression(boxes, overlapThresh=0.65):
if len(boxes) == 0:
return []
boxes = np.array(boxes)
pick = []
x1 = boxes[:,0]
y1 = boxes[:,1]
x2 = boxes[:,0] + boxes[:,2]
y2 = boxes[:,1] + boxes[:,3]
areas = (x2 - x1) * (y2 - y1)
idxs = np.argsort(y2)
while len(idxs) > 0:
i = idxs[-1]
pick.append(i)
xx1 = np.maximum(x1[i], x1[idxs[:-1]])
yy1 = np.maximum(y1[i], y1[idxs[:-1]])
xx2 = np.minimum(x2[i], x2[idxs[:-1]])
yy2 = np.minimum(y2[i], y2[idxs[:-1]])
w = np.maximum(0, xx2 - xx1)
h = np.maximum(0, yy2 - yy1)
overlap = (w * h) / areas[idxs[:-1]]
idxs = np.delete(idxs, np.concatenate(([len(idxs)-1],
np.where(overlap > overlapThresh)[0])))
return boxes[pick].astype(int)
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret: break
# 定义 ROI------只检测画面下半部分
h, w = frame.shape[:2]
roi = frame[h//3*2:h, :]
rects, weights = hog.detectMultiScale(
roi, winStride=(8,8), padding=(16,16), scale=1.05
)
# 坐标映射回原图
rects = [(x, y + 2*h//3, w_, h_) for (x,y,w_,h_) in rects]
# 应用 NMS
rects_nms = non_max_suppression(rects, 0.6)
for (x, y, w_, h_) in rects_nms:
cv2.rectangle(frame, (x,y), (x+w_, y+h_), (0,255,0), 2)
cv2.imshow('HOG+SVM with NMS', frame)
if cv2.waitKey(1) & 0xFF == 27: break
cap.release()
cv2.destroyAllWindows()
关键函数解析:
non_max_suppression(boxes, overlapThresh)
:剔除重叠度高于阈值的冗余检测框,只保留最具代表性的- 在
detectMultiScale
后先ROI
裁剪,减少无关区域计算量
2. Haar 级联分类器
使用 OpenCV
提供的 Haar
级联 XML
模型,在图像中快速检测人脸、眼睛、车辆等常见对象。
2.1 实现过程
- 加载级联分类器
XML
文件 - 读取图像并转换为灰度
- 调用
detectMultiScale
,得到一系列检测框 - 据置信度或最小/最大尺寸过滤,并绘制结果
python
import cv2
# 功能:使用 Haar 级联检测人脸
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
img = cv2.imread('10.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30)
)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imshow('Haar Cascade Face Detection', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键函数解析:
cv2.CascadeClassifier(xml_path)
:加载Haar
或LBP
级联模型detectMultiScale(image, scaleFactor, minNeighbors, minSize)
:多尺度扫描检测minNeighbors
:每个候选窗口至少需通过的相邻检测次数,越高越严格minSize
:目标最小尺寸,剔除过小噪声。
2.2 优化思路
Haar
级联检测器适合实时人脸、车牌、行人检测。通过调整 scaleFactor
、minNeighbors
,以及分阶段检测(先粗后细),可在速度与准确度之间找到平衡。
python
import cv2
# 功能:Haar 级联人脸+眼睛 检测,分级优化
face_cas = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cas = cv2.CascadeClassifier('haarcascade_eye_tree_eyeglasses.xml')
img = cv2.imread('10.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 1. 粗级人脸检测
faces = face_cas.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=3, minSize=(50,50))
for (x,y,w,h) in faces:
cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)
roi_gray = gray[y:y+h, x:x+w]
roi_color= img[y:y+h, x:x+w]
# 2. 细级眼睛检测
eyes = eye_cas.detectMultiScale(roi_gray, scaleFactor=1.1, minNeighbors=5, minSize=(15,15))
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color, (ex,ey), (ex+ew, ey+eh), (0,255,0), 1)
cv2.imshow('Haar Cascade Face & Eyes', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键函数解析:
- 两级检测:先以较小
minNeighbors
、大scaleFactor
快速定位,再在ROI
内用更严格参数细化 haarcascade_eye_tree_eyeglasses.xml
:在人脸ROI
内检测眼睛,可验证人脸准确度并应对侧脸漏检
3. 自定义分类器训练
使用自定义正/负样本,通过 HOG
提取特征并用 scikit-learn
的线性 SVM
训练一个简单的对象检测器。
3.1 实现过程
- 准备数据集:将正样本(含目标)与负样本(不含目标)分别放在
pos/
和neg/
目录 - 遍历读取图像,对每张图像计算
HOG
特征向量,并打标签 - 训练线性
SVM
,使用sklearn.svm.LinearSVC
- 保存模型
- 加载模型并在新图像上滑窗检测
python
import cv2, os
import numpy as np
from sklearn.svm import LinearSVC
from sklearn.externals import joblib
# 功能:基于自定义样本训练 HOG+SVM 检测器
def extract_hog(image):
hog = cv2.HOGDescriptor()
return hog.compute(image).flatten()
# 1. 读取正/负样本并提取特征
features, labels = [], []
for fname in os.listdir('pos/'):
img = cv2.imread(os.path.join('pos', fname), cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (64, 128))
features.append(extract_hog(img))
labels.append(1)
for fname in os.listdir('neg/'):
img = cv2.imread(os.path.join('neg', fname), cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (64, 128))
features.append(extract_hog(img))
labels.append(0)
X = np.array(features)
y = np.array(labels)
# 2. 训练 SVM
svm = LinearSVC()
svm.fit(X, y)
joblib.dump(svm, 'custom_hog_svm.pkl')
# 3. 滑窗检测示例
model = joblib.load('custom_hog_svm.pkl')
test = cv2.imread('test_scene.jpg')
gray = cv2.cvtColor(test, cv2.COLOR_BGR2GRAY)
h, w = 128, 64
for y0 in range(0, gray.shape[0]-h, 16):
for x0 in range(0, gray.shape[1]-w, 16):
window = gray[y0:y0+h, x0:x0+w]
feat = extract_hog(window).reshape(1, -1)
pred = model.predict(feat)
if pred == 1:
cv2.rectangle(test, (x0,y0), (x0+w,y0+h), (0,255,0), 2)
cv2.imshow('Custom HOG+SVM Detection', test)
cv2.waitKey(0)
cv2.destroyAllWindows()
关键函数解析
hog.compute(image)
:计算固定窗口的HOG
特征LinearSVC()
:训练一个线性支持向量机predict(feature_vector)
:对滑窗提取的特征做二分类预测joblib.dump/load()
:序列化模型,便于后续快速加载使用
小结
本文系统梳理了基于传统机器学习方法的目标检测技术,涵盖从 HOG + SVM
到 Haar
级联分类器的应用与优化,并进一步拓展至自定义分类器的训练实战。在具体实现中,介绍了滑窗、多尺度检测的基础流程,还引入了非极大值抑制、ROI
加速、级联细化检测等提升检测效率和精度的关键策略。此外,通过训练自定义 HOG + SVM
模型,读者可以灵活应对特定场景下的目标识别任务,为构建轻量、高效的视觉系统奠定坚实基础。
系列链接
OpenCV计算机视觉实战(1)------计算机视觉简介
OpenCV计算机视觉实战(2)------环境搭建与OpenCV简介
OpenCV计算机视觉实战(3)------计算机图像处理基础
OpenCV计算机视觉实战(4)------计算机视觉核心技术全解析
OpenCV计算机视觉实战(5)------图像基础操作全解析
OpenCV计算机视觉实战(6)------经典计算机视觉算法
OpenCV计算机视觉实战(7)------色彩空间详解
OpenCV计算机视觉实战(8)------图像滤波详解
OpenCV计算机视觉实战(9)------阈值化技术详解
OpenCV计算机视觉实战(10)------形态学操作详解
OpenCV计算机视觉实战(11)------边缘检测详解
OpenCV计算机视觉实战(12)------图像金字塔与特征缩放
OpenCV计算机视觉实战(13)------轮廓检测详解
OpenCV计算机视觉实战(14)------直方图均衡化
OpenCV计算机视觉实战(15)------霍夫变换详解
OpenCV计算机视觉实战(16)------图像分割技术
OpenCV计算机视觉实战(17)------特征点检测详解
OpenCV计算机视觉实战(18)------视频处理详解
OpenCV计算机视觉实战(19)------特征描述符详解
OpenCV计算机视觉实战(20)------光流法运动分析
OpenCV计算机视觉实战(21)------模板匹配详解
OpenCV计算机视觉实战(22)------图像拼接详解